CSS頁面佈局技術允許我們拾取網頁中的元素,並且控制它們相對正常佈局流、周邊元素、父容器或者主視口/視窗的位置。在這個模塊中將涉及更多關於頁面[佈局技術](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Layout_mode)的細節: * 浮... ...
註:全文摘自MDN-介紹CSS佈局
CSS頁面佈局技術允許我們拾取網頁中的元素,並且控制它們相對正常佈局流、周邊元素、父容器或者主視口/視窗的位置。在這個模塊中將涉及更多關於頁面佈局技術的細節:
- 浮動
- 定位
- CSS 表格
- 彈性盒子
- 網格
每種技術都有它們的用途,各有優缺點。
正常佈局流
正常佈局流是指在不對頁面進行任何佈局控制時,瀏覽器預設的HTML佈局方式。讓我們快速地看一個HTML的例子:
<p>I love my cat.</p>
<ul>
<li>Buy cat food</li>
<li>Exercise</li>
<li>Cheer up friend</li>
</ul>
<p>The end!</p>
預設情況下,瀏覽器的顯示如下:
註意,HTML元素完全按照源碼中出現的先後次序顯示——第一個段落、無序列表、第二個段落。
佈局技術會覆蓋預設的佈局行為:
position
屬性 — 正常佈局流中,預設為static
,使用其它值會引起元素不同的佈局方式,例如將元素固定到瀏覽器視口的左上角。- 浮動——應用
float
值,諸如left
能夠讓塊級元素互相併排成一行,而不是一個堆疊在另一個上面。 display
屬性——標準值block
,inline
orinline-block
會改變元素在正常佈局流中的行為方式(見 Types of CSS boxes ),而一些不常見或特殊的值允許我們使用完全不同的方式進行佈局,使用工具比如Flexbox。
浮動
浮動技術允許元素浮動到另外一個元素的左側或右側,而不是預設的一個堆疊另一個。float 的主要用途是佈置出多個列並且浮動文字以環繞圖片。下麵我們快速瀏覽一下 float
屬性並通過一個例子來說明。
float 屬性有四個可能的值:
left
— 將元素浮動到左側。right
— 將元素浮動到右側。none
— 預設值, 不浮動。- inherit — 繼承父元素的浮動屬性。
簡單HTML示例
下麵展示瞭如何用浮動來創建一個簡單的兩列佈局。首先看一下HTML:
<h1>2 column layout example</h1>
<div>
<h2>First column</h2>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p>
</div>
<div>
<h2>Second column</h2>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut.</p>
</div>
代碼中有一個一級標題和兩個簡單的 <div>
元素。每個又各自包含一個二級標題和一個段落。預設情況下。HTML內容自上而下顯示:
整列浮動
下麵讓我們將兩個 <div>
元素排成一行。下麵的代碼可以實現這個效果. 註意這兩個 <div>
一個浮動值為 left
,另外一個浮動為 right
。這意味著它們其中一個往左靠,另外一個往右靠。給這兩個元素分別設置 width
值,使得它們能夠在同一行放下來,並且設置一個水平的間距(總寬度不要大於100!).
div:nth-of-type(1) {
width: 48%;
float: left;
}
div:nth-of-type(2) {
width: 48%;
float: right;
}
修改過的代碼如下:
定位技術
定位技術(position)允許我們將一個元素從它在頁面的原始位置準確地移動到另外一個位置。
有四種主要的定位類型需要我們瞭解:
- 靜態定位(Static positioning) 是每個元素預設的屬性——它表示“將元素放在文檔佈局流的預設位置——沒有什麼特殊的地方”。
- 相對定位(Relative positioning) 允許我們相對元素在正常的文檔流中的位置移動它——包括將兩個元素疊放在頁面上。這對於微調和精準設計(design pinpointing)非常有用。
- 絕對定位(Absolute positioning) 將元素完全從頁面的正常佈局流中移出,類似將它單獨放在一個圖層中. 我們可以將元素相對於頁面的
<html>
元素邊緣固定,或者相對於離元素最近的被定位的祖先元素(ancestor element)。絕對定位在創建複雜佈局效果時非常有用,例如通過標簽顯示和隱藏的內容面板或者通過按鈕控制滑動到屏幕中的信息面板. - 固定定位(Fixed positioning) 與絕對定位非常類似,除了它是將一個元素相對瀏覽器視口固定,而不是相對另外一個元素。 在創建類似頁面滾動總是處於頁面上方的導航菜單時非常有用。
簡單定位示例
我們將展示一些示例代碼來熟悉這些佈局技術. 這些示例代碼都作用在相同的HTML上:
<h1>Positioning</h1>
<p>I am a basic block level element.</p>
<p class="positioned">I am a basic block level element.</p>
<p>I am a basic block level element.</p>
該HTML將使用以下CSS預設樣式:
body {
width: 500px;
margin: 0 auto;
}
p {
background: aqua;
border: 3px solid blue;
padding: 10px;
margin: 10px;
}
span {
background: red;
border: 1px solid black;
}
渲染效果如下:
相對定位
相對定位通常用來對佈局進行微調,比如將一個圖標往下調一點,以便放置文字. 我們可以通過下麵的規則添加相對定位來實現效果:
.positioned {
position: relative;
background: yellow;
top: 30px;
left: 30px;
}
這裡我們給中間段落一個position``relative
值——這屬性本身不做任何事情,所以我們還添加了top
和left
屬性。這些可以將受影響的元素向下向右移——這可能看起來和你所期待的相反,但你需要把它看成是左邊和頂部的元素被“推開”一定距離,這就導致了它的向下向右移動。
添加此代碼將給出以下結果:
絕對定位
絕對定位用於將元素移動到web頁面的任何位置,以創建複雜的佈局。有趣的是,它經常被用於與相對定位和浮動的協同工作。
回到我們最初的非定位示例,我們可以添加以下的CSS規則來實現絕對定位:
.positioned {
position: absolute;
background: yellow;
top: 30px;
left: 30px;
}
這裡我們給我們的中間段一個position
的 absolute
值,並且和前面一樣加上 top
和left
屬性。但是,添加此代碼將給出以下結果:
這和之前截然不同!定位元素現在已經與頁面佈局的其餘部分完全分離,並位於頁面的頂部。其他兩段現在靠在一起,好像之前那個中間段落不存在一樣。top
和left
屬性對絕對位置元素的影響不同於相對位置元素。在這種情況下,他們沒有指定元素相對於原始位置的移動程度。相反,它們指定元素應該從頁面邊界的頂部和左邊的距離(確切地說,是 <html>
元素的距離)。
我們現在暫時不討論固定定位( fixed positioning )——它基本上以相同的方式工作,除了它仍然固定在瀏覽器視窗的邊緣,而不是它定位的父節點的邊緣。
CSS 表格
HTML表格對於顯示表格數據是很好的,但是很多年前——在瀏覽器中支持基本的CSS之前——web開發人員過去也常常使用表格來完成整個網頁佈局——將它們的頁眉、頁腳、不同的列等等放在不同的表行和列中。這在當時是有效的,但它有很多問題——表佈局是不靈活的,非常重的標記,難以調試和語義上的錯誤(比如,屏幕閱讀器用戶在導航表佈局方面有問題)。
CSS表格的存在是為了讓您能夠像表格一樣佈局元素,而不需要上面描述的任何問題——這聽起來可能有些奇怪,您應該使用表格元素作為表格數據,但有時這可能是有用的。例如,您可能想要列出一個表單,其中有標簽和文本輸入;這可能很棘手,但是CSS表使其變得容易。
讓我們來看一個例子。首先,創建HTML表單的一些簡單標記。每個輸入元素都有一個標簽,我們還在一個段落中包含了一個標題。為了進行佈局,每個標簽/輸入對都封裝在<div>
中。
<form>
<p>First of all, tell us your name and age.</p>
<div>
<label for="fname">First name:</label>
<input type="text" id="fname">
</div>
<div>
<label for="lname">Last name:</label>
<input type="text" id="lname">
</div>
<div>
<label for="age">Age:</label>
<input type="text" id="age">
</div>
</form>
現在,我們例子中的CSS。除了使用 display
屬性外,大多數CSS都是相當普通的。 <form>
, <div>
, <label>
和<input>
被告知要分別顯示表、表行和表單元——基本上,它們會像HTML表格標記一樣,導致標簽和輸入在預設情況下排列整齊。我們所要做的就是添加一些大小、邊緣等等,讓一切看起來都好一點,我們就完成了。
你會註意到標題段落已經給出了 display: table-caption;
——這使得它看起來就像一個表格<caption>
——和caption-side: bottom;
讓標題在表格的底部下進行設計,即使標記是在源的輸入之前。這就能讓你有一點靈活的彈性。
html {
font-family: sans-serif;
}
form {
display: table;
margin: 0 auto;
}
form div {
display: table-row;
}
form label, form input {
display: table-cell;
margin-bottom: 10px;
}
form label {
width: 200px;
padding-right: 5%;
text-align: right;
}
form input {
width: 300px;
}
form p {
display: table-caption;
caption-side: bottom;
width: 300px;
color: #999;
font-style: italic;
}
結果如下:
柔性盒子
CSS是一種功能強大的語言,它可以做很多事情,但它卻在佈局上有所下降。傳統的老式佈局方法,如float
和positioning
工作,但有時它們會感覺比他們需要的更複雜、更靈活、更有彈性。例如,如果你想要:
- 垂直中心盒子的內容(不僅僅是文本;
line-height
將會失效)。 - 製作幾列有相同的高度包含不同數量內容的列,不使用固定的高度,或用背景圖像偽裝。
- 在一行中創建幾個盒子,占用相同數量的可用空間,不管有多少個,並且如果它們有內邊距,外邊距等就應用它。
上面的例子幾乎不可能通過常規的CSS實現——柔性盒子(或flexbox)是為了讓這些東西更容易實現而被髮明的。
讓我們來看一個例子;首先,一些簡單的HTML:
<section>
<div>This is a box</div>
<div>This is a box</div>
<div>This is a box</div>
</section>
<button class="create">Create box</button>
<button class="reset">Reset demo</button>
這裡我們有一個<section>
元素,裡面有三個<div>
,再加上幾個按鈕來創建一個新盒子,和重新設置demo。預設情況下,子元素不會被佈局或改變大小,使用傳統的方法,我們必須仔細地對每個元素設置大小,允許寬度、外邊距、邊框和內邊距,如果我們添加了另一個子元素,我們就必須完全改變所有的值。
使用Flexbox替代它:
html {
font-family: sans-serif;
}
section {
width: 93%;
height: 240px;
margin: 20px auto;
background: purple;
display: flex;
}
div {
color: white;
background: orange;
flex: 1;
margin-right: 10px;
text-shadow: 1px 1px 1px black;
}
div:last-child {
margin-right: 0;
}
section, div {
border: 5px solid rgba(0,0,0,0.85);
padding: 10px;
}
這個CSS的兩行非常有趣:
display: flex;
告訴<section>
元素的子元素作為flexible boxes——預設情況下,它們都將展開以填充父類的可用高度,不管它是什麼,並將其列出來——有足夠的寬度來包裝他們的內容。flex: 1;
告訴每個<div>
元素,在行中獲得相同數量的空間,不管有多少。
為了進一步說明這是多麼的神奇,我們還將添加一些JavaScript,以便您可以通過按下_Create box_按鈕來添加進一步的子 <div>
。
var section = document.querySelector('section');
var createBtn = document.querySelector('.create');
var resetBtn = document.querySelector('.reset');
function createBox() {
var box = document.createElement('div');
box.textContent = 'This is a box';
section.appendChild(box);
}
createBtn.onclick = createBox;
resetBtn.onclick = function() {
while (section.firstChild) {
section.removeChild(section.firstChild);
}
createBox();
createBox();
createBox();
}
這是一個例子——多試試見證Flexbox作為一個佈局工具的強大。
網格佈局
這裡提到的最具實驗性的特性是CSS網格,它在瀏覽器中還沒有得到廣泛的支持。Web頁面通常使用網格系統佈局,與列印媒體相同,這裡的想法是通過定義一個網格來簡化這個過程,然後定義內容的哪些部分位於網格的每個區域。
目前的CSS網格在任何地方都還沒有得到真正的支持(除了Firefox和Chrome的實驗性版本)。
IE和Edge支持一種更舊的、過時的技術。這是我們將來可以期待的!
註意:為了更好地瞭解當前的網格框架和其他正在使用的技術,以及即將到來的原生CSS網格規範,請參閱我們的 Grids 文章。
【end】