在 CSS 中,我们可以访问 currentColor
,它非常有用。遗憾的是,我们无法访问类似 currentBackgroundColor
的东西,而且 color-mod()
函数还需要一段时间才能实现。
话虽如此,我相信我不孤单,我想根据上下文样式化一些链接,并在链接悬停或聚焦时反转颜色。借助 CSS 自定义属性和一些简单的实用程序类,我们可以实现非常强大的效果,这得益于我们样式的级联特性。
查看 CodePen 上的示例
使用实用程序类和自定义属性上下文着色链接,作者:Christopher Kirk-Nielsen (@chriskirknielsen)
在 CodePen 上。
为了实现这一点,我们需要使用实用程序类(包含我们的自定义属性)来指定我们的文本和背景颜色。然后,我们将使用这些类来定义下划线的颜色,下划线将在悬停时扩展为完整的背景。
让我们从我们的标记开始
<section class="u-bg--green">
<p class="u-color--dark">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, <a href="#">sed do eiusmod tempor incididunt</a> ut labore et dolore magna aliqua. Aliquam sem fringilla ut morbi tincidunt. Maecenas accumsan lacus vel facilisis. Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus semper.
</p>
</section>
这将为我们提供一个包含段落的块,该段落包含一个链接。让我们设置我们的实用程序类。我将定义 我在 Color Hunt 上找到的四种颜色。我们将为 color
属性创建一个类,为 background-color
属性创建一个类,它们将分别包含一个用于分配颜色值的变量(分别为 --c
和 --bg
)。因此,如果我们要定义 green
颜色,我们将拥有以下内容
.u-color--green {
--c: #08ffc8;
color: #08ffc8;
}
.u-bg--green {
--bg: #08ffc8;
background-color: #08ffc8;
}
如果您是 Sass 用户,您可以使用地图自动执行此过程,并循环遍历值以自动创建颜色和背景类。请注意,这不是必需的,它只是一种自动创建许多颜色相关实用程序类的方法。这非常有用,但要跟踪您的使用情况,以便您不会,例如,创建七个从未在您的网站上使用的背景类。话虽如此,以下是生成我们类的 Sass 代码
$colors: ( // Define a named list of our colors
'green': #08ffc8,
'light': #fff7f7,
'grey': #dadada,
'dark': #204969
);
@each $n, $c in $colors { // $n is the key, $c is the value
.u-color--#{$n} {
--c: #{$c};
color: #{$c};
}
.u-bg--#{$n} {
--bg: #{$c};
background-color: #{$c};
}
}
但是,如果我们在标记中忘记应用实用程序类会怎样?--c
变量将自然使用 currentColor
... --bg
也是如此!让我们定义一个顶级默认值以避免这种情况
html {
--c: #000000;
--bg: #ffffff;
}
酷!现在我们只需要样式化我们的链接即可。在本文中,我们将使用我们可靠的 <a>
元素来样式化所有链接,但您也可以轻松添加一个 .fancy-link
之类的类。
此外,您可能知道,链接应该按照“LoVe-HAte”顺序进行样式化::link
、:visited
、:hover
(和 :focus
!)以及 :active
。我们可以使用 :any-link
,但浏览器支持 并不像 CSS 自定义属性那样好。(如果情况相反,这将不是什么大问题。)
我们可以通过为较旧的浏览器提供可接受的体验,然后检查自定义属性支持来开始声明我们链接的样式
/* Styles for older browsers */
a {
color: inherit;
text-decoration: underline;
}
a:hover,
a:focus,
a:active {
text-decoration: none;
outline: .0625em solid currentColor;
outline-offset: .0625em;
}
a:active {
outline-width: .125em;
}
@supports (--a: b) { /* Check for CSS variable support */
/* Default variable values */
html {
--c: #000000;
--bg: #ffffff;
}
a {
/*
* Basic link styles go here...
*/
}
}
接下来,让我们创建基本的链接样式。我们将使用自定义属性来使我们的样式尽可能DRY。
首先,我们需要设置我们的变量。我们想要定义一个 --space
变量,该变量将用于各种属性,以在文本周围添加一些空间。链接的颜色也将使用 --link-color
在变量中定义,默认值为 currentColor
。伪下划线将使用背景图像生成,该图像的大小将根据 --bg-size
的状态进行调整,默认情况下设置为使用 --space
值。最后,为了给这个过程增添一些乐趣,我们还将在链接处于 :active
状态时使用 box-shadow
模拟链接周围的边框,因此我们将它的尺寸定义为 --shadow-size
,在其非活动状态下设置为 0
。这将为我们提供
--space: .125em;
--link-color: currentColor;
--bg-size: var(--space);
--shadow-size: 0;
我们首先需要调整回退样式。我们将设置 color
以使用我们的自定义属性,并删除默认下划线
color: var(--link-color);
text-decoration: none;
接下来,让我们创建我们的伪下划线。该图像将是一个线性渐变,具有两个相同的起点和终点:文本的颜色 --c
。我们确保它只在水平方向上重复,使用 background-repeat: repeat-x;
,并将其放置在元素的底部,使用 background-position: 0 100%;
。最后,我们给出它的尺寸,在水平方向上为 100%,在垂直方向上为 --bg-size
的值。最终我们将得到以下内容
background-image: linear-gradient(var(--c, currentColor), var(--c, currentColor));
background-repeat: repeat-x;
background-position: 0 100%;
background-size: 100% var(--bg-size);
为了我们的 :active
状态,让我们也定义一个阴影框,它将不存在,但有了我们的变量,它就可以活跃起来:box-shadow: 0 0 0 var(--shadow-size, 0) var(--c);
这就是大部分基本样式。现在,我们需要做的是根据链接状态为我们的变量分配新值。
:link
和 :visited
是用户在链接处于“空闲”状态时看到的内容。由于我们已经设置好了一切,所以这是一个简短的规则集。虽然从技术上讲,我们可以跳过此步骤并在 --link-color
的初始分配中声明 --c
变量,但我在这里分配它是为了使我们样式的每个步骤都清晰明了
a:link,
a:visited {
--link-color: var(--c);
}
现在链接看起来很酷,但如果我们与它进行交互,什么也不会发生... 让我们接下来创建这些样式。需要发生两件事:背景必须占据所有可用高度(即 100%
),并且文本颜色必须更改为背景颜色,因为背景是文本颜色(令人困惑,对吧?)。第一个很简单:--bg-size: 100%;
。对于文本颜色,我们分配 --bg
变量,如下所示:--link-color: var(--bg);
。加上我们的伪类选择器,我们最终得到
a:hover,
a:focus,
a:active {
--bg-size: 100%;
--link-color: var(--bg);
}
看看那个下划线在悬停或聚焦时变成了完整的背景!作为奖励,我们可以在单击链接时添加一个模拟边框,方法是增加 --shadow-size
,我们的 --space
变量将再次派上用场
a:active {
--shadow-size: var(--space);
}
我们现在几乎完成了!但是,它看起来有点太通用,所以让我们添加一个过渡、一些填充和圆角,并确保如果链接跨越多行,它看起来也很不错!
对于过渡,我们只需要动画化 color
、background-size
和 box-shadow
。持续时间由您决定,但考虑到链接通常大约 20 像素高,我们可以设置一个较小的持续时间。最后,为了使它看起来更平滑,让我们使用 ease-in-out
缓动。总结起来就是
transition-property: color, background-size, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease-in-out;
will-change: color, background-size, box-shadow; /* lets the browser know which properties are about to be manipulated. */
接下来,我们将 --space
变量分配给 padding
和 border-radius
,但不要担心前者——因为我们没有将其定义为 inline-block
,所以填充不会影响我们文本块的垂直节奏。这意味着您可以调整背景的高度,而无需担心行间距!(只要确保测试您的值)
padding: var(--space);
border-radius: var(--space);
最后,为了确保样式在多行上正确应用,我们只需要添加 box-decoration-break: clone;
(以及前缀,如果您需要的话),就完成了。
完成后,我们应该拥有以下样式
/* Styles for older browsers */
a {
color: inherit;
text-decoration: underline;
}
a:hover,
a:focus,
a:active {
text-decoration: none;
outline: .0625em solid currentColor;
outline-offset: .0625em;
}
a:active {
outline-width: .125em;
}
/* Basic link styles for modern browsers */
@supports (--a: b) {
/* Default variable values */
html {
--c: #000000;
--bg: #ffffff;
}
a {
/* Variables */
--space: .125em;
--link-color: currentColor;
--bg-size: var(--space);
--shadow-size: 0;
/* Layout */
padding: var(--space); /* Inline elements won't affect vertical rhythm, so we don't need to specify each direction */
/* Text styles */
color: var(--link-color);/* Use the variable for our color */
text-decoration: none; /* Remove the default underline */
/* Box styles */
border-radius: var(--space); /* Make it a tiny bit fancier ✨ */
background-image: linear-gradient(var(--c, currentColor), var(--c, currentColor));
background-repeat: repeat-x;
background-position: 0 100%;
background-size: 100% var(--bg-size);
box-shadow: 0 0 0 var(--shadow-size, 0) var(--c, currentColor); /* Used in the :active state */
box-decoration-break: clone; /* Ensure the styles repeat on links spanning multiple lines */
/* Transition declarations */
transition-property: color, background-size, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease-in-out;
will-change: color, background-size, box-shadow;
}
/* Idle states */
a:link,
a:visited {
--link-color: var(--c, currentColor); /* Use --c, or fallback to currentColor */
}
/* Interacted-with states */
a:hover,
a:focus,
a:active {
--bg-size: 100%;
--link-color: var(--bg);
}
/* Active state */
a:active {
--shadow-size: var(--space); /* Define the box-shadow size */
}
}
当然,它比仅仅有一个下划线更复杂,但与允许您始终访问文本和背景颜色的实用程序类一起使用,它是一个非常不错的渐进增强。
您可以使用三种变量为每种颜色进行增强,无论是 rgb
还是 hsl
格式,以调整不透明度等。您还可以添加一个 text-shadow
来模拟 text-decoration-skip-ink
!
如果您不使用实用程序类来应用颜色会怎样?自己看看吧!您所需要做的就是为您的变量定义一个合理的默认值。
我不明白...
您好!
如果您忘记向某个部分添加实用程序类,而该部分包含一个链接,您将在悬停/聚焦时看到问题出现。尝试删除
html
中定义的默认 CSS 变量,看看我的意思;最后一部分没有添加实用程序类。您可以确保链接仅在实用程序类上下文中工作,可以使用类似
[class*="u-bg--"] [class*="u-color--"] a
的方法,但这会增加选择器的复杂性,我想要避免在本文中进行这种操作。如果您有任何疑问,请告诉我,我很乐意为您解答!