通常,CSS 和 HTML 之间的连接是 CSS 选择器匹配 HTML 元素,而 CSS 对它们进行样式设置。 CSS 不了解 HTML 中的实际内容。 但确实存在一种方法,CSS 可以获取 HTML 中的数据,只要该数据位于该 HTML 元素的属性中。
就是这样
div::after {
content: attr(data-whatever);
}
这当然很有趣。 例如,您可以将其用于(相当不可访问的)工具提示
<button data-tooltip="Information only mouse-having sighted people will see.">
Button
</button>
button:hover::after {
content: attr(data-tooltip);
/* positioned and styled and whatnot */
/* ya, a :focus style would buy you a tad more a11y */
}
但是您不能将 HTML 放入属性值中,因此这些工具提示仅限于字符串值,并且不能在其中包含标题、链接或任何其他类似内容。
这是一个更好的用例。 存在一个旧的打印样式表要点,您可以在其中使用 attr()
添加链接的 URL,以便您实际上可以查看链接的链接目标
@media (print) {
a[href]::after {
content: " (" attr(href) " )";
}
}
真聪明。 但是还有什么呢? 你能传递一种颜色吗?
<h2 data-color="#f06d06">
Custom Colored Header
</h2>
这不是无效的,但没有用。
h2 {
/* Not gonna work */
color: attr(data-color);
}
attr()
中的值是字符串。 即使该字符串与十六进制代码的格式相同,它也不会用作十六进制代码。
您也不能传递一个可以在 background-image()
等中使用的 URL。 您也不能传递像 3
、20px
或 4rem
或 0.8vw
这样的单位。
CSS 的 attr() 函数仅是字符串,而字符串仅真正用作 content
,而 content
(不可选择且有一定程度的不可访问性)本身并不是特别有用。 例如,您不能选择伪内容的文本,也不能搜索它,这使得它相当不可访问。
您知道什么可以传递任何类型的值并且与属性一样易于实现吗?
CSS 自定义属性!
您可以将它们直接放入任何元素的 style
属性中。 现在这些值对该元素可用
<button
style="
--tooltip-string: 'Ug. Tooltips.';
--tooltip-color: #f06d06;
--tooltip-font-size: 11px;
--tooltip-top: -10px
"
>
Button
</button>
我们在上面将字符串传递给 CSS,但也传递了颜色和长度值。 这些值可以立即按原样使用
button::after {
content: var(--tooltip-string);
color: var(--tooltip-color);
font-size: var(--tooltip-font-size);
}
这是该演示,其中包含一些繁琐的“逻辑”(需要大量改进才能真正有用)以允许变体
查看 CodePen 上 Chris Coyier 的 CSS 自定义属性比 attr() 更好 创作。
实际上,这并没有提高可访问性。 如果我要真正实现工具提示,我可能会 仔细阅读这篇博文。
attr() 的其他“好”用例呢?
经常出现的一个用例是响应式数据表。 想象一个表格,其中标题位于顶行,数据行位于下方
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
....
</tr>
</thead>
<tbody>
<tr>
<td>Chris</td>
<td>Coyier</td>
...
</tr>
...
</tbody>
</table>
这样的数据行在小屏幕上可能会出现问题(太宽)。 因此,在响应式数据表中,我们可能会隐藏该顶行,并改为显示每个单元格的标签。
@media (max-width: 500px) {
thead {
display: none;
}
/* Need to reveal another label now that we've hidden the normal labels */
}
该标签从哪里来? 我们可以做…
. ...
<tr>
<td data-label="First Name">Chris</td>
<td data-label="Last Name">Coyier</td>
...
</tr>
然后
td::before {
content: attr(data-label);
/* Also display: block things and such */
}
这是一个相当不错的用例。 如果我们对 <thead>
使用某种可访问的隐藏方法,它甚至可能会通过 a11y 检查。
但是,同样的操作也可以使用 CSS 自定义属性来完成……
. ...
<tr>
<td style="--label: 'First Name';">Chris</td>
<td style="--label: 'Last Name';">Chris</td>
...
</tr>
td::before {
content: var(--label);
...
}
Eric Bidelman 向我指出了一种使用伪内容显示输入值的方法。
<style>
input {
vertical-align: middle;
margin: 2em;
font-size: 14px;
height: 20px;
}
input::after {
content: attr(data-value) '/' attr(max);
position: relative;
left: 135px;
top: -20px;
}
</style>
<input type="range" min="0" max="100" value="25">
<script>
var input = document.querySelector('input');
input.dataset.value = input.value; // Set an initial value.
input.addEventListener('change', function(e) {
this.dataset.value = this.value;
});
</script>
我觉得这有点危险,因为我认为伪内容不应该对像 <input>
这样的替换元素起作用。 这可能是 output 的工作,而 JavaScript 本质上是相同的。 您可以使用额外的元素来使用伪内容,但实际上没有必要。
利用伪内容不可复制的事实也很巧妙。 例如,GitHub 使用 data-line-number=""
和 ::before { content: attr(data-line-number); }
进行代码块行号。

