介绍
HTML 元素可以具有用于各种目的的属性,从辅助功能信息到样式控制。
<!-- We can use the `class` for styling in CSS, and we've also make this into a landmark region -->
<div class="names" role="region" aria-label="Names"></div>
不鼓励的是自己发明属性,或将现有属性用于无关的功能。
<!-- `highlight` is not an HTML attribute -->
<div highlight="true"></div>
<!-- `large` is not a valid value of `width` -->
<div width="large">
这样做有很多不好的理由。 您的 HTML 将变得无效,这可能不会造成任何实际的负面影响,但会剥夺您拥有有效 HTML 的温暖模糊的感觉。 最有说服力的理由是 HTML 是一种不断发展的语言,即使今天没有作用的属性和值并不意味着它们将来永远不会有作用。
不过,好消息是:您可以自己发明属性。 您只需要在它们前面加上 data-*
前缀,然后就可以随心所欲地使用它们了!
语法
能够自己发明 HTML 属性并将自己的信息放入其中非常方便。 幸运的是,您可以做到! 这正是数据属性的作用。 它们是这样的
<!-- They don't need a value -->
<div data-foo></div>
<!-- ...but they can have a value -->
<div data-size="large"></div>
<!-- You're in HTML here, so careful to escape code if you need to do something like put more HTML inside -->
<li data-prefix="Careful with HTML in here."><li>
<!-- You can keep dashing if you like -->
<aside data-some-long-attribute-name><aside>
数据属性通常被称为 data-*
属性,因为它们总是以这种格式出现。 data
这个词,然后是一个连字符 -
,然后是您可以自己定义的其他文本。
data
属性吗?
您可以单独使用 <div data=""></div>
这可能不会造成任何伤害,但您将无法使用我们将在本指南后面介绍的 JavaScript API。 您实际上是在为自己定义一个属性,正如我在介绍中提到的,这样做是不鼓励的。
数据属性的不当用法
存储应该可访问的内容。 如果内容应该在页面上显示或读取,不要只将它们放入数据属性中,还要确保这些内容在 HTML 内容中也存在。
<!-- This isn't accessible content -->
<div data-name="Chris Coyier"></div>
<!-- If you need programmatic access to it but shouldn't be seen, there are other ways... -->
<div>
<span class="visually-hidden">Chris Coyier</span>
</div>
使用数据属性进行样式设置
CSS 可以根据属性及其值选择 HTML 元素。
/* Select any element with this data attribute and value */
[data-size="large"] {
padding: 2rem;
font-size: 125%;
}
/* You can scope it to an element or class or anything else */
button[data-type="download"] { }
.card[data-pad="extra"] { }
这很有吸引力。 HTML/CSS 中的主要样式挂钩是类,虽然类很棒(它们具有中等特异性,并且通过 classList
提供不错的 JavaScript 方法),但元素要么存在要么不存在(本质上是开或关)。 使用 data-*
属性,您获得了开/关功能以及在同一特异性级别上根据属性值进行选择的能力。
/* Selects if the attribute is present at all */
[data-size] { }
/* Selects if the attribute has a particular value */
[data-state="open"],
[aria-expanded="true"] { }
/* "Starts with" selector, meaning this would match "3" or anything starting with 3, like "3.14" */
[data-version^="3"] { }
/* "Contains" meaning if the value has the string anywhere inside it */
[data-company*="google"] { }
属性选择器的特异性
它与类完全相同。 我们通常将特异性视为一个四部分值
内联样式、ID、类/属性、标签
因此,单个属性选择器本身的特异性为 0, 0, 1, 0。 类似于这样的选择器
div.card[data-foo="bar"] { }
…的特异性为 0, 0, 2, 1。 2 是因为有一个类(.card
)和一个属性([data-foo="bar"]
),1 是因为有一个标签(div
)。
属性选择器的特异性低于 ID,高于元素/标签,与类相同。
不区分大小写的属性值
如果您需要校正数据属性中可能存在的大小写不一致,属性选择器为此提供了一个不区分大小写的变体。
/* Will match
<div data-state="open"></div>
<div data-state="Open"></div>
<div data-state="OPEN"></div>
<div data-state="oPeN"></div>
*/
[data-state="open" i] { }
它是在方括号选择器中的小 i
。
在视觉上使用数据属性
CSS 允许您提取数据属性值,并在需要时显示它。
/* <div data-emoji="✅"> */
[data-emoji]::before {
content: attr(data-emoji); /* Returns '✅' */
margin-right: 5px;
}
样式设置示例用例
您可以使用数据属性来指定网格容器要包含多少列。
<div data-columns="2"></div>
<div data-columns="3"></div>
<div data-columns="4"></div>
在 JavaScript 中访问数据属性
与任何其他属性一样,您可以使用通用方法 getAttribute
访问其值。
let value = el.getAttribute("data-state");
// You can set the value as well.
// Returns data-state="collapsed"
el.setAttribute("data-state", "collapsed");
但数据属性也有自己的特殊 API。 假设您有一个具有多个数据属性的元素(这完全没问题)
<span
data-info="123"
data-index="2"
data-prefix="Dr. "
data-emoji-icon="🏌️♀️"
></span>
如果您对该元素有引用,您可以像这样设置和获取属性
// Get
span.dataset.info; // 123
span.dataset.index; // 2
// Set
span.dataset.prefix = "Mr. ";
span.dataset.emojiIcon = "🎪";
请注意最后一行中的 camelCase 用法。 它会自动将 HTML 中的 kebab 样式属性(例如 data-this-little-piggy
)转换为 JavaScript 中的 camelCase 样式(例如 dataThisLittlePiggy
)。
从某种意义上说,这个 API 不如 classList
那样好用,后者具有清晰的 add
、remove
、toggle
和 replace
方法,但它也比没有好。
您还可以访问内联数据集
<img src="spaceship.png"
data-ship-id="324" data-shields="72%"
onclick="pewpew(this.dataset.shipId)">
</img>
数据属性中的 JSON 数据
<ul>
<li data-person='
{
"name": "Chris Coyier",
"job": "Web Person"
}
'></li>
</ul>
为什么不呢? 它只是一个字符串,并且可以将其格式化为有效的 JSON(注意引号等)。 您可以提取这些数据,并根据需要对其进行解析。
const el = document.querySelector("li");
let json = el.dataset.person;
let data = JSON.parse(json);
console.log(data.name); // Chris Coyier
console.log(data.job); // Web Person
JavaScript 用例
其概念是您可以使用数据属性将 JavaScript 可能需要访问的信息放入 HTML 中,以执行某些操作。
一个常见的用例与数据库功能有关。 假设您有一个“点赞”按钮
<button data-id="435432343">♡</button>
该按钮可以在其上设置一个单击处理程序,该处理程序执行一个 Ajax 请求到服务器,以在单击时递增数据库中的点赞次数。 它知道要更新哪个记录,因为它从数据属性中获取了该信息。
规格
- 选择器级别 4 (工作草案)
- 选择器级别 3 (推荐)
- 选择器级别 2,修订版 1 (初始定义)
浏览器支持
此浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器从该版本开始支持该功能。
桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
7 | 6 | 11 | 12 | 5.1 |
移动/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
127 | 127 | 3 | 5.0-5.1 |
我假设你也可以做
我认为现在还不行。我认为
attr()
仅适用于content
属性,它可能与类型有关(例如,我们需要一种方法来指定属性是数字、长度还是其他内容,而不是字符串)。数据属性中的 JSON 数据(或任何其他数据)……。
我使用 data-attribute 通过 PHP 从后端 SQL-DB 传输数据到我的 Web 客户端。因为我无法对要传输的数据做出任何假设,所以在将其作为 data-attribute 的值放在 ' ' 或 "" 中之前,我将其进行 base64 编码。这样,我可以避免任何转义狂欢来确保数据到达客户端。在客户端使用数据时,我使用 base64 解码来获取数据。
此致
IMO 这已经走得太远了。尤其是在使用 PHP 时,只需对数据使用
htmlspecialchars()
(可能使用ENT_QUOTES
标志)就足以保证你不会遇到任何转义问题。这样做的优点是不必在 JavaScript 方面进行任何解码——只需访问
element.dataset.name
即可获取正确的数据,所有编码的字符都已由浏览器解码。嗨,弗洛里安
这是真的,看起来有点过分,但我感觉是在“更安全”的一边,因为我没有改变原始数据,我只是按原样传输数据,不做任何使用假设。
我在后端不知道客户端是否会呈现数据,或者将其用于正则表达式、传递给其他过程或其他任何操作……。
干杯
哇,很棒的帖子。我喜欢你的完整指南。作为一名自学成才的开发者,我经常发现我通过经验只知道这些指南中每个部分的 50%,但全面了解对我有很大帮助!
我不知道这些东西有一个 JavaScript API,也不知道你可以在 CSS 中选择那么多选项。非常酷。
这篇文章真的很棒。谢谢你的写作。我喜欢底部的绿灯。
应该指出,Internet Explorer 或旧版 Edge 不支持不区分大小写的属性值。
与 Can I use 的说法相反,它确实在 Chromium Edge 中起作用
https://caniuse.cn/#feat=mdn-css_selectors_attribute_case_insensitive_modifier
这是一个非常有用的指南,谢谢你,克里斯!
受到启发,我尝试创建一个 CSS 系统,用户可以使用 data-attribute 指定他们想要的行(就像你的示例一样),然后在 grid-template-columns 中使用 attr(data-columns) 来获得类似于:grid-template-columns: repeat(attr(data-columns), 1fr); 的东西
我认为这将是快速从 HTML 定义网格的一种非常好的方法,但不幸的是这不起作用,你知道如何在不为所有可能选项编写 CSS 的情况下实现类似功能,还是我遗漏了什么?
很棒的文章。感谢分享!
Cómo puedo colorear la sintaxis de mi código fuente, así como aparece en vuestra página web , para dar ejemplos.
https://prism.npmjs.net.cn
有没有办法在属性以特定文本开头的元素上获取 JavaScript 或 jQuery 点击事件?例如“data-gtm-event-“
另一个用例
通过 js 控制错误消息。
就像用于属性的目标是具有指定 ID 的输入一样,你可以填充它引用的 ID 的任何错误消息。
我还将添加一个
aria-live
属性到<p>
来告诉屏幕阅读器任何更改。使用 data-attribute 是否可以提高网站的 SEO,或者它无关紧要?
我无法使这段代码正常工作
<div class="box" data-width="150">Some content..</div>
<style>
.box{
position:absolute;
left: attr(data-width px);
}
</style>
是否可以使用这种方式设置“left”属性的值?
是的,这是因为
attribute()
不受left
属性的支持。这必须放在伪元素的content
属性上才能输出数字。attr(data-something) 在 ::after{} 和 ::befor{} 中起作用。
你可以这样在内容中编写属性
div[data-smth]
[data-smth]::after or before::{
content: attr(data-smth);
}
如果你需要像你的样式,只需在 js 中使用 js,而不是在 js 中,因为它们很难实现
只是想知道还有没有其他选择器,我希望大于,但即使是不等于也很好