為什麼 CSS 3 要實現垂直居中那麼的難?

這個問題問的重點不是想知道如何居中。。請好心人不要再修改問題了。。

問題是想問。明明用一句align可以解決,為什麼他不讓?為什麼要寫N行?那個坑爹的組織怎麼想的?

當然強烈歡迎順便討論各種居中簡便牛逼方法。。。


本問題主要問的是「為什麼這麼難」,我來說下我的理解。

1. CSS 設計初期相關需求不足

最主要的布局模型(inline/block)剛誕生時,對此需求不足。CSS 最開始針對的是 web文檔,其中整體布局中垂直方向居中的需求不足,所以根本就專門沒有設計用來實現這個需求的語法。

2. 基於 CSS 2 布局模型來制定垂直居中規則有困難

因為已有的樣式原語(屬性、值)並非專門用於布局的垂直居中,那麼在尚未提供明確語義規約(比如明確使用 display: flex/grid)的場景下,如果提供一個用於在各種布局模型下垂直居中的語法(或者說把 vertical-align: middle 的適用條件放開),會涉及非常複雜的問題。比如:

  • 同一個容器內有浮動、有相對定位、有流內內容,垂直居中如何界定中線?
  • 每個元素自身又如何對齊?如果一個元素既浮動又垂直居中要怎麼定位?要不要觸發 BFC?要不要創建包含塊?
  • 把一個底下的元素居中了縮小了容器高度,中線變了,前面的是不是又要重新計算?到底先算哪個?

即便定義了一大堆規則,還是可能使得原來的布局規則發生歧義或是不兼容的情況,然後瀏覽器實現的時候又因為各種沒考慮到的問題造成各種差異,那麼這個時候開發者只會加班到更晚。總的來說,在沒有明確布局原語情況下貿然增加這個規則,不管對規範本身還是瀏覽器實現,都可能是天坑。那麼用已有的方式來 hack,雖然麻煩,但至少在不同瀏覽器下的一致性還能夠接受。

3. Web 規範推進落地相對緩慢

開放的規則,一步走錯就可能影響大量開發者,規則制定者不能一拍腦殼決定「這個功能快 tm 加上」。所以 W3C 有一系列規則來保障產出的正式版規範經得起推敲。流程是惱人的,但是沒有流程更加無法想像會亂成什麼樣子。

另外從規範制定相對完備、到最新瀏覽器實現、再到老舊瀏覽器市場份額慢慢衰減,這個過程又非常漫長。Flex / grid 布局就是我上面里提到的新增的「明確的布局語義」,相當於「重新定義了布局」,那麼在考慮了「新」需求以後,垂直居中就變得輕而易舉了。

***

最後,關於實現的方法,CSS-Tricks 上幾年前就已經有了完整的指南,可以參考一下。


對需要水平垂直居中的元素寫css:

position : absolute;
top : 50%;
left : 50%;
transform : translate(-50%,-50%);

flex:

對父級元素寫css:

單行居中:

display : flex;
justify-content : center;
align-items : center;

多行垂直居中:

display : flex;
justify-content : center;
flex-wrap : wrap/wrap-reverse;
align-items : center;

grid:

為什麼不是一行代碼?因為CSS設計的初衷是布局, 若你自己從系統的布局開始設計的時候, 你就會發現, 單獨設計一條垂直居中的語法並不是那麼優雅的, 因此, 垂直居中可以看作是業務能力拓展, 使用者可以自行封裝調用. 就好像規範是散裝的薯條雞翅漢堡, 而垂直居中就是各種套餐.


其實現在的CSS規範中已經有了你所說的一個屬性實現垂直居中的屬性。看看 CSS Box Alignment Module Level 3

W3C是一個致力於讓規範更完善的組織,如果你覺得哪些不好,希望有哪些新特性,建議你直接向這個組織提交你想要的東西,或者參與。在萬能的知乎上噴是沒有任何意義的。


