CSS入門指南-4:頁面佈局

這是《CSS設計指南》的讀書筆記,用於加深學習效果。css

display 屬性

display是 CSS 中最重要的用於控制佈局的屬性。每一個元素都有一個默認的 display 值。對於大多數元素它們的默認值一般是 block 或 inline 。一個 block 元素一般被叫作塊級元素。一個 inline 元素一般被叫作行內元素。html

block

div 是一個標準的塊級元素。一個塊級元素會新開始一行而且儘量撐滿容器。其餘經常使用的塊級元素包括 pform 和HTML5中的新元素: headerfootersection 等等。web

inline

img 是一個標準的行內元素。你能夠把兩個 <img> 標籤寫在兩行,但這並不影響圖片再瀏覽器中的顯示效果,它們會並列出如今一行上。並且標籤直接的空白(標記中的兩個標籤雖然分別位於兩行,但這並不影響圖片在瀏覽器中顯示時的效果。圖片是行內元素,因此它們顯示的時候就會並列出如今一行上。並且,標籤之間的空白(包括製表、回車和空格)都會被瀏覽器忽略。瀏覽器

a 元素是最經常使用的行內元素,它能夠被用做連接。app

none

另外一個經常使用的 display 值是 none。一些特殊元素的默認 display 值是它,例如script。display:none 一般被 JavaScript 用來在不刪除元素的狀況下隱藏或顯示元素。
把display設置爲 none,該元素及全部包含在其中的元素,都不會在頁面中顯示。它們原來佔據的空間也會被回收。框架

相對的屬性是 visibility,這個屬性經常使用的值是 visible(默認)和 hidden。把元素的 visibility 設定爲 hidden,元素會隱藏,但它佔據的空間仍然存在。ide

其餘 display 值

還有不少的更有意思的 display 值,幾乎全部HTML元素的display屬性值要麼爲block,要麼爲inline。最明顯的一個例外是table元素,它有本身特殊的display屬性值。這裏有一份詳細的列表佈局

塊級元素(好比標題和段落)會相互堆疊在一塊兒沿頁面向下排列,每一個元素分別佔一行。而行內元素(好比連接和圖片)則會相互並列,只有在空間不足以並列的狀況下才會折到下一行顯示 。post

塊級元素和行內元素是能夠互相轉化的:學習

/*默認爲塊級元素*/
p {display: inline;}
/*默認爲行內元素*/
a {display: block;}複製代碼

屬性了 display 屬性以後,咱們來看下頁面佈局:

佈局的基本概念

多欄佈局有三種基本的實現方案:固定寬度流動彈性

  • 固定寬度佈局的大小不會隨用戶調整瀏覽器窗口大小而變化,通常是900到1100像素寬。其中960像素是最多見的,由於這個寬度適合全部現代顯示器,並且可以被1六、十二、十、八、六、五、4和3整除,不只容易計算等寬分欄的數量,並且計算結果也能獲得沒有小數的像素數。

  • 流動佈局的大小會隨用戶調整瀏覽器窗口大小而變化。這種佈局可以更好地適應大屏幕,但同時也意味着放棄對頁面某些方面的控制,好比隨着頁面寬度變化,文本行的長度和頁面元素之間的位置關係均可能變化。Amazon.com的頁面採用的就是流動中欄佈局,在各欄寬度加大時經過爲內容元素周圍添加空白來保持內容居中,並且如今的導航條會在佈局變窄到某個寬度時收縮進一個下拉菜單中,從而爲內容騰出空間。

  • 彈性佈局與流動佈局相似,在瀏覽器窗口變寬時,不只佈局變寬,並且全部內容元素的大小也會變化,讓人產生一種全部東西都變大了的感受。

佈局的高度

多數狀況下,佈局中結構化元素(乃至任何元素)的高度是沒必要設定的。事實上,我甚至想告訴你根本不該該給元素設定高度。除非你確實須要這樣作,好比在頁面中創造一個絕對定位的元素。

爲何正常狀況下都應該保持元素height屬性的默認值auto不變呢?很簡單,只有這樣元素才能隨本身包含內容的增長而在垂直方向上擴展。這樣擴展的元素會把下方的元素向下推,而佈局也能隨着內容數量的增減而垂直伸縮。假如你明確設定了元素的高度,那麼超出的內容要麼被剪掉,要麼會跑到容器以外——取決於元素overflow屬性的設定。

佈局的寬度

與高度不一樣,咱們須要更精細地控制佈局寬度,以便隨着瀏覽器窗口寬度的合理變化,佈局可以做出適當的調整,確保文本行不會過長或太短。若是隨意給元素添加內邊距、邊框,或者元素自己過大,致使浮動元素的寬度超過包含元素的佈局寬度,那浮動元素就可能「躲」到其餘元素下方。應該讓這些內容元素自動擴展到填滿欄的寬度。(這是塊級元素的默認行爲)

三欄-固定寬度佈局

咱們先從一個簡單的居中的單欄佈局開始吧。看下面 HTML 代碼,主要標記的 ID 是 wrapper:

<div id="wrapper">
    <article>
        <h1>Single-Column Layout</h1>
        <p>這是第一段</p>
        <h2>This is a Second-Level Heading</h2>
        <p>這是第二段</p>
    </article>
</div>複製代碼

佈局相關 css 以下:

#wrapper {
    width:960px; margin:0 auto; border:1px solid;
}
article {
    background:#ffed53;    
}複製代碼

