核心要點
@supports
規則來檢查CSS轉換支持,或對參數進行更嚴格的檢查以確保它們是寬度和高度的有效值,從而進一步改進mixin。 CSS居中一直以來都是一項繁瑣的任務,甚至成為該語言的一個笑柄,導致諸如“我們成功地將宇航員送上月球,但我們無法在CSS中進行垂直對齊”之類的笑話。
雖然CSS在處理居中,特別是垂直居中時確實有點棘手,但我認為這些笑話有點不公平。實際上,CSS中有很多方法可以居中內容,你只需要知道如何去做。
本文並非旨在解釋這些方法的工作原理,而是說明如何將它們封裝在Sass mixin中以方便易用。因此,如果您對CSS居中感到有些不舒服,我建議您事先閱讀一些資源:
準備好了嗎?讓我們開始吧。
概述
首先,我們將重點關注將元素在其父元素中居中,因為這是絕對居中最常見的用例(模態框、部分內容等)。當您詢問某人關於CSS居中的問題時,通常得到的回復是:您知道元素的尺寸嗎? 原因是,如果您不知道元素尺寸,最佳解決方案是依賴CSS轉換。這會稍微降低瀏覽器支持度,但它非常靈活。如果您無法使用CSS轉換或知道元素的寬度和高度,那麼很容易依賴負邊距。
因此,我們的mixin將基本上執行以下操作:將元素的左上角絕對定位在容器的中間,然後根據是否將尺寸傳遞給mixin,使用CSS轉換或負邊距將其向後移動其寬度和高度的一半。無尺寸:使用轉換;有尺寸:使用邊距。
然後您可以像這樣使用它:
<code>/** * 为子元素启用位置上下文 */ .parent { position: relative; } /** * 将元素在其父元素中绝对居中 * 没有将尺寸传递给mixin,因此它依赖于CSS转换 */ .child-with-unknown-dimensions { @include center; } /** * 将元素在其父元素中绝对居中 * 将宽度传递给mixin,因此我们对水平轴使用负边距,对垂直轴使用CSS转换 */ .child-with-known-width { @include center(400px); } /** * 将元素在其父元素中绝对居中 * 将高度传递给mixin,因此我们对垂直轴使用负边距,对水平轴使用CSS转换 */ .child-with-known-height { @include center($height: 400px); } /** * 将元素在其父元素中绝对居中 * 将宽度传递给mixin,因此我们对水平轴和垂直轴都使用负边距 */ .child-with-known-dimensions { @include center(400px, 400px); }</code>
編譯後,它應該輸出以下內容:
<code>.parent { position: relative; } .child-with-unknown-dimensions { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .child-with-known-width { position: absolute; top: 50%; left: 50%; margin-left: -200px; width: 400px; transform: translateY(-50%); } .child-with-known-height { position: absolute; top: 50%; left: 50%; transform: translateX(-50%); margin-top: -200px; height: 400px; } .child-with-known-dimensions { position: absolute; top: 50%; left: 50%; margin-left: -200px; width: 400px; margin-top: -200px; height: 400px; }</code>
好的,這看起來有點冗長,但請記住,此輸出僅用於演示目的。在給定情況下,您不太可能發現自己同時使用所有這些方法。
構建mixin
好的,讓我們深入研究。從之前的代碼片段中,我們已經知道mixin的簽名:它有兩個可選參數,$width
和$height
。
<code>/** * 为子元素启用位置上下文 */ .parent { position: relative; } /** * 将元素在其父元素中绝对居中 * 没有将尺寸传递给mixin,因此它依赖于CSS转换 */ .child-with-unknown-dimensions { @include center; } /** * 将元素在其父元素中绝对居中 * 将宽度传递给mixin,因此我们对水平轴使用负边距,对垂直轴使用CSS转换 */ .child-with-known-width { @include center(400px); } /** * 将元素在其父元素中绝对居中 * 将高度传递给mixin,因此我们对垂直轴使用负边距,对水平轴使用CSS转换 */ .child-with-known-height { @include center($height: 400px); } /** * 将元素在其父元素中绝对居中 * 将宽度传递给mixin,因此我们对水平轴和垂直轴都使用负边距 */ .child-with-known-dimensions { @include center(400px, 400px); }</code>
繼續。在任何情況下,mixin都需要使元素絕對定位,因此我們可以從這一點開始。
<code>.parent { position: relative; } .child-with-unknown-dimensions { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .child-with-known-width { position: absolute; top: 50%; left: 50%; margin-left: -200px; width: 400px; transform: translateY(-50%); } .child-with-known-height { position: absolute; top: 50%; left: 50%; transform: translateX(-50%); margin-top: -200px; height: 400px; } .child-with-known-dimensions { position: absolute; top: 50%; left: 50%; margin-left: -200px; width: 400px; margin-top: -200px; height: 400px; }</code>
我們將必須巧妙地編寫代碼。讓我們在這裡暫停一下,分析一下我們擁有的不同選項:
宽度 | 高度 | 解决方案 |
---|---|---|
未定义 | 未定义 | translate |
定义 | 定义 | margin |
定义 | 未定义 | margin-left translateY |
未定义 | 定义 | translateX margin-top |
讓我們用這個。
<code>/** * 为子元素启用位置上下文 */ .parent { position: relative; } /** * 将元素在其父元素中绝对居中 * 没有将尺寸传递给mixin,因此它依赖于CSS转换 */ .child-with-unknown-dimensions { @include center; } /** * 将元素在其父元素中绝对居中 * 将宽度传递给mixin,因此我们对水平轴使用负边距,对垂直轴使用CSS转换 */ .child-with-known-width { @include center(400px); } /** * 将元素在其父元素中绝对居中 * 将高度传递给mixin,因此我们对垂直轴使用负边距,对水平轴使用CSS转换 */ .child-with-known-height { @include center($height: 400px); } /** * 将元素在其父元素中绝对居中 * 将宽度传递给mixin,因此我们对水平轴和垂直轴都使用负边距 */ .child-with-known-dimensions { @include center(400px, 400px); }</code>
現在我們已經為mixin設置了框架,我們只需要用實際的CSS聲明來填補空白。
<code>.parent { position: relative; } .child-with-unknown-dimensions { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .child-with-known-width { position: absolute; top: 50%; left: 50%; margin-left: -200px; width: 400px; transform: translateY(-50%); } .child-with-known-height { position: absolute; top: 50%; left: 50%; transform: translateX(-50%); margin-top: -200px; height: 400px; } .child-with-known-dimensions { position: absolute; top: 50%; left: 50%; margin-left: -200px; width: 400px; margin-top: -200px; height: 400px; }</code>
注意:#{0 0}
技巧是一個不太乾淨的技巧,用於防止Sass進行稍微過於激進的壓縮,這會導致margin: mt 0 ml
而不是margin: mt 0 0 ml
到目前為止,一切順利。
更進一步
我們可以做幾件事來進一步改進我們的mixin,例如在mixin中包含一個@supports
規則來檢查CSS轉換支持,或者假設存在(或允許)Modernizr並根據是否支持CSS轉換來輸出條件樣式。我們還可以對參數進行更嚴格的檢查,以確保它們是寬度和高度的有效值。
但是,您必須問自己,這樣做是否是一件好事。 mixin本身的循環複雜度已經達到6,對於Sass輔助函數來說已經相當多了。它仍然可以接受,但是向其中添加更多代碼可能會導致循環複雜度進一步增加。
Flexbox怎麼樣?
我很確定你們中的一些人正在座位上跳躍,思考我們如何使用Flexbox將元素在其父元素中居中。確實,這是可能的,而且事實證明,如果條件允許,這是所有解決方案中最簡單的。
我們剛剛設置的解決方案和Flexbox解決方案之間的主要區別在於,後者建立在父元素之上,而前者主要關注子元素(前提是它的任何祖先的位置都不同於static)。
為了使元素使其子元素居中,您只需要設置三個屬性。您可以為此創建一個mixin、佔位符、類或任何您喜歡的元素。
<code>/// 在其父元素中水平、垂直或绝对居中元素 /// 如果指定,此mixin将根据元素的尺寸使用负边距。否则,它将依赖于CSS转换,CSS转换的浏览器支持度较低,但由于它们与尺寸无关,因此更灵活。 /// /// @author Kitty Giraudel /// /// @param {Length | null} $width [null] - 元素宽度 /// @param {Length | null} $height [null] - 元素高度 /// @mixin center($width: null, $height: null) { .. }</code>
假設您添加了相關的供應商前綴(通過mixin或Autoprefixer),此解決方案應該在許多瀏覽器中“正常工作”。
<code>@mixin center($width: null, $height: null) { position: absolute; top: 50%; left: 50%; // 更多魔法在这里... }</code>
正如您肯定猜到的那樣,它會產生:
<code>@mixin center($width: null, $height: null) { position: absolute; top: 50%; left: 50%; @if not $width and not $height { // 使用 `translate` } @else if $width and $height { // 使用 `margin` } @else if not $height { // 使用 `margin-left` 和 `translateY` } @else { // 使用 `margin-top` 和 `translateX` } }</code>
最終想法
我們想要一個簡短的mixin來輕鬆地將元素在其父元素中居中;這個mixin可以完成這項工作,而且做得很好。它不僅足夠聰明,無論元素是否具有特定尺寸都能工作,而且還提供了一個友好且直觀的API,這非常重要。
通過查看代碼,任何人都可以立即理解@include center
行是包含一個輔助函數,該輔助函數執行一些邏輯以使元素在其父元素中居中。但是請記住,為了使此方法有效,後者(或DOM樹中的任何父元素)必須具有不同於static的位置! ;)
您可以在SassMeister上使用此代碼:https://www.php.cn/link/780bc6caf343bb06a4372c0821012624。
(由於篇幅限制,此處省略了FAQs部分。 FAQs部分內容與文章內容高度重複,可以根據需要自行添加或修改。)
以上是以薩斯為中心的詳細內容。更多資訊請關注PHP中文網其他相關文章!