我是這麼理解這個問題的,最開始的web頁面就是文檔流的形式,是不關心「頁面高度」這個概念的,這一點不像別的排版工具有「頁」的概念,web頁面它更像一卷寫滿字的廁紙,想多看一點就拉出來一點:)你會關心一卷廁紙的長度么? 所以從這個角度來講,垂直居中是一個很無理的需求。當然需求是會變化的,如今的web瀏覽器已經不像當年那麼羸弱了,web app的興起使垂直居中變成了一個強需求,但舊的傳統web頁面仍然是遵從「文檔流」的邏輯的,你不可能不兼容,所以實現這個需求困難完全是歷史原因導致的。


CSS3垂直居中已經不難了,flexbox已經提供了完美解法。

CSS揭秘

How Flexbox Works

為什麼之前難,因為沒有CSS3,沒有Flexbox。

不能再CSS2里做一個更好用的vertical-align嗎,明白為什麼是那樣很重要嗎?


這個問題下面怎麼全都是這麼麻煩的答案啊(不是答非所問,就是超級麻煩的方法),我看完忍不住怒答了。雖然DIV垂直居中一直是非常頭疼的問題,但那是在以前(這都什麼年代了)。曾經我們還要用 「絕對定位+top:50%+margin-top:-(div height/2)px」 這樣的方法,可現在我們有CSS3新特性了呀,實現起來很簡單啊!

答案就是:calc() ,只要一句 「margin-top:
calc( (100vh - 360px)/2 )」 就解決了,這裡的360px指代元素的高度值。

關於這個參數的使用,我曾經在知乎問題中有提到過:CSS如何實現這種背景效果? - 坑晨的回答 - 知乎 於是這次我來詳細的展開說一下(因為這個參數很強大,要吃透還是得研究研究的)。

什麼是calc()?

學習calc()之前,我們有必要先知道calc()是什麼?calc()從字面我們可以把他理解為一個函數function,其實calc是英文單詞 calculate(計算) 的縮寫,是css3的一個新增的功能,用來指定元素的長度。你可以使用calc()給元素的width、height、margin、padding、top、font-size和border等屬性設置動態值。為何說是動態值呢?因為我們可使用表達式來得到值。不過calc()最大的好處就是用在流體布局上,可以通過calc()計算得到元素的寬度。

calc()能做什麼?

calc()能讓你做強大的不確定數值計算,你可以給一個div元素,使用%、em、px和rem等單位值計算出其寬度或者高度,比如說「width:calc(50% + 2em)」,這樣就可以不用考慮DIV的具體數值。

calc()語法

calc()語法非常簡單,就像我們小時候學加 (+)、減(-)、乘(*)、除(/)一樣,使用數學表達式來表示:margin-top: calc( (100vh - 344px)/2 )

calc()的運算規則

可使用通用的數學運算規則,但是也提供更智能的功能:

  • 使用「+」「-」「*」「/」四則運算

  • 可以使用px、vw、vh、%、em、rem等單位

  • 可以混合使用各種單位進行計算

  • 表達式中有「+」和「-」時,其前後必須要有空格,如「widht: calc(10%+5em)」這種寫法是錯誤的

  • 表達式中有「*」和「/」時,其前後可以沒有空格,但建議留有空格

關於百分比與Viewport使用的說明:

  • 100%指代父項的寬度

  • Viewport指代可視窗口尺寸,也就是瀏覽器

  • VW為窗口寬度單位,1vw等於viewport寬度的1%

  • VH為窗口高度單位,1vh等於viewport高的的1%

——————————————————————————————————————————

最後,總結一下從css2進化到css3的所有垂直居中方法:

  • flex法,父元素添加 display: flex; 子元素添加 margin: auto;

  • 利用calc() 數值計算

  • box法,子元素添加 display: (-webkit-/-moz-/-ms-)box; box-orient: horizontal; box-pack: center; box-align: center;

  • 模擬表格,父元素添加 display: table; 子元素添加 display: table-cell; vertical-align: middle

  • 絕對定位,子元素添加 position: absolute; top: 50%; margin-top: -(div height/2)px;

  • 利用padding或margin(邊距法)

  • 利用line-height(行高法),只針對文字


幾乎全部人都在回答『如何實現垂直居中』, 其實題問題的人的最強烈的疑問是, 為什麼垂直居中這麼常用的功能, 在CSS乃至CSS3中, 要用一大堆Tricks來實現.

