属性

HTML 概览中简要讨论了属性;现在是深入研究的时候了。

属性是使 HTML 如此强大的原因。属性是在开始标记中以空格分隔的名称和名称/值对,它们提供有关元素的信息和功能。

The opening tag, attributes, and closing tag, labelled on an HTML element.

属性定义了元素的行为、链接和功能。有些属性是全局属性,这意味着它们可以出现在任何元素的开始标记中。其他属性适用于多个元素但并非全部,而另一些属性是元素特定的,仅与单个元素相关。在 HTML 中,除了布尔属性和某种程度上的枚举属性外,所有属性都需要一个值。

如果属性值包含空格或特殊字符,则该值必须用引号引起来。出于这个原因,并且为了提高可读性,始终建议使用引号。

虽然 HTML 不区分大小写,但某些属性值区分大小写。属于 HTML 规范一部分的值不区分大小写。定义的字符串值(例如 class 和 id 名称)区分大小写。如果属性值在 HTML 中区分大小写,则当在 CSS 和 JavaScript 中用作属性选择器的一部分时,它也区分大小写;否则,它不区分大小写。

<!-- the type attribute is case insensitive: these are equivalent -->
<input type="text">
<input type="TeXt">

<!-- the id attribute is case sensitive: they are not equivalent -->
<div id="myId">
<div id="MyID">

布尔属性

如果存在布尔属性,则它始终为 true。布尔属性包括 autofocusinertcheckeddisabledrequiredreversedallowfullscreendefault, loopautoplaycontrolsmutedreadonlymultiple,selected。如果存在这些属性中的一个(或多个),则元素被禁用、必填、只读等。如果不存在,则不是。

布尔值可以省略,设置为空字符串,或为属性的名称;但该值不必实际设置为字符串 truetruefalse😀 等所有值(虽然无效)都将解析为 true。

以下三个标记是等效的

<input required>
<input required="">
<input required="required">

如果属性值为 false,则省略该属性。如果属性为 true,则包含该属性,但不提供值。例如,required="required" 在 HTML 中不是有效值;但由于 required 是布尔值,因此无效值解析为 true。但是,由于无效的枚举属性不一定解析为与缺失值相同的值,因此养成省略值的习惯比记住哪些属性是布尔值与枚举值并可能提供无效值更容易。

在 true 和 false 之间切换时,请使用 JavaScript 完全添加和删除属性,而不是切换值。

const myMedia = document.getElementById("mediaFile");
myMedia.removeAttribute("muted");
myMedia.setAttribute("muted");

请注意,在 XML 语言(如 SVG)中,所有属性都需要包含一个值,包括布尔属性。

枚举属性

枚举属性有时会与布尔属性混淆。它们是 HTML 属性,具有一组有限的预定义有效值。与布尔属性一样,如果属性存在但值缺失,它们具有默认值。例如,如果包含 <style contenteditable>,则默认值为 <style contenteditable="true">

但是,与布尔属性不同,省略属性并不意味着它为 false;存在但缺少值的属性不一定为 true;无效值的默认值不一定与空字符串相同。继续该示例,如果缺少或无效,contenteditable 默认值为 inherit,并且可以显式设置为 false

默认值取决于属性。与布尔值不同,属性在存在时不会自动“true”。如果包含 <style contenteditable="false">,则该元素不可编辑。如果值无效,例如 <style contenteditable="😀">,或者令人惊讶的是 <style contenteditable="contenteditable">,则该值无效,并且默认值为 inherit

在大多数情况下,对于枚举属性,缺失值和无效值是相同的。例如,如果 <input> 上的 type 属性缺失、存在但没有值或具有无效值,则默认值为 text。虽然此行为很常见,但它不是规则。因此,了解哪些属性是布尔值与枚举值非常重要;尽可能省略值,以免出错,并根据需要查找值。

全局属性

全局属性是可以设置在任何 HTML 元素上的属性,包括 <head> 中的元素。有超过 30 个全局属性。虽然理论上所有这些属性都可以添加到任何 HTML 元素,但某些全局属性在设置在某些元素上时无效;例如,在 <meta> 上设置 hidden,因为元内容不显示。

id

全局属性 id 用于定义元素的唯一标识符。它有许多用途,包括:- 链接的片段标识符的目标。- 标识用于脚本编写的元素。- 将表单元素与其标签关联。- 为辅助技术提供标签或描述。- 在 CSS 中使用(高特异性或作为属性选择器)定位样式。

id 值是一个不带空格的字符串。如果它包含空格,则文档不会中断,但您必须在 HTML、CSS 和 JS 中使用转义字符来定位 id。所有其他字符都有效。id 值可以是 😀.class,但这不是一个好主意。为了使您当前和未来的编程更轻松,请使 id 的第一个字符为字母,并且仅使用 ASCII 字母、数字、_-。最佳实践是提出一个 id 命名约定,然后坚持下去,因为 id 值区分大小写。

