Am I centered yet?
Center me, please!
摘要:在通常情況下,對那些需要居中的元素來說,其尺寸往往是由其內容來決定的。雖然沒有垂直居中效果,但也是完全可以接受的。的另一個好處在于,它還可以將匿名容器即沒有被標簽包裹的文本節點垂直居中。
主要摘自:《CSS 揭秘》,強烈推薦的一本書。
“44 年前我們就把人類送上月球了,但現在我們仍然無法在 CSS 中 實現垂直居中。”——James Anderson(https://twitter.com/jsa/ status/358603820516917249)
在 CSS 中對元素進行水平居中是非常簡單的:如果它是一個行內元素, 就對它的父元素應用 text-align: center; 如果它是一個塊級元素,就對它自身應用 margin: auto。然而如果要對一個元素進行垂直居中,可能光是想想就令人頭皮發麻了。
長久以來,為了解決這一絕世難題,前端開發者們殫精竭慮,琢磨出了各種解決方法,可惜大多數并不實用。在本篇攻略中,我們將探索現代 CSS 的強大威力,以全新的思路去攻克各種場景下的垂直居中難題。請注意,有幾種技巧十分流行,但在這里并不會深入探討,原因如下:
表格布局法(利用表格的顯示模式)需要用到一些冗余的 HTML 元素,實現起來不夠優雅簡潔,因此這里不多介紹。
行內塊法也不作討論,因為在我看來這種方法 hack 的味道很濃。
如果你有興趣,可以去看看 Chris Coyier 寫的 Centering in the Unknown。這篇出色的文章詳細講述了這兩種技巧。
我們將使用如下所示的結構代碼,并直接插入
元素中(但實際上我們將要探索的這些技巧是與容器無關的):基于絕對定位Am I centered yet?
Center me, please!
我們先來看一個早期的垂直居中方法,它要求元素具有固定的寬度和高度:
main { position: absolute; top: 50%; left: 50%; margin-top: -3em; /* 6/2 = 3 */ margin-left: -9em; /* 18/2 = 9 */ width: 18em; height: 6em; }
這段代碼在本質上做了這樣幾件事情:
先把這個元素的左上角放置在視口(或最近的、具有定位屬性的祖先元素)的正中心
然后再利用負外邊距把它向左、向上移動(移動距離相當于它自身寬高的一半),從而把元素的正中心放置在視口的正中心。
借助強大的 calc() 函數,這段代碼還可以省掉兩行聲明:
main { position: absolute; top: calc(50% - 3em); left: calc(50% - 9em); width: 18em; height: 6em; }
顯然,這個方法最大的局限在于它要求元素的寬高是固定的。
在通常情況下,對那些需要居中的元素來說,其尺寸往往是由其內容來決定的。如果 能找到一個屬性的百分比值以元素自身的寬高作為解析基準,那我們的難題就迎刃而解了!遺憾的是,對于絕大多數 CSS 屬性(包括 margin)來說, 百分比都是以其父元素的尺寸為基準進行解析的。
CSS 領域有一個很常見的現象,真正的解決方案往往來自于我們最意想不到的地方。
在這個例子中,答案來自于 CSS Transforms 。當我們在 translate() 變形函數中使用百分比值時,是以這個元素自身的寬度和高度為基準進行換算和移動的,而這正是我們所需要的。接下來,只要換用基于百分比的 CSS 變形來對元素進行偏移,就不需要在偏移量中把元素的尺寸寫死。這樣我們就可以徹底解除對固定尺寸的依賴:
main { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
可以看到,這個容器已經完美居中了,完全滿足我們的期望。
當然,沒有任何技巧是十全十美的,上面這個方法也有一些需要注意的地方:
我們有時不能選用絕對定位,因為它對整個布局的影響太過強烈。
如果需要居中的元素已經在高度上超過了視口,那它的頂部會被視口裁切掉。有一些辦法可以繞過這個問題,但 hack 味道過濃。
在某些瀏覽器中,這個方法可能會導致元素的顯示有一些模糊,因 為元素可能被放置在半個像素上。這個問題可以用 transform- style: preserve-3d 來修復,不過這個修復手段也可以認為是一個 hack,而且很難保證它在未來不會出問題。
線上例子:http://dabblet.com/gist/cd12fac0e18bb27fb62d基于 viewport
假設我們不想使用絕對定位,仍然可以采用 translate() 技巧來把這 個元素以其自身寬高的一半為距離進行移動;但是在缺少 left 和 top 的情況下,如何把這個元素的左上角放置在容器的正中心呢?
我們的第一反應很可能是用 margin 屬性的百分比值來實現,就像這樣:
main { width: 18em; padding: 1em 1.5em; margin: 50% auto 0; transform: translateY(-50%); }
不過,如圖所示,這段代碼會產生十分離譜的結果:
原因在于 margin 的百分比值是以父元素的寬度作為解析基準的 。沒錯,即使對于 margin-top 和 margin-bottom 來說也是這樣!
不過幸運的是,如果只是想把元素相對于視口進行居中,仍然是有希望的。CSS Values and Units Module Level 3 定義了一套新的單位,稱為 viewport 相關的長度單位。
vw :1% of viewport’s width
vh :1% of viewport’s height
vmin :1% of viewport’s smaller dimension
vmax :1% of viewport’s larger dimension
在我們的這個例子中,適用于外邊距的是 vh 單位:
main { width: 18em; padding: 1em 1.5em; margin: 50vh auto 0; transform: translateY(-50%); }
可以看到,其效果堪稱完美。當然,這個技巧的實用性是相當有限的,因為它只適用于在視口中居中的場景。
線上例子:http://dabblet.com/gist/bf12b39d8f5da2b6e5b6基于 Flexbox
這是毋庸置疑的最佳解決方案,因為 Flexbox 是專門針對這類需求所設計的。我們之所以要討論其他方案,僅僅是因為那些方案在瀏覽器的支持程度上稍微好一些而已。但其實目前現代瀏覽器對 Flexbox 的支持度已經相當不錯了。
我們只需寫兩行聲明即可:
先給這個待居中元素的父元素設置 display: flex (在這個例子中是 元素)
再給這個元素自身設置我們再熟悉不過的 margin: auto(在這個例子中是 元素):
body { display: flex; min-height: 100vh; margin: 0; } main { margin: auto; }
請注意,當我們使用 Flexbox 時,margin: auto 不僅在水平方向上將元素居中,垂直方向上也是如此。還有一點,我們甚至不需要指定任何寬度(當然,如果需要的話,也是可以指定的):這個居中元素分配到的寬度等于 max-content。
如果瀏覽器不支持 Flexbox,頁面渲染結果看起來就跟我們的起點圖是一樣的了(如果設置了寬度的話)。雖然沒有垂直居中效果,但也是完全可以接受的。
Flexbox 的另一個好處在于,它還可以將匿名容器(即沒有被標簽包裹的文本節點)垂直居中。舉個例子,假設我們的結構代碼是:
Center me, please!
我們先給這個 main 元素指定一個固定的尺寸,然后借助 Flexbox 規范 所引入的 align-items 和 justify-content 屬性,我們可以讓它內部的文本也實現居中:
main { display: flex; align-items: center; justify-content: center; width: 18em; height: 10em; }
線上例子:http://play.csssecrets.io/vertical-centering-vh關于未來
根據 CSS Box Alignment Module Level 3 的計劃,在未來,對于簡單的垂直居中需求, 我們完全不需要動用特殊的布局模式了。因為只需要下面這行代碼就可以搞定:
align-self: center;
不管這個元素上還應用了其他什么屬性,這樣寫就夠了。這聽起來可能難以置信,但或許你電腦上的瀏覽器很快就會讓它成為現實。
參考CSS Transforms Module Level 1
CSS Values and Units Module Level 4
CSS Flexible Box Layout Module Level 1
CSS Box Alignment Module Level 3
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/117147.html
摘要:同行這么做使用實現圓形進度條前端掘金在開發微信小程序的時候,遇到圓形進度條的需求。實現也談數組去重前端掘金的數組去重是一個老生常談的話題了。百度前端技術學院自定義前端掘金一標簽概念元素表示用戶界面中項目的標題。 閑話圖片上傳 - 掘金作者:孫輝,美團金融前端團隊成員。15年畢業加入美團,相信技術,更相信技術只是大千世界里知識的一種,個人博客: https://sunyuhui.com ...
摘要:同行這么做使用實現圓形進度條前端掘金在開發微信小程序的時候,遇到圓形進度條的需求。實現也談數組去重前端掘金的數組去重是一個老生常談的話題了。百度前端技術學院自定義前端掘金一標簽概念元素表示用戶界面中項目的標題。 閑話圖片上傳 - 掘金作者:孫輝,美團金融前端團隊成員。15年畢業加入美團,相信技術,更相信技術只是大千世界里知識的一種,個人博客: https://sunyuhui.com ...
摘要:寫在前面居中方案是一個老生常談的問題,主要包括水平居中和垂直居中,水平居中大家用的比較多,最常用的莫過于方案了,而垂直居中,很多時候會讓很多新手頭疼。常用居中方案水平解決方案水平居中適用于已經知道寬度,并且其父級寬度不為的元素水平居中。 寫在前面 css居中方案是一個老生常談的問題,主要包括水平居中和垂直居中,水平居中大家用的比較多,最常用的莫過于margin:0 auto方案了,而垂...
摘要:高度模型淺識為的簡寫,簡稱為塊級格式化上下文,為瀏覽器渲染某一區域的機制,中只有和中還增加了和。并非所有的布局都會在開發中使用,但是其中也會涉及一些知識點。然而在不同的純制作各種圖形純制作各種圖形多圖預警 一勞永逸的搞定 flex 布局 尋根溯源話布局 一切都始于這樣一個問題:怎樣通過 CSS 簡單而優雅的實現水平、垂直同時居中。記得剛開始學習 CSS 的時候,看到 float 屬性不...
閱讀 1634·2023-04-26 02:11
閱讀 2978·2023-04-25 16:18
閱讀 3710·2021-09-06 15:00
閱讀 2630·2019-08-30 15:55
閱讀 1933·2019-08-30 13:20
閱讀 2050·2019-08-26 18:36
閱讀 3120·2019-08-26 11:40
閱讀 2535·2019-08-26 10:11