效果圖
效果圖

如圖所示,經過給外包裝設定寬度值,並將其水平外邊距設定爲 auto,這個單欄佈局在頁面上居中了。隨着向裏添加內容,這一欄的高度會相應增長。外包裝中的article元素本質上就是一個沒有寬度的塊級盒子(關於「沒有寬度的盒子」,請參見3.2節),它水平擴展填滿了外包裝。

下面,咱們再向外包裝裏添加一個導航元素,讓它做爲第二欄。

HTML 代碼以下:

<div id="wrapper">
    <nav>
        <ul>
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
            <li><a href="#">Link 3</a></li>
        </ul>
    </nav>
    <article>
        <h1>Single-Column Layout</h1>
        <p>這是第一段</p>
        <h2>This is a Second-Level Heading</h2>
        <p>這是第二段.</p>
    </article>
</div>複製代碼

這裏咱們將兩欄都添加float: left,以讓它們並排顯示。

#wrapper {
    width:960px; 
    margin:0 auto; 
    border:1px solid; 
    overflow:hidden;
}
nav {
    width:150px;
    float:left; /*浮動*/
    background:#dcd9c0;
    }
nav li {
    /*去掉列表項目符號*/
    list-style-type:none;
    }
article {
    width:810px;
    float:left; /*浮動*/
    background:#ffed53;    
    }複製代碼

效果圖
效果圖

這裏咱們把兩欄的總寬度設定爲外包裝的寬度(150+810=960),並浮動它們,就能夠創造出並肩排列的兩欄來。每一欄的長度取決於內容多少。

接下來咱們添加第三欄。

<div id="wrapper">
    <nav>
        <ul>
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
            <li><a href="#">Link 3</a></li>
        </ul>
    </nav>
    <article>
        <h1>Single-Column Layout</h1>
        <p>這是第一段</p>
        <h2>This is a Second-Level Heading</h2>
        <p>這是第二段.</p>
    </article>
    <aside>
        <h3>This is the Sidebar</h3>
        <p>這是側邊欄.</p>
    </aside>
</div>複製代碼

接下來咱們調整一下 article 這一欄的寬度,爲第三欄騰出空間

#wrapper {
    width:960px; margin:0 auto; border:1px solid; overflow:hidden;
}
nav {
    width:150px;
    float:left;
    background:#dcd9c0;
}
article {
    width:600px;
    float:left;
    background:#ffed53;    
}
aside {
    width:210px;
    float:left;
    background:#3f7ccf;
}複製代碼

三欄的示意圖
三欄的示意圖