当他们尝试复制代码时,没有人喜欢选择行号! 这里很好用(可能比 CSS 计数器更灵活),但同样,CSS 自定义属性也可以处理。
<td style="--line-num: 5"> ... </td>
您可以争辩说这更好,因为如果您确实想要使用 CSS 计数器,您可以使用第一个值来启动,而不需要在每一行上使用它。
查看 CodePen 上 Chris Coyier 的 行号 创作。
与涉及在 CSS 中复制文本以进行样式设置的印刷技巧相同。 查看 Mandy Michael 使用 attr()
的 酷炫演示。 我相信您可以想象 --heading: "Fracture";
如何在那里发挥作用。
CSS3 值规范(在候选推荐中)有一种方法可以使 attr() 有用
我不确定这是否很重要,因为我认为 CSS 自定义属性几乎完全替代了 attr()
,但规范确实 专门介绍了这一点,可能是为了使其更有用。
想法是在 CSS 中获取值时设置值类型。
<div data-color="red">Some Words</div>
div {
color: attr(data-color color);
}
或者…
<span data-size="50">span</span>
span {
font-size: attr(data-size px);
}
但据我所知,没有浏览器支持此功能。
这不是 css 技巧。 这已经进入了 css 黑魔法的领域。
+1 CSS 向导
我昨天刚用 attr() 函数结合 abbr 标签。 花费了一些时间,但它在移动尺寸下显示缩写,在平板电脑和台式机尺寸下显示完整单词。 用于显示带星期几和月份的日期。
完全明白你的意思,但从什么时候开始,直接使用内联样式会更有意义? 我想如果你需要在多个地方重用该值,那么使用自定义属性更有意义,但在列出的示例中,您可以轻松地直接编写内联样式。
我同意,这确实回到了使用内联样式,内联样式会更容易。 我认为使用自定义属性只是增加了酷炫因素。
没错 - 但当你想向伪元素提供属性时,它确实帮助很大。 解决了我的一个长期设计问题 - 一个透明的狗耳 https://codepen.io/scootman/pen/XzpbGK。 不使用自定义属性也可以实现 - 但 HTML 太繁琐了
关于工具提示示例,将内容放入内联样式中以进行自定义属性解决方法感觉太hacky 了。 不如这样做更容易且更易访问?
别误会 - 内联样式和自定义属性对于非字符串内容来说是一个很酷的技巧,但你给出的示例的第二个版本与第一个版本一样不可访问。
是的,自定义属性仅仅通过使用它们本身并没有带来任何 a11y。 aria-label 似乎是一个非常棒的属性,可以用于它们! 当然比
title
好,因为title
的样式无法控制。我认为 aria-label 是这里最好的选择。 感谢你的提示。
听着,attr 可以与 jquery 一起使用。 例如,如果你想更改图标的背景,你可以使用 attr 进行操作。 我会展示给你
$(“#button”).on(“mouseenter”, function(e) {
$(this).animate….attr(“diffuse-color”, “red”); });
这会使背景动画化。 使用测试用例
我认为你想说的是:JavaScript 可以访问属性的值并在你预期的方式使用该值,例如,将字符串用作颜色值。
是的,JavaScript 可以做到。
CSP 呢?
内容安全策略?
你想详细说明一下吗?
CSS3 Values 规范更好,因为它允许我们在不从单个样式属性中剪切字符串的情况下设置/删除属性。
a11y?!
W1y?
;)
顺便说一句,我喜欢上面的东西。并且同意 Goose 的观点,它确实是黑魔法!我最喜欢的提示类型。:)
很好的例子,我特别喜欢链接的 @media (print) 例子,之前没有见过或想过,太酷了!:D
我从这篇文章中学到了三件事。
attr()
始终只提供字符串,这就是它不适用于颜色等的原因。我现在明白了 lolcounter-reset
和counter-increment
属性的存在。太棒了!你可以在
style
属性中覆盖自定义属性。同样,太棒了!感谢 Chris。
你错过了一个用例——只有新的规范才能涵盖它——即更优雅地设置 CSS 变量。
例如,在一个网格上(我相信有更好的用例,例如通过属性传递动态颜色)
请参阅以下示例:https://jsfiddle.net/nilssolanki/z7r46n8k/