id 在文档中应该是唯一的。如果 id 被多次使用,则页面的布局可能不会中断,但您的 JavaScript、链接和元素交互可能无法按预期运行。

导航栏包含四个链接。我们将在稍后介绍链接元素,但现在,请注意链接不限于基于 HTTP 的 URL;它们可以是当前文档(或其他文档)中页面各部分的片段标识符。

在机器学习研讨会网站上,页面标题中的导航栏包含四个链接

href 属性提供激活链接后用户将被定向到的超链接。当 URL 包含井号 (#) 后跟一串字符时,该字符串是片段标识符。如果该字符串与网页中元素的 id 匹配,则该片段是该元素的锚点或书签。浏览器将滚动到定义锚点的位置。

这四个链接指向我们页面中由其 id 属性标识的四个部分。当用户单击导航栏中的四个链接中的任何一个时,由片段标识符链接到的元素(包含匹配 id 减去 # 的元素)会滚动到视图中。

机器学习研讨会的 <main> 内容有四个带有 id 的部分。当网站访问者单击 <nav> 中的链接之一时,带有该片段标识符的部分将滚动到视图中。标记类似于

<section id="reg">
  <h2>Machine Learning Workshop Tickets</h2>
</section>

<section id="about">
  <h2>What you'll learn</h2>
</section>

<section id="teachers">
  <h2>Your Instructors</h2>
  <h3>Hal 9000 <span>&amp;</span> EVE</h3>
</section>

<section id="feedback">
  <h2>What it's like to learn good and do other stuff good too</h2>
</section>

比较 <nav> 链接中的片段标识符,您会注意到每个标识符都与 <main><section>id 匹配。浏览器为我们提供了一个免费的“页面顶部”链接。设置 href="#top"(不区分大小写)或仅设置 href="#",将使用户滚动到页面顶部。

href 中的井号分隔符不是片段标识符的一部分。片段标识符始终是 URL 的最后一部分,并且不会发送到服务器。

CSS 选择器

在 CSS 中,您可以使用 id 选择器(例如 #feedback)或使用区分大小写的属性选择器 [id="feedback"](以降低特异性)来定位每个部分。

脚本编写

在 MLW.com 上,有一个仅供鼠标用户使用的彩蛋。单击电灯开关会切换页面的打开和关闭状态。

电灯开关图像的标记为:html <img src="svg/switch2.svg" id="switch" alt="light switch" class="light" /> id 属性可以用作 getElementById() 方法的参数,并且与 # 前缀一起,用作 querySelector()querySelectorAll() 方法的参数的一部分。

const switchViaID = document.getElementById("switch");
const switchViaSelector = document.querySelector("#switch");

我们的一个 JavaScript 函数利用了通过元素的 id 属性来定位元素的能力

<script>
  /* switch is a reserved word in js, so we us onoff instead */
  const onoff = document.getElementById('switch');
  onoff.addEventListener('click', function(){
    document.body.classList.toggle('black');
  });
</script>

<label>

HTML <label> 元素具有一个 for 属性,该属性的值是与其关联的表单控件的 id。通过在每个表单控件上包含 id 并将每个表单控件与标签的 for 属性配对来创建显式标签,可确保每个表单控件都具有关联的标签。

虽然每个标签只能与一个表单控件关联,但一个表单控件可以有多个关联的标签。

如果表单控件嵌套在 <label> 开始和结束标记之间,则不需要 forid 属性:这称为“隐式”标签。标签让所有用户都知道每个表单控件的用途。

<label>
  Send me a reminder <input type="number" name="min"> before the workshop resumes
</label>.

forid 之间的关联使辅助技术用户可以使用该信息。此外,单击标签上的任何位置都会使焦点转移到关联的元素,从而扩大控件的点击区域。这不仅对那些有灵活性问题导致鼠标操作不太准确的人有帮助;它还有助于每个手指比单选按钮宽的移动设备用户。

在此代码示例中,虚假测验的虚假第五个问题是一个单选多项选择题。每个表单控件都有一个显式标签,每个标签都有一个唯一的 id。为了确保我们不会意外重复 id,id 值是问题编号和值的组合。

当包含单选按钮时,由于标签描述了单选按钮的值,我们将所有同名按钮都包含在 <fieldset> 中,其中 <legend> 是整个集合的标签或问题。

其他无障碍功能用途

在无障碍功能和可用性中使用 id 不限于标签。在文本简介中,通过引用 <h2>id 作为 <section>aria-labelledby 的值来提供可访问的名称,从而将 <section> 转换为区域地标

<section id="about" aria-labelledby="about_heading">
<h2 id="about_heading">What you'll learn</h2>

有超过 50 个 aria-* 状态和属性可用于确保无障碍功能。aria-labelledbyaria-describedbyaria-detailsaria-owns 将空格分隔的 id 引用列表作为其值。aria-activedescendant 标识当前聚焦的后代元素,它将单个 id 引用作为其值:即具有焦点的单个元素的 id 引用(一次只能聚焦一个元素)。

class

class 属性提供了一种使用 CSS(和 JavaScript)定位元素的附加方法,但在 HTML 中没有其他用途(尽管框架和组件库可能会使用它们)。class 属性将其值作为元素区分大小写的类的空格分隔列表。

构建良好的语义结构可以根据元素的放置位置和功能来定位元素。良好的结构可以使用后代元素选择器、关系选择器和属性选择器。当您在本节中学习有关属性的知识时,请考虑如何设置具有相同属性或属性值的元素的样式。并不是说您不应该使用 class 属性,而是大多数开发人员没有意识到他们通常不需要这样做。

到目前为止,MLW 尚未使用任何类。一个网站可以不使用单个类名称就启动吗?我们拭目以待。

style

style 属性允许应用内联样式,这些样式应用于设置了该属性的单个元素。style 属性将其值作为 CSS 属性值对,该值的语法与 CSS 样式块的内容相同:属性后跟一个冒号(就像在 CSS 中一样),分号结束每个声明,位于值之后。

样式仅应用于设置了该属性的元素,后代继承继承的属性值,除非嵌套元素或 <style> 块或样式表上的其他样式声明覆盖了这些值。由于该值包含应用于该元素的单个样式块的内容的等效项,因此它不能用于生成的内容,创建关键帧动画或应用任何其他 at-rules。

虽然 style 确实是一个全局属性,但不建议使用它。而是在单独的文件中定义样式。也就是说,style 属性在开发期间可以派上用场,以实现快速样式设置,例如用于测试目的。然后获取“解决方案”样式并将其粘贴到您链接的 CSS 文件中。

tabindex

tabindex 属性可以添加到任何元素,以使其能够接收焦点。tabindex 值定义是否将其添加到制表符顺序中,以及(可选)添加到非默认制表符顺序中。

tabindex 属性将其值作为整数。负值(约定是使用 -1)使元素能够接收焦点(例如通过 JavaScript),但不会将该元素添加到制表符序列中。tabindex 值为 0 使元素可聚焦并通过制表符访问,从而将其添加到页面源代码顺序的默认制表符顺序中。值为 1 或更大值会将元素置于优先级焦点序列中,不建议使用。

在此页面上,有一个使用 <share-action> 自定义元素作为 <button> 的共享功能。包含零的 tabindex 是为了将自定义元素添加到键盘默认制表符顺序中

<share-action authors="@estellevw" data-action="click" data-category="web.dev" data-icon="share" data-label="share, twitter" role="button" tabindex="0">
  <svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
    <use href="#shareIcon" />
  </svg>
  <span>Share</span>
</share-action>

buttonrole 会告知屏幕阅读器用户,此元素应像按钮一样工作。JavaScript 用于确保按钮功能承诺得到兑现;包括处理 clickkeydown 事件以及处理 Enter 和空格键按键。

表单控件、链接、按钮和 可编辑内容 元素能够接收焦点;当键盘用户按下 Tab 键时,焦点会移动到下一个可聚焦元素,就好像它们设置了 tabindex="0" 一样。其他元素默认情况下不可聚焦。将 tabindex 属性添加到这些元素使它们能够在原本不会聚焦时接收焦点。

如果文档包含 tabindex1 或更大的元素,则这些元素包含在单独的制表符序列中。正如您将在 codepen 中注意到的那样,制表符首先在单独的序列中开始,按从最低值到最高值的顺序排列,然后再按源代码顺序在常规序列中进行。

更改制表符顺序可能会产生非常糟糕的用户体验。这使得依赖辅助技术(键盘和屏幕阅读器)来导航您的内容变得困难。作为开发人员,管理和维护也很困难。焦点很重要;有一个完整的模块讨论焦点和焦点顺序。

role

role 属性ARIA 规范的一部分,而不是 WHATWG HTML 规范role 属性可用于为内容提供语义含义,从而使屏幕阅读器可以告知网站用户对象预期的用户交互。

有一些常见的 UI 小部件,例如 组合框菜单栏选项卡列表树形网格,它们没有原生 HTML 等效项。例如,在创建选项卡式设计模式时,可以使用 tabtablisttabpanel 角色。可以实际看到用户界面的人已经通过经验了解了如何导航小部件,并通过单击关联的选项卡使不同的面板可见。当使用一组按钮来显示不同的面板时,在 <button role="tab"> 中包含 tab 角色,可以让屏幕阅读器用户知道当前具有焦点的 <button> 可以将相关面板切换到视图中,而不是实现典型的按钮式功能。

role 属性不会更改浏览器行为或改变键盘或指针设备交互 - 将 role="button" 添加到 <span> 不会将其变成 <button>。这就是为什么建议将语义化 HTML 元素用于其预期用途的原因。但是,当无法使用正确的元素时,role 属性使在非语义化元素被改装为语义化元素角色时告知屏幕阅读器用户成为可能。

contenteditable

contenteditable 属性设置为 true 的元素是可编辑的、可聚焦的,并且会添加到制表符顺序中,就好像设置了 tabindex="0" 一样。Contenteditable 是一个枚举属性,支持值 truefalse,如果属性不存在或具有无效值,则默认值为 inherit

以下三个开始标记是等效的

<style contenteditable>
<style contenteditable="">
<style contenteditable="true">

如果包含 <style contenteditable="false">,则该元素不可编辑(除非它默认情况下是可编辑的,例如 <textarea>)。如果值无效,例如 <style contenteditable="😀"><style contenteditable="contenteditable">,则该值默认值为 inherit

要在状态之间切换,请查询 HTMLElement.isContentEditable 只读属性的值。

const editor = document.getElementById("myElement");
if(editor.contentEditable) {
  editor.setAttribute("contenteditable", "false");
} else {
  editor.setAttribute("contenteditable", "");
}

或者,可以通过将 editor.contentEditable 设置为 truefalseinherit 来指定此属性。

全局属性可以应用于所有元素,甚至 <style> 元素。您可以使用属性和少量 CSS 来制作实时 CSS 编辑器。

<style contenteditable>
style {
  color: inherit;
  display:block;
  border: 1px solid;
  font: inherit;
  font-family: monospace;
  padding:1em;
  border-radius: 1em;
  white-space: pre;
}
</style>

尝试将 stylecolor 更改为 inherit 以外的其他值。然后尝试将 style 更改为 p 选择器。不要删除 display 属性,否则样式块将消失。

自定义属性

我们仅触及了 HTML 全局属性的表面。还有更多属性仅适用于一个或一组有限的元素。即使有数百个定义的属性,您可能仍然需要规范中没有的属性。HTML 可以满足您的需求。

您可以通过添加 data- 前缀来创建任何您想要的自定义属性。您可以将您的属性命名为任何以 data- 开头的名称,后跟任何不以 xml 开头且不包含冒号 (:) 的小写字符系列。

虽然 HTML 具有容错性,并且如果您创建不以 data 开头的非支持属性,或者即使您以 xml 开头或包含 : 开头的自定义属性,HTML 也不会中断,但创建以 data- 开头的有效自定义属性是有好处的。使用自定义数据属性,您知道您不会意外地使用现有属性名称。自定义数据属性是面向未来的。

虽然浏览器不会为任何特定的 data- 前缀属性实现默认行为,但有一个内置的 dataset API 可以迭代您的自定义属性。自定义属性是使用 JavaScript 传达应用程序特定信息的绝佳方式。以 data-name 的形式将自定义属性添加到元素,并使用元素上的 dataset[name] 通过 DOM 访问这些属性。

<blockquote data-machine-learning="workshop"
  data-first-name="Blendan" data-last-name="Smooth"
  data-formerly="Margarita Maker" data-aspiring="Load Balancer"
  data-year-graduated="2022">
  HAL and EVE could teach a fan to blow hot air.
</blockquote>

您可以使用 getAttribute() 使用完整的属性名称,或者您可以利用更简单的 dataset 属性。

el.dataset["machineLearning"]; // workshop
e.dataset.machineLearning; // workshop

dataset 属性返回每个元素的 data- 属性的 DOMStringMap 对象。<blockquote> 上有多个自定义属性。dataset 属性意味着您不需要知道这些自定义属性是什么即可访问它们的名称和值

for (let key in el.dataset) {
  customObject[key] = el.dataset[key];
}

本文中的属性是全局属性,这意味着它们可以应用于任何 HTML 元素(尽管并非所有属性都对这些元素有影响)。接下来,我们将深入研究链接,了解我们未解决的介绍图像中的两个属性 - targethref - 以及其他几个元素特定的属性。

检查您的理解情况

测试您对属性的知识。

id 在文档中应该是唯一的。

错误
再试一次。
正确
正确!

选择格式正确的自定义属性。

data-birthday
正确
birthday
再试一次。
data:birthday
再试一次