要實現標題全屏居中(同時在垂直和水平方向居中),有若干種方法,包括使用彈性佈局、表格單元、絕對定位和自動外邊距等。
全屏居中
其中目前比較流行也比較容易理解的方法是使用絕對定位+偏移實現。也就是分兩步來把元素居中:
1. 第一步先把元素放在離視口左上角(座標原點)50%視口寬和50%視口高的地方;
2. 第二步把元素反向偏移其自身寬高的50%。
html,body{background: #333;height:100%; width:100%;margin:0;padding:0;}
h1 {
margin-left: -25%;
margin-top: -35px;/* h1元素邊框的高度一半 */
color: white;
width: 50%;
height: 30px;
text-align: center;
position: absolute;
left: 50%;
top: 50%;
padding: 20px 0;
border: 1px solid #666;
}
上述代碼使用絕對定位,top: 50%, left: 50%完成第一步,margin-left和margin-top完成第二步。注意標題元素寬度使用百分比,可在水平方向自適應屏幕寬度。最好設置下min-width,以免屏幕過小時,標題文本溢出。
這樣的代碼是可以工作的。但是吹毛求疵的話,代碼的性能並不好。當然在這種簡單用例下不太會被暴露出來。
性能優化
但是如果你想給這個標題添加一些動畫效果,比如上下晃動的話,那麼就很有必要優化一下代碼。
第二步完成相對自身尺寸的偏移,剛好可以使用CSS3變換中的translate(使用百分比取值時,以其邊框border box尺寸爲參照)來實現。
我們先給出代碼,然後說明爲什麼要這樣,有什麼好處和壞處。
*{margin:0;padding:0;}
html,body{background: #333;height:100%; width:100%;}
h1 {
-ms-transform: translate3d(-50%, -50%, 0);
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
color: white;
width: 50%;
text-align: center;
position: absolute;
left: 50%;
top: 50%;
}
我們首先需要了解瀏覽器的渲染過程:
- 解析DOM Tree,創建一個或多個渲染層(layer)
- 將每個層獨立地繪製進位圖(bitmap)中(計算樣式->佈局->柵格化)
- 將層作爲紋理(texture)上傳至 GPU
- 複合(composite)多個層來生成最終的屏幕圖像
- 每個層的樣式出現調整後,要重新計算樣式->重新佈局(可能沒有)->重新柵格化(可能沒有)->重新組合
使用top/left只會創建一個層,而使用translate方法將促使瀏覽器(webkit)把h1元素提取出來放在GPU單獨的渲染層中(RenderLayer),這樣有3點益處:
1. 該元素任何合成屬性(Composite Property)的變化將不會影響原有文檔,不會導致原文檔被重新佈局(relayout或reflow),所謂重新佈局就是重新計算位置和尺寸,這是前端性能的殺手。位置和角度就是典型的合成屬性。
2. 該層將由GPU(Compositor Thread)負責渲染,從而節省CPU資源,不會阻塞主線程JS代碼的執行。
3. 動畫更爲平滑,這是因爲使用translate將可以以小於像素的單位(sub-pixel)來繪製,並在幀之間加入了blur(模糊)效果。
可能帶來的負作用是額外的渲染層導致更多的線程間通信,如果過度使用,導致生成成百上千的渲染層,那反而會導致組合各層圖像的成本迅速上升成爲主要矛盾,且我們需要記住GPU也是有內存限制的。當然還有一個前提是translate方法得到了瀏覽器支持,這在移動端沒有問題。
另外使用translate的3D版本和translate 2d版本的區別在於可以強迫在聲明後就創建獨立的渲染層,這樣一旦動畫開始,無需等待。
在線實例
這裏有一個在線用例是居中標題區塊的完整實現:
http://wow.techbrood.com/fiddle/6908
還有兩個在線用例用來比較top/left和translate方法的性能(你需要學會使用Chrome DevTools):
http://wow.techbrood.com/fiddle/17737
http://wow.techbrood.com/fiddle/17739