这是关于 CSS 变量如何用于使复杂布局和交互的代码更易于编写和维护的两部分系列文章中的第二篇。第一篇 文章 阐述了此技术适用的各种用例。本文介绍了回退值和无效值的使用,将该技术扩展到非数值。
我们在本系列的 第一篇文章 中介绍的使用 CSS 变量驱动布局和交互切换的策略存在一个主要警告:它仅适用于数值——长度、百分比、角度、持续时间、频率、无单位数值等等。因此,知道可以使用单个 CSS 变量切换十多个属性的计算值,但随后需要显式切换诸如 flex-direction
或 text-align
等属性的非数值(例如,从 row
切换到 column
,或从 left
切换到 right
,反之亦然),这确实令人沮丧。
以下是一个示例,其中 text-align
属性取决于奇偶性,而 flex-direction
属性取决于我们是否在宽屏场景中查看前端。

我对此表示了抱怨,并收到了一个 非常有趣的建议,该建议利用了 CSS 变量的回退值和无效值。它很有趣,并为我们提供了新的内容,所以让我们从简要回顾一下什么是回退值和无效值开始吧!
回退值
CSS 变量的回退值是 var()
函数的第二个可选参数。例如,假设我们有一些 .box
元素,其背景设置为 --c
变量。
.box { background: var(--c, #ccc) }
如果我们没有在其他地方显式指定 --c
变量的值,则使用回退值 #ccc
。
现在假设其中一些框具有 .special
类。在这里,我们可以将 --c
指定为某种橙色。
.special { --c: #f90 }
这样,具有此 .special
类的框具有橙色的 background
,而其他框使用浅灰色回退值。
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
这里需要注意一些事项。
首先,回退值可以是另一个 CSS 变量,该变量本身可以具有 CSS 变量回退值,并且……我们可以通过这种方式陷入一个非常深的兔子洞!
background: var(--c, var(--c0, var(--c1, var(--c2, var(--c3, var(--c4, #ccc))))))
其次,逗号分隔列表是一个完全有效的回退值。实际上,在 var()
函数中第一个逗号之后指定的所有内容都构成回退值,如下面的示例所示。
background: linear-gradient(90deg, var(--stop-list, #ccc, #f90))
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
最后但并非最不重要的一点是,我们可以为在不同位置使用的相同变量设置不同的回退值,如下面的示例所示。
$highlight: #f90;
a {
border: solid 2px var(--c, #{rgba($highlight, 0)})
color: var(--c, #ccc);
&:hover, &:focus { --c: #{$highlight} }
}
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
无效值
首先,我想澄清一下我的意思。“无效值”更短更容易记住,但它实际上指的是任何使声明在计算值时 无效 的值。
例如,考虑以下代码片段。
--c: 1em;
background: var(--c)
1em
是一个有效的长度值,但这不是 background-color
属性的有效值,因此此处此属性将采用其初始值(即 transparent
)。
综合运用
假设我们有一堆段落,我们根据奇偶性更改 color
值的亮度以在 black
和 white
之间切换(如本系列上一篇文章中所述)。
p {
--i: 0;
/* for --i: 0 (odd), the lightness is 0*100% = 0% (black)
* for --i: 1 (even), the lightness is 1*100% = 100% (white)* /
color: hsl(0, 0%, calc(var(--i)*100%));
&:nth-child(2n) { --i: 1 }
}
我们还希望奇数段落右对齐,同时保持偶数段落左对齐。为了实现这一点,我们引入了一个 --parity
变量,我们通常情况下不显式设置它——仅在偶数项中设置。我们在通常情况下设置的是我们之前的变量 --i
。我们将其设置为 --parity
的值,并使用 0
作为回退值。
p {
--i: var(--parity, 0);
color: hsl(0, 0%, calc(var(--i)*100%));
&:nth-child(2n) { --parity: 1 }
}
到目前为止,这与我们代码的先前版本完全相同。但是,如果我们利用以下事实:我们可以为相同变量在不同位置使用不同的回退值,那么我们也可以将 text-align
设置为 --parity
的值,并使用… right
作为回退值!
text-align: var(--parity, right)
在通常情况下,我们没有显式设置 --parity
;text-align
使用回退值 right
,这是一个有效值,因此我们有右对齐。但是,对于偶数项,我们显式将 --parity
设置为 1
,这对于 text-align
不是有效值。这意味着 text-align
会恢复到其 initial
值,即 left
。
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
现在,我们对奇数项实现了右对齐,对偶数项实现了左对齐,同时仍然只使用了一个 CSS 变量!
剖析更复杂的示例
假设我们希望获得以下结果。

我们使用段落元素 <p>
创建这些卡片,每个卡片一个。我们将其 box-sizing
切换为 border-box
,然后为其设置 width
、max-width
、padding
和 margin
。我们还更改了默认的 font
。
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
我们还添加了一个虚拟轮廓,以便查看这些元素的边界。
接下来,让我们使用 CSS 计数器 和 :before
伪元素添加编号。
p {
/* same code as before */
counter-increment: c;
&:before { content: counter(c, decimal-leading-zero) }
}
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
现在,我们将为段落提供 flex
布局并增加编号的大小。
p {
/* same code as before */
display: flex;
align-items: center;
&:before {
font-size: 2em;
content: counter(c, decimal-leading-zero);
}
}
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
现在到了有趣的部分!
我们设置了一个切换 --i
,它会根据奇偶性更改值——对于奇数项为 0
,对于偶数项为 1
。
p {
/* same code as before */
--i: 0;
&:nth-child(2n) { --i: 1 }
}
接下来,我们希望编号对于奇数项位于左侧,对于偶数项位于右侧。我们可以通过 order
属性来实现。此属性的初始值为 0
,对于 :before
伪元素和段落文本内容都是如此。如果我们将偶数元素的编号(:before
伪元素)的 order
属性设置为 1
,则此操作会将编号移动到内容之后。
p {
/* same code as before */
--i: 0;
&:before {
/* same code as before */
/* we don't really need to set order explicitly as 0 is the initial value */
order: 0;
}
&:nth-child(2n) {
--i: 1;
&:before { order: 1 }
}
}
您可能会注意到,在这种情况下,order
值与切换 --i
值相同,因此为了简化操作,我们将 order
设置为切换值。
p {
/* same code as before */
--i: 0;
&:before {
/* same code as before */
order: var(--i)
}
&:nth-child(2n) { --i: 1 }
}
查看 thebabydino 在 CodePen 上创建的 Pen(@thebabydino)。
现在,我们希望在编号和段落文本之间留出一些间距(假设为 $gap
)。这可以通过 :before
上的横向 margin
来实现。
对于奇数项,项目编号位于左侧,因此我们需要一个非零 margin-right
。对于偶数项,项目编号位于右侧,因此我们需要一个非零 margin-left
。
当奇数项的奇偶性切换值为 0
时,左外边距为 0 = 0*$gap
,而右外边距为 $gap = 1*$gap = (1 - 0)*$gap
。
类似地,对于偶数项,当奇偶性切换值为 1
时,左外边距为 $gap = 1*$gap
,而右外边距为 0 = 0*$gap = (1 - 1)*$gap
。
两种情况下,结果都是 margin-left
等于奇偶切换值乘以边距值 ($gap
),而 margin-right
等于 1
减去奇偶切换值,所有结果都乘以边距值。
$gap: .75em;
p {
/* same code as before */
--i: 0;
&:before {
/* same code as before */
margin:
0 /* top */
calc((1 - var(--i))*#{$gap}) /* right */
0 /* bottom */
calc(var(--i)*#{$gap}) /* left */;
}
&:nth-child(2n) { --i: 1 }
}
如果我们在多个地方使用互补值 (1 - var(--i)
),那么最好将其设置为另一个 CSS 变量 --j
。
$gap: .75em;
p {
/* same code as before */
--i: 0;
--j: calc(1 - var(--i));
&:before {
/* same code as before */
margin:
0 /* top */
calc(var(--j)*#{$gap}) /* right */
0 /* bottom */
calc(var(--i)*#{$gap}) /* left */;
}
&:nth-child(2n) { --i: 1 }
}
查看 thebabydino 在 CodePen 上创建的 Pen (@thebabydino)。
接下来,我们想为这些项目提供一个合适的 background
。这是一个灰色到橙色的渐变,对于奇数项(奇偶切换 --i: 0
),从左到右(或沿着 90deg
角)渐变,对于偶数项(奇偶切换 --i: 1
),从右到左(沿着 -90deg
角)渐变。
这意味着渐变角度的绝对值相同 (90deg
),只有符号不同——对于奇数项 (--i: 0
) 为 +1
,对于偶数项 (--i: 1
) 为 -1
。
为了切换符号,我们使用在第一篇文章中介绍的方法。
/*
* for --i: 0, we have 1 - 2*0 = 1 - 0 = +1
* for --i: 1, we have 1 - 2*1 = 1 - 2 = -1
*/
--s: calc(1 - 2*var(--i))
这样,我们的代码就变成了
p {
/* same code as before */
--i: 0;
--s: calc(1 - 2*var(--i));
background: linear-gradient(calc(var(--s)*90deg), #ccc, #f90);
&:nth-child(2n) { --i: 1 }
}
我们还可以移除虚拟轮廓,因为我们现在不需要它了。
查看 thebabydino 在 CodePen 上创建的 Pen (@thebabydino)。
接下来,我们对 transform
属性做类似的操作。
奇数项向右(x 轴正方向)稍微平移,并顺时针(正方向)稍微旋转,而偶数项向左(x 轴负方向)稍微平移,并逆时针(负方向)稍微旋转。
平移和旋转量相同,只有符号不同。
对于奇数项,transform
链为
translate(10%) rotate(5deg)
而对于偶数项,我们有
translate(-10%) rotate(-5deg)
使用我们的符号 --s
变量,统一的代码为
p {
/* same code as before */
--i: 0;
--s: calc(1 - 2*var(--i));
transform: translate(calc(var(--s)*10%))
rotate(calc(var(--s)*5deg));
&:nth-child(2n) { --i: 1 }
}
现在开始有点样子了!
查看 thebabydino 在 CodePen 上创建的 Pen (@thebabydino)。
下一步是圆角卡片。对于奇数卡片,我们希望左侧的角圆角半径为高度的一半。对于偶数项,我们希望右侧的角圆角半径相同。
鉴于我们不知道卡片的高度,我们只使用一个非常大的值,比如 50vh
,由于 border-radius
的工作方式,它会被缩放到适合的大小。在我们的例子中,这意味着缩放到项目 height
的一半(因为垂直方向在同一侧都有顶部和底部圆角)和完整项目 width
(因为水平方向只有一个圆角;要么在左侧要么在右侧,但不在左右两侧)中较小的那个。
这意味着我们希望左侧的角具有此半径 ($r: 50vh
) 用于奇数项 (--i: 0
),而右侧的角具有相同半径用于偶数项 (--i: 1
)。因此,我们做了一些与编号 margin
案例非常相似的事情。
$r: 50vh;
p {
/* same code as before */
--i: 0;
--j: calc(1 - var(--i));
--r0: calc(var(--j)*#{$r});
--r1: calc(var(--i)*#{$r});
/* clockwise from the top left */
border-radius: var(--r0) /* top left */
var(--r1) /* top right */
var(--r1) /* bottom right */
var(--r0) /* bottom left */;
&:nth-child(2n) { --i: 1 }
}
查看 thebabydino 在 CodePen 上创建的 Pen (@thebabydino)。
现在到了真正有趣的部分——文本对齐!我们希望奇数项中的文本右对齐,而偶数项中的文本左对齐。唯一的问题是 text-align
不接受数字值,因此我们无法使用加法或乘法技巧来帮助我们。
可以帮助我们的是结合使用 CSS 变量的回退值和无效值。为此,我们引入另一个奇偶变量 --p
,并且实际上我们将此变量设置为偶数项的 1
。与之前的 --i
不同,我们永远不会为一般情况显式设置 --p
,因为我们希望此变量的不同回退值用于不同的属性。
至于 --i
,我们将其设置为 --p
,并在一般情况下回退值为 0
。这个 0
的回退值实际上是在一般情况下使用的值,因为我们从未在那里显式设置 --p
。对于我们显式将 --p
设置为 1
的偶数情况,--i
也变为 1
。
同时,我们将 text-align
属性设置为 --p
,并在一般情况下回退值为 right
。在偶数情况下,我们显式地将 --p
设置为 1
,text-align
值变为无效(因为我们将 text-align
设置为 --p
的值,而 --p
现在是 1
,这对于 text-align
不是有效值),因此文本恢复为左对齐。
p {
/* same code as before */
--i: var(--p, 0);
text-align: var(--p, right);
&:nth-child(2n) { --p: 1 }
}
这给了我们我们一直在追求的结果。
查看 thebabydino 在 CodePen 上创建的 Pen (@thebabydino)。
处理响应式
虽然我们的卡片示例在较宽的屏幕上看起来很棒,但在缩小屏幕时却并非如此。

为了解决这个问题,我们引入了另外两个自定义属性 --wide
和 --k
来在宽屏和窄屏案例之间切换。在一般情况下,我们将 --k
设置为 --wide
,回退值为 0
,然后如果视口宽度为 340px
及以上,则将 --wide
设置为 1
。
p {
/* same code as before */
--k: var(--wide, 0);
@media (min-width: 340px) { --wide: 1 }
}
由于我们只希望在宽屏情况下对项目进行转换并圆角,因此我们将平移、旋转和半径值乘以 --k
(除非视口很宽,否则为 0
,这会将其值切换为 1
)。
p {
/* same code as before */
--k: var(--wide, 0);
--r0: calc(var(--k)*var(--j)*#{$r});
--r1: calc(var(--k)*var(--i)*#{$r});
border-radius: var(--r0) /* top left */
var(--r1) /* top right */
var(--r1) /* bottom right */
var(--r0) /* bottom left */;
transform: translate(calc(var(--k)*var(--s)*10%))
rotate(calc(var(--k)*var(--s)*5deg));
@media (min-width: 340px) { --wide: 1 }
}
这 稍微好一点,但在窄视口中我们的内容仍然溢出。我们可以通过仅在宽屏情况下将编号(:before
伪元素)放置在左侧或右侧来解决此问题,然后在窄屏情况下将其移动到卡片上方。
为此,我们将它的 order
和它的横向 margin
值都乘以 --k
(在宽屏情况下为 1
,否则为 0
)。
我们还将 flex-direction
设置为 --wide
,回退值为 column
。
这意味着 flex-direction
值在一般情况下为 column
(因为我们没有在其他地方显式设置 --wide
)。但是,如果视口很宽 (min-width: 340px
),则我们的 --wide
变量将设置为 1
。但 1
对于 flex-direction
是一个无效值,因此此属性恢复到其初始值 row
。
p {
/* same code as before */
--k: var(--wide, 0);
flex-direction: var(--wide, column);
&:before {
/* same code as before */
order: calc(var(--k)*var(--i));
margin:
0 /* top */
calc(var(--k)*var(--j)*#{$gap}) /* right */
0 /* bottom */
calc(var(--k)*var(--i)*#{$gap}) /* left */;
}
@media (min-width: 340px) { --wide: 1 }
}
结合在 body
上设置 min-width
为 160px
,我们现在消除了溢出问题。
我们还可以做的一件事是调整 font-size
,使其也依赖于 --k
。
p {
/* same code as before */
--k: var(--wide, 0);
font: 900 calc(var(--k)*.5em + .75em) cursive;
@media (min-width: 340px) { --wide: 1 }
}
就是这样,我们的演示现在具有良好的响应能力!
更多快速示例!
让我们再看一些使用相同技术的演示,但快速地不做从头开始构建。我们只会快速浏览它们背后的基本思想。
圆盘切片
就像我们一起完成的卡片示例一样,我们可以使用 :before
伪元素进行编号,并在段落上使用 flex
布局。 圆盘切片效果 是使用 clip-path
实现的。
段落元素本身——水平偏移量、创建阴影效果的 radial-gradient()
的位置和强度、linear-gradient()
的方向及其停止点的饱和度、color
和文本对齐——都取决于 --parity
变量。
p {
/* other styles not relevant here */
--p: var(--parity, 1);
--q: calc(1 - var(--p));
--s: calc(1 - 2*var(--p)); /* sign depending on parity */
transform: translate((calc(var(--i)*var(--s)*#{-$x})));
background:
radial-gradient(at calc(var(--q)*100%) 0,
rgba(0, 0, 0, calc(.5 + var(--p)*.5)), transparent 63%)
calc(var(--q)*100%) 0/ 65% 65% no-repeat,
linear-gradient(calc(var(--s)*-90deg),
hsl(23, calc(var(--q)*98%), calc(27% + var(--q)*20%)),
hsl(44, calc(var(--q)*92%), 52%));
color: HSL(0, 0%, calc(var(--p)*100%));
text-align: var(--parity, right);
&:nth-child(odd) { --parity: 0 }
}
对于编号(段落的 :before
伪元素),我们有 margin
和 order
都以与卡片示例完全相同的方式依赖于 --parity
。
如果视口 width
小于圆盘直径 $d
加上水平切片偏移量的绝对值的两倍 $x
,那么我们就不再处于 --wide
案例中了。这会影响我们段落的 width
、padding
和 margin
,以及它们的水平偏移量和形状(因为我们不会剪裁它们以在此时获得圆盘切片效果)。
body {
/* other styles not relevant here */
--i: var(--wide, 1);
--j: calc(1 - var(--i));
@media (max-width: $d + 2*$x) { --wide: 0 }
}
p {
/* other styles not relevant here */
margin: calc(var(--j)*.25em) 0;
padding:
calc(var(--i)*#{.5*$r}/var(--n) + var(--j)*5vw) /* vertical */
calc(var(--i)*#{.5*$r} + var(--j)*2vw) /* horizontal */;
width: calc(var(--i)*#{$d} /* wide */ +
var(--j)*100% /* not wide */);
transform: translate((calc(var(--i)*var(--s)*#{-$x})));
clip-path:
var(--wide,
/* fallback, used in the wide case only */
circle($r at 50% calc((.5*var(--n) - var(--idx))*#{$d}/var(--n))));
}
我们在 270px
以下处于窄屏情况,并且在段落上具有 flex-direction
为 column
。我们还将编号的横向边距和 order
都清零。
body {
/* other styles not relevant here */
--k: calc(1 - var(--narr, 1));
@media (min-width: 270px) { --narr: 0 }
}
p {
/* other styles not relevant here */
flex-direction: var(--narr, column);
&:before {
/* other styles not relevant here */
margin:
0 /* top */
calc(var(--k)*var(--q)*.25em) /* right */
0 /* bottom */
calc(var(--k)*var(--p)*.25em) /* left */;
order: calc(var(--k)*var(--p));
}
}
四步信息图

这与前两个示例的工作原理基本相同。我们在段落上使用 flex
布局,在窄屏情况下使用 column
方向。在同一情况下,我们还有更小的 font-size
。
body {
/* other styles not relevant here */
--k: var(--narr, 1);
@media (min-width: 400px) { --narr: 0 }
}
p {
/* other styles not relevant here */
flex-direction: var(--narr, column);
font-size: calc((1.25 - .375*var(--k))*1em);
}
奇偶性决定每个段落的文本对齐方式,哪个横向 border
获取非零值,以及 border
渐变的位置和方向。奇偶性和我们是否处于宽屏情况都会决定横向边距和填充。
body {
/* other styles not relevant here */
--i: var(--wide, 1);
--j: calc(1 - var(--i));
@media (max-width: $bar-w + .5*$bar-h) { --wide: 0 }
}
p {
/* other styles not relevant here */
margin:
.5em /* top */
calc(var(--i)*var(--p)*#{.5*$bar-h}) /* right */
0 /* bottom */
calc(var(--i)*var(--q)*#{.5*$bar-h}) /* left */;
border-width:
0 /* top */
calc(var(--q)*#{$bar-b}) /* right */
0 /* bottom */
calc(var(--p)*#{$bar-b}) /* left */;
padding:
$bar-p /* top */
calc((var(--j) + var(--i)*var(--q))*#{$bar-p}) /* right */
$bar-p /* bottom */
calc((var(--j) + var(--i)*var(--p))*#{$bar-p}) /* left */;
background:
linear-gradient(#fcfcfc, gainsboro) padding-box,
linear-gradient(calc(var(--s)*90deg), var(--c0), var(--c1))
calc(var(--q)*100%) /* background-position */ /
#{$bar-b} 100% /* background-size */;
text-align: var(--parity, right);
}
图标使用:before
伪元素创建,其order
取决于奇偶性,但仅当我们不在窄屏场景下时——在这种情况下,它始终位于段落实际文本内容之前。其横向margin
取决于奇偶性和我们是否处于宽屏情况下。将其定位在其父段落一半之外的大值组件仅在宽屏情况下存在。font-size
也取决于我们是否处于窄屏情况下(这会影响其em
尺寸和填充)。
order: calc((1 - var(--k))*var(--p));
margin:
0 /* top */
calc(var(--i)*var(--p)*#{-.5*$ico-d} + var(--q)*#{$bar-p}) /* right */
0 /* bottom */
calc(var(--i)*var(--q)*#{-.5*$ico-d} + var(--p)*#{$bar-p}) /* left */;
font-size: calc(#{$ico-s}/(1 + var(--k)));
环使用绝对定位的:after
伪元素创建(其位置取决于奇偶性),但仅限于宽屏情况。
content: var(--wide, '');
二维情况

calc()
错误,不支持Edge浏览器)。这里我们有一堆article
元素,每个元素都包含一个标题。让我们看看这个响应式布局是如何工作的最有趣方面!
在每个文章上,我们都有一个二维布局(grid
)——但仅当我们不在窄屏场景下(--narr: 1
)时,在这种情况下,我们会回退到正常的文档流,使用:before
伪元素创建编号,然后是标题,然后是实际文本。在这种情况下,我们还会在标题上添加垂直填充,因为我们不再有网格间隙,我们不希望内容过于拥挤。
html {
--k: var(--narr, 0);
@media (max-width: 250px) { --narr: 1 }
}
article {
/* other styles irrelevant here */
display: var(--narr, grid);
}
h3 {
/* other styles irrelevant here */
padding: calc(var(--k)*#{$hd3-p-narr}) 0;
}
对于grid
,我们创建了两列,其宽度取决于奇偶性和我们是否处于宽屏情况下。在宽屏情况下,我们将编号(:before
伪元素)跨两行,根据奇偶性分别位于第二列或第一列。如果我们不在宽屏情况下,则段落跨第二行的两列。
在宽屏场景下,我们将grid-auto-flow
设置为column dense
,否则将其恢复为initial
值row
。由于我们的article
元素比列的组合宽度和它们之间的列间隙更宽,因此我们使用place-content
将实际的网格列定位在右侧或左侧,具体取决于奇偶性。
最后,我们将标题放置在列的末尾或开头,具体取决于奇偶性,以及如果我们在宽屏场景下,段落文本的对齐方式。
$col-1-wide: calc(var(--q)*#{$col-a-wide} + var(--p)*#{$col-b-wide});
$col-2-wide: calc(var(--p)*#{$col-a-wide} + var(--q)*#{$col-b-wide});
$col-1-norm: calc(var(--q)*#{$col-a-norm} + var(--p)*#{$col-b-norm});
$col-2-norm: calc(var(--p)*#{$col-a-norm} + var(--q)*#{$col-b-norm});
$col-1: calc(var(--i)*#{$col-1-wide} + var(--j)*#{$col-1-norm});
$col-2: calc(var(--i)*#{$col-2-wide} + var(--j)*#{$col-2-norm});
html {
--i: var(--wide, 1);
--j: calc(1 - var(--i));
@media (max-width: $art-w-wide) { --wide: 0 }
}
article {
/* other styles irrelevant here */
--p: var(--parity, 1);
--q: calc(1 - var(--p));
grid-template-columns: #{$col-1} #{$col-2};
grid-auto-flow: var(--wide, dense column);
place-content: var(--parity, center end);
&:before {
/* other styles irrelevant here */
grid-row: 1/ span calc(1 + var(--i));
grid-column: calc(1 + var(--p))/ span 1;
}
&:nth-child(odd) { --parity: 0 }
}
h3 {
/* other styles irrelevant here */
justify-self: var(--parity, self-end);
}
p {
grid-column-end: span calc(1 + var(--j));
text-align: var(--wide, var(--parity, right));
}
我们还有数值,例如网格间隙、边框半径、填充、字体大小、渐变方向、旋转和平移方向,具体取决于奇偶性和/或我们是否处于宽屏情况下。
更多示例!
如果您想了解更多内容,我已经创建了一个完整的响应式演示集供您欣赏!