如圖所示,經過把三個浮動容器的總寬度設定爲剛好等於外包裝的寬度(150+600+210=960),就有了三欄佈局的框架。

如今咱們再添加一個頁眉和頁腳:

<div id="wrapper">
    <header>
        <h1>A Fixed-Width Layout</h1>
    </header>
    <nav>
        <ul>
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
            <li><a href="#">Link 3</a></li>
        </ul>
    </nav>
    <article>
        <h1>Single-Column Layout</h1>
        <p>這是第一段</p>
        <h2>This is a Second-Level Heading</h2>
        <p>這是第二段.</p>
    </article>
    <aside>
        <h3>This is the Sidebar</h3>
        <p>這是側邊欄.</p>
    </aside>
       <footer>
        <p>This is the footer. Phasellus pretium gravida interdum. Nam interdum posuere tempus. Ut commodo laoreet dolor, non hendrerit mi dictum vitae. Nam nec egestas libero.</p>
    </footer>
</div>複製代碼

爲了讓頁腳在最下一欄不浮動到 aside 後邊,咱們爲頁腳應用clear:both,以組織它向上移動。
css 樣式以下:

* {margin:0; padding:0;} 
#wrapper {
    width:960px;
    margin:0 auto;
    border:1px solid;
} 
header {
    background:#f00;
} 
nav {
    width:150px;
    float:left;
    background:#dcd9c0;
} 
nav li {
    list-style-type:none;
} 
article {
    width:600px;
    float:left;
    background:#ffed53;
}
aside {
    width:210px;
    float:left;
    background:#3f7ccf;
} 
footer {
    clear:both;
    background:#000;
}複製代碼

如今效果如圖:

三欄+頁眉+頁腳的效果圖
三欄+頁眉+頁腳的效果圖

如今各欄太擁擠,每欄的高度也都由文本內容決定,咱們如今修改一下,爲內容間加上空白。

爲欄設定內邊距和邊距

爲了讓內容與欄邊界空開距離,爲欄添加水平外邊距和內邊距,但這樣會致使佈局寬度增大,進而浮動欄下滑。
好比,咱們給 article 增長內邊距:

article {
    width: 600px;
    float: left;
    background: #ffed53;
    padding: 10px 20px;
}複製代碼

效果如圖:

article 增長內邊距後的效果圖
article 增長內邊距後的效果圖

因爲增長了內邊距致使article的總寬度增長,致使右邊的欄不能再與前兩排並列在一塊兒。有三種方法來預防改問題發生:

  • 從設定的元素寬度中減去添加的水平外邊距、邊框和內邊距的寬度和。
  • 在容器內部的元素上添加內邊距或外邊距。
  • 使用CSS3的box-sizing屬性切換盒子縮放方式,好比section {box-sizing:border-box;} 。 應用box-sizing屬性後,給section添加邊框和內邊距都不會增大盒子,相反會致使內容變窄。

重設寬度以抵消內邊距和邊框

一個代代相傳的解決方案是經過數學計算。CSS開發者須要用比他們實際想要的寬度小一點的寬度,須要減去內邊距和邊框的寬度。好比咱們給600像素寬的中間欄增長了20像素的內邊距,爲了抵消增長的內邊距,能夠把欄減小40像素而設定爲560像素。值得慶幸地是你不須要再這麼作了...

給容器內部元素應用內邊距和邊框

把外邊距和內邊距應用到內容元素上確實有效,不過這樣的前提是這些元素沒有明確的設定寬度,這樣內容纔會隨內外邊距的增長而縮小。
與其爲容器中的元素添加外邊距,不如在欄中再添加一個沒有寬度的div,讓它包含全部內容元素,而後再給這個div應用邊框和內邊距。如此一來,只要爲內部div設定一次樣式,就能夠把讓全部內容元素與欄邊界保持一致的距離。並且,未來再須要調整時也會很方便。任何新增內容元素的寬度都由這個內部div決定。

下面咱們用這種方法修復上面第三欄浮動到下邊的問題。

<article>
    <div class="inner">
    <!-- 這裏是各類內容 -->
    </div>