其實這就是互聯網世界中的所謂『歷史遺留』的問題. 一個正常的語言一旦要實現一個非常常用的功能居然要學習和研究各種奇技淫巧, 而且你在網上搜索了之後大家都對這些奇技淫巧樂在其中的feel, 那隻能說明一個問題-----------

這種『歷史遺留』養活了許多人...包括W3C...


CSS3 使用 flexible box 已經可以直接設置垂直居中了。你冤枉那個坑爹組織啦。

參考這裡:http://www.w3.org/TR/css3-flexbox/


看看CSS權威指南,了解一下布局演算法。在CSS 3之前那個荒蠻時代還沒有這麼多的顯示模型,一些布局演算法不容易實現,會遇到先有雞還是先有蛋的問題。


padding: 10px 0 不就是垂直居中嗎?

你要問的應該是為什麼定高垂直居中為什麼這麼難。

首先應該避免定高。

讓文檔流內容自然而然地撐起父元素才是正經事。

即使一定要定高,配合 flex 也很容易垂直居中。

.parent{
height: 100px;
display: flex;
align-items: center;
}

這其實是對需求的理解問題。


不難啊,只要把line height 和 height 設成同樣的值就好了

如果要把很多多行元素整體居中,也是一樣。把要居中的元素先都放到一個層里。在外圍的容器層 把line height 和 height 設成同樣的值,就行了


Absolute Horizontal And Vertical Centering In CSS

建議看下這篇,比較神。前段時間的項目里就用了這個方法,很好用。


安利一個網站

How to center in css

http://howtocenterincss.com/


因為瀏覽器在載入中想知道文檔的高度真的很難啊


人家這是11年發的牢騷


display: -webkit-box;

display: -moz-box;

display: -ms-flexbox;

display: -webkit-flex;

display: flex;

-webkit-align-items: center;

align-items: center;

-webkit-justify-content: center;

justify-content: center;

上面這代碼......難道我一直用的假的 CSS?

標準代碼就三行,麻煩嗎?

這鍋 CSS 不背!


看到這個問題,引爆了我的吐槽能量……

平常我也有用WPF來編程,WPF的垂直居中真的做得簡單易用好用

VerticalAlignment設置母元素的垂直居中位置,有TOP、BOTTOM、CENTER、STRECH,無論是上下中甚至是擴展到全部都包含……

VerticalContentAlignment來設置子元素的垂直居中位置,同樣也有上面提到的屬性……

我能理解以前舊的CSS落後沒有兼容這一塊的原因,可是到了CSS3,哪怕用FLEXBOX的垂直居中,真心也沒WPF這樣來得簡單直接……

同理,GRID、數據綁定等等……WPF也比網頁前端來的簡單方便……

可能你會說桌面編程能和網頁編程根本不同的東西,能相提並論?

如果你搞過WPF的前端……就會發現這其實和網頁前端基本大同小異……

但做同樣的功能,用WPF前端做比用網頁前端效率實在快太TM多了……

我是真心搞不懂,為什麼CSS非得有事沒事要搞這麼複雜……

我不是說哪種編程語言才是最好的編程語言之類的嘲諷性話題,只是單論語法方面,CSS本來就應該可以做得更好……


唔...暫時能想到7種,後面兩種適用性比較差

https://github.com/joe223/b/issues/7github.com


正好我也需要在div 中垂直居中顯示文字

最後我投機取巧把 文字寫在button里

button的文字 看上去 好像就是 垂直居中的

谷歌 IE 都是正常的

&
& button{
font-family: 微軟雅黑;
height:50%;
width:50%;
border:1px solid #000;
background:transparent;/* 背景透明 */
}
&
&

&

為什麼「margin:auto」可以讓塊級元素水平居中?
如何讓input裡面placeholder水平居中?
css 使用display:inline-block的問題求解?
現在國外做網站是用 DIV + CSS,還是 table?
有哪些好的 HTML 和 CSS 入門教程可以推薦給新手?

TAG:CSS | 萬維網聯盟W3C |