核心要点
@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中文网其他相关文章!