</article>複製代碼

接下來,咱們不只要給內部 div 應用內邊距,還要給她應用外邊距和邊框。

/*更新 css*/
article {
    width:600px;
    float:left;
    background:#ffed53;
}
article .inner {
    margin:10px; 
    border:2px solid red;
    padding:20px; 
}複製代碼

效果如圖:

給容器內部元素應用內邊距和邊框的示例圖
給容器內部元素應用內邊距和邊框的示例圖

以上措施使佈局有了明顯改觀。就這麼簡單的幾下,佈局就顯得更專業了。處理欄及其內部div的關鍵在於,浮動欄並設定欄寬,但不給任何內容元素設定寬度。要讓內容元素擴展以填充它們的父元素——內部div。這樣,只要簡單地設定內部div的外邊距和內邊距,就可讓它們以及它們包含的內容與欄邊界保持必定距離。

使用 box-sizing:border-box

人們慢慢的意識到傳統的盒子模型不直接,因此他們新增了一個叫作 box-sizing 的CSS屬性。當你設置一個元素爲 box-sizing: border-box; 時,此元素的內邊距和邊框再也不會增長它的寬度。這裏有一個與前一頁相同的例子,惟一的區別是兩個元素都設置了 box-sizing: border-box;

nav {
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:150px;
    float:left;
    background:#dcd9c0;
    padding:10px 10px;
    }
article {
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:600px;
    float:left;
    background:#ffed53;    
    padding:10px 20px;
}
aside {
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;
    width:210px;
    float:left;
    background:#3f7ccf;
    padding:10px 10px;
}複製代碼

使用 box-sizing: border-box; 的效果圖
使用 box-sizing: border-box; 的效果圖

這是目前爲止最好的解決方法了,那最簡單有效的方法就是在 css 裏添加這樣一條規則:

* {
    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    box-sizing:border-box;        
    }複製代碼

三欄-中欄流動佈局

中欄流動佈局的目的是在屏幕變窄時,中欄變窄,左欄和右欄寬度不變。
這裏咱們使用負外邊距實現。

用負外邊距實現

實現三欄佈局且讓中欄內容區流動(不固定)的核心問題是處理右欄的定位,並在中欄內容區大小改變時控制右欄與佈局的關係。

這裏咱們使用Ryan Brill給出的控制兩個外包裝容器的外邊距的解決方案。其中一個外包裝包圍三欄,另外一個外保障包圍左欄和中欄。

html代碼示例以下:

<div id="main_wrapper">
    <header>
        <!-- 頁眉-->
    </header>
    <div id="threecolwrap">/*三欄外包裝(包圍所有三欄)*/
        <div id="twocolwrap">/*兩欄外包裝(包圍左欄和中欄)*/ /*左欄*/
            <nav>
                <!-- 導航 -->
            </nav> /*中欄*/
            <article>
                <!-- 區塊 -->
            </article>
        </div>/*結束兩欄外包裝(twocolwrap)*/ /*右欄*/
        <aside>
            <!-- 側欄 -->
        </aside>
    </div>/*結束三欄外包裝(threecolwrap)*/
    <footer>
        <!-- 頁腳 -->
    </footer>
</div>複製代碼

css規則以下:

* {
    margin: 0;
    padding: 0;
}

body {
    font: 1em helvetica, arial, sans-serif;
}

div#main_wrapper {
    min-width: 600px;
    max-width: 1100px;
    /*超過最大寬度時,居中佈局*/
    margin: 0 auto;
    /*背景圖片默認從左上角開始拼接*/
    background: url(images/bg_tile_150pxw.png) repeat-y #eee;
}

header {
    padding: 5px 10px;
    background: #3f7ccf;
}

div#threecolwrap {
    /*浮動強制它包圍浮動的欄*/
    float: left;
    width: 100%;
    /*背景圖片右對齊*/
    background: url(images/bg_tile_210pxw.png) top right repeat-y;
}

div#twocolwrap {
    /*浮動強制它包圍浮動的欄*/
    float: left;
    width: 100%;
    /*把右欄拉到區塊外邊距騰出的位置上*/
    margin-right: -210px;
}

nav {
    float: left;
    width: 150px;
    background: #f00;
    padding: 20px 0;
}

/*讓子元素與欄邊界保持必定距離*/

nav>* {
    margin: 0 10px;
}

article {
    width: auto;
    margin-left: 150px;
    /*在流動居中的欄右側騰出空間*/
    margin-right: 210px;
    background: #eee;
    padding: 20px 0;
}

/*讓子元素與欄邊界保持必定距離*/ 
article>* {
    margin: 0 20px;
}

aside {
    float: left;
    width: 210px;
    background: #ffed53;
    padding: 20px 0;
}

/*讓子元素與欄邊界保持必定距離*/ 
aside>* {
    margin: 0 10px;
}

footer {
    clear: both;
    width: 100%;
    text-align: center;
    background: #000;
}複製代碼

寬屏效果
寬屏效果

窄屏效果
窄屏效果

基本原理:上面兩幅圖展現了流動中欄佈局。三欄中的右欄是210像素寬。爲了給右欄騰出空間,中欄article元素有一個210像素的右外邊距。包圍左欄和中欄的兩欄外包裝上210像素的負右外邊距,會把右欄拉回article元素右外邊距(在兩欄外包裝內部右側)創造的空間內。中欄aticle元素的寬度是auto,所以它仍然會力求佔據浮動左欄剩餘的全部空間。但是,一方面它本身的右外邊距在兩欄外包裝內爲右欄騰出了空間,另外一方面兩欄外包裝的負右外邊距又把右欄拉到了該空間內。

百分比寬度

上面的例子中,咱們用到了百分比寬度,百分比是一種相對於包含塊的計量單位。你還能同時使用 min-width 和 max-width 來限制最大或最小寬度!

你能夠用百分比作佈局,可是這須要更多的工做。若是咱們上邊的例子中 nav 用百分比寬度作佈局,當窗口寬度很窄時 nav 的內容會以一種不太友好的方式被包裹起來。

inline-block 佈局

上面的例子咱們實現多欄並列的方式是使用float,不過咱們也可使用inline-block。下邊是咱們把 float 替換爲inline-block 的例子。

nav {
    width:150px;
    display: inline-block;
    vertical-align: top;
    background:#dcd9c0;
    }
article {
    word-spacing:0;
    width:600px;
    display: inline-block;
    vertical-align: top;
    background:#ffed53;    
    }
aside {
    word-spacing:0;
    width:210px;
    display: inline-block;
    vertical-align: top;
    background:#3f7ccf;
    }複製代碼

使用inline-block,有一些事情須要你牢記:

  • vertical-align 屬性會影響到 inline-block 元素,你可能會把它的值設置爲 top 。
  • 你須要設置每一列的寬度
  • 若是HTML源代碼中元素之間有空格,那麼列與列之間會產生空隙

特別是第三條,若是咱們不作任何修改,兩個 block 之間會存在空格,像這樣:

列與列之間有空格
列與列之間有空格

由於列與列之間產生了空格,因此 aside 跑到了下邊。這裏最簡單的解決辦法是:

<nav>
導航
</nav><article>
內容
</article><aside>
第三欄
</aside>複製代碼

其餘解決方案能夠參考這篇文章 Fighting the Space Between Inline Block Elements

其餘佈局方式

初次以外,css 還提供了 columnflexbox等佈局方式,這些之後有機會再介紹吧。

總結

這篇文章咱們介紹了用浮動的有寬度的元素來建立多欄佈局、如何讓固定佈局在頁面上居中以及讓它們在必定範圍內能夠伸縮。同時也瞭解瞭如何使用內部div在浮動元素中生成間距,而又不會改變佈局的總寬度。

參考連接


最後,感謝女友支持。

歡迎關注(April_Louisa) 請我喝芬達
歡迎關注
歡迎關注
請我喝芬達
請我喝芬達
相關文章
相關標籤/搜索