Skip to content
This page has been auto-translated and may contain errors.View in English

文本元素 ​

docs.scrimba.com

访客在页面上读到的大部分内容,都是普通的书面文字:标题、段落、加粗的警示、一句引言、一段代码。HTML 为这些内容分别准备了专门的元素,选对元素带来的不只是外观上的变化——它还会告诉浏览器、搜索引擎和无障碍工具每一段文字究竟是什么。

标题与层级结构 ​

HTML 提供了六级**标题**,从 <h1> 一直到 <h6>。标题就是页面或页面某个部分的标题文字。<h1> 是主标题,页面最上方那个大标题;<h2> 标记一个主要章节,<h3> 标记这个章节里的子章节,依此类推直到 <h6>。

想象一本纸质书:封面上的书名是 <h1>,每一章的标题是 <h2>,章节内部的小标题是 <h3>。用这些级别来表示内容之间的从属关系。

从一开始就要记住一点:不要因为想让文字变成某个大小才选某级标题。<h1> 看起来确实很大,但它的作用是表示"这是主标题",不是"把这段文字放大"。如果你想让某处文字变大,那是以后 CSS 该做的事。

<h1> 到 <h6> 这六个标题元素,描述的是文档的**层级结构**:哪些部分是章节,哪些是子章节。数字表示的是级别,和大小没有关系。<h1> 是大纲的最顶层,<h2> 在它之下,<h3> 再在 <h2> 之下。

要早点养成的习惯是:按顺序嵌套标题,不要跳级。一个用 <h2> 标记的章节,里面应该是 <h3> 子章节,不能直接跳到 <h4>。为了得到某个默认字号而跳级,是最常见的错误,而且用错了工具:如果你想让标题呈现某种样式,用 CSS 来设置,数字应该只用来表示它在结构中的级别。

标题元素定义的是文档的**大纲结构**:各个章节按顺序排列出的层级关系,就像目录里主题下面嵌套着子主题一样。由此可以推出三条实践规则,这三条都和无障碍访问、搜索相关,而不是和外观相关。

第一,每页只用一个 <h1>,作为这页内容的真正标题。它是大纲的顶端,只保留一个能让所有工具都明确知道这页讲的是什么。

第二,往下不要跳级。屏幕阅读器(为看不见页面的人朗读内容的软件)会让用户拉出一份标题列表,在标题之间跳转,就像视力正常的读者快速浏览找到想看的章节一样。从 <h2> 跳到 <h4>,在这份列表里就像少了一级,导航也就说不通了。

第三,级别表示的是语义,而不是字号。搜索引擎会读取标题结构来理解页面的组织方式,所以如果一个 <h3> 只是因为默认字号看起来合适才被选用,而不是因为它真的是第三级章节,这就会悄悄地误导爬虫和屏幕阅读器。字号交给 CSS 设置,数字只用来传达语义。

html
<h1>新手做酸面包</h1>

<h2>制作酵头</h2>
<p>酵头是由面粉和水培养出的活性菌种。</p>

<h3>第一到第三天</h3>
<p>将等量的面粉和水混合,然后耐心等待。</p>

<h2>烤出你的第一个面包</h2>
<p>酵头一旦有活性,你就可以开始烘焙了。</p>

一个 <h1> 给出整页的标题。两个 <h2> 标记出主要章节,<h3> 恰好嵌套在第一个 <h2> 里面。只看标题的编号,不读一句正文,你就能看出这篇文章的结构。

Juno标题与层级结构 六级标题,从 <h1> 到 <h6>,<h1> 就是最上面那一个主标题,剩下的用来标记章节和子章节。我早期踩过的坑:别因为想要文字变大就随便抓一个标题元素来用,那是 CSS 该干的事。数字表示的是这段文字是什么,不是它有多大。
Juno标题与层级结构 标题是给内容分级的,不是用来调字号的。按顺序嵌套,不要为了拿到一个更小的默认字号就跳级,这是最容易让人栽跟头的地方。想让标题呈现某种样式?用 CSS,数字就专心表示结构好了。
Juno标题与层级结构 每页只用一个 <h1>,往下不跳级,也永远不要为了字号去选级别。屏幕阅读器用户在标题之间跳转,就像在看目录一样,搜索引擎读的也是同一套大纲结构,所以为了外观选的标题会同时误导两者。让数字保持语义,把外观交给 CSS。

段落与换行 ​

一段普通文字放在**段落**元素 <p> 里。把每段文字分别包在自己的 <p>...</p> 中,浏览器会在上下留一点空隙,让段落像书里那样彼此分开。

html
<p>做面包需要四样东西:面粉、水、盐和时间。</p>
<p>把这些做对了,剩下的就是耐心。</p>

注意,在 HTML 文件里按回车键对页面没有任何影响。浏览器会忽略你输入的换行和多余空格,它只关心标签。这就是为什么要用 <p> 来分隔段落,而不是把它们分行打出来。

如果你确实需要在一个段落内部换行,比如地址的每一行或者一首短诗,有个专门的 <br> 元素能做到。它只负责强制换一行,别的什么都不做。

<p> 元素装的是流动的正文段落,是承载正文内容的默认元素。浏览器会把源码里连续的空格、tab 和换行统统折叠成一个空格,所以文字在页面上的排布是由标签决定的,不是由你在文件里怎么排版决定的。

<br> 元素在一段文字中强制换行。它是一个空元素,没有闭合标签,只有当换行本身就是内容的一部分时才适合用它:比如邮政地址、诗的分行、签名区块。

html
<p>
  王丽<br>
  北京市朝阳区某某路14号<br>
  邮编 100020
</p>

<br> 不该用来做间距工具。堆两个 <br><br> 把两段文字撑开,看起来没问题,但这是个错误的直觉:那是两个段落,就应该是两个 <p> 元素,它们之间的间距属于视觉呈现,应该归 CSS 管。用 <br> 来腾空间,把结构和样式混在了一起,这个习惯值得早点改掉。

<p> 是一个块级(block-level)元素,意味着它会另起一行并占满可用的宽度,和周围的段落上下堆叠排列。它是承载一段正文的正确容器,浏览器会对它的内容做空白折叠(whitespace collapsing):源码里任何一串空格、tab 和换行,渲染时都变成一个空格。这就是为什么你在源码里怎么排版都无所谓,只要自己看得清楚就行。

<br> 表示的是属于内容本身的换行,不是布局上的空隙。这个区分带来了实际的无障碍访问成本。屏幕阅读器把 <p> 的边界当作一个段落的结束,并据此做出停顿,让用户能感知到一个想法在哪里结束、下一个想法从哪里开始。一串 <br> 元素不会产生这样的边界:软件会一口气读下去,视力正常的读者从间距中看出的结构,对听的人来说是不存在的。用空段落来当间隔符也有同样的问题——有些屏幕阅读器会把它们读成"空白",有些直接跳过,不管哪种情况,你想留出的空隙都没能传达出去。

经过真实项目验证下来的规则是:只有当换行是数据本身的一部分时才用 <br>(地址、诗句、表单标签里的一行),块与块之间的垂直间距永远用 CSS 的 margin 来做。结构承载含义,样式承载外观,把这两者分开,才能让一个页面同时做到易维护和无障碍。

Juno段落与换行 每段文字放进自己的 <p>...</p> 里,这就是段落之间会有间距的原因。浏览器会忽略你打的回车和空格,所以真正起作用的是标签。只有当一行真的需要在段落中间换行时才用 <br>,比如地址。
Juno段落与换行 段落用 <p>,浏览器会折叠源码里的空白,所以怎么排版文件本身对页面没有影响。<br> 用于属于内容本身的换行,比如地址,绝不是用来把东西撑开的。用两个 <br> 腾出空隙,就是间距从 CSS 里漏出来的信号。
Juno段落与换行<p> 是一个块,能给屏幕阅读器一个真正的段落边界供其停顿;一串 <br> 什么都给不了,结构对听的人来说就消失了。所以只有换行属于数据本身时才用 <br>,所有垂直间距都用 CSS 的 margin 来做。用空段落当间隔符也有同样的无障碍访问漏洞,同样要避免。

强调:<strong> 与 <b>、<em> 与 <i> ​

有两个元素能让文字加粗,另外两个能让文字变斜体。<strong> 和 <b> 都渲染为粗体;<em> 和 <i> 都渲染为斜体。所以是四个标签,两种外观。

html
<p><strong>警告:</strong>烤箱现在非常热。</p>
<p>你需要<em>彻底</em>揉面。</p>

现阶段,当某段文字很重要时,比如一条警告,就用**<strong>**;想强调某个词——就像大声朗读时你会加重语气的那个词——就用 <em>。这两个是你大部分时候最需要的,浏览器会自动帮你渲染成粗体和斜体。

这四个元素分成两对,区别在于语义和外观。<strong> 和 <em> 是语义化的:它们表达了这段文字的某种含义。<b> 和 <i> 是外观性的:它们只改变文字的样子。

当内容带有**重要性、严肃性或紧迫性时用 <strong>:一条警告、一个关键指示。当你要做语气强调**时用 <em>——大声读这句话时你会加重语气的那个词,这种强调有时会改变句子的含义。两者渲染出来分别是粗体和斜体,但你选它们是因为它们的含义,不是因为外观。

<b> 和 <i> 用在你只是想要粗体或斜体、但背后没有重要性或强调的场合。想让眼睛聚焦在某个关键词上,用 <b>;船名或外语短语,用 <i>。它们标记的是文字在风格上被区别对待,但不代表这段文字更重要。

html
<p><strong>切勿</strong>在系统仍处于加压状态时打开阀门。</p>
<p>她低声说这是<em>她</em>的主意,不是他的。</p>
<p>键盘快捷键是 <b>Ctrl</b> 加 <b>S</b>。</p>
<p>我们搭乘"<i>丽江号</i>"渡轮过去的。</p>

如果只记一件事:<strong> 和 <em> 是真的表达含义,<b> 和 <i> 只是外观上的表现。当文字真的很重要时,选语义化的那一对。

这四个元素默认在屏幕上渲染出来的效果是一样的——不是粗体就是斜体,所以从视觉上看它们可以互换。真正的区别在于它们向"看不到像素"的东西传达了什么信息,而选择哪个元素,恰恰取决于这一点。

<strong> 标记的是重要性:严肃、紧急,或者不能被漏看的内容。<em> 标记的是语气强调:那个改变了句子含义的重音词(比较一下"明天给我打电话"和"明天给我打电话")。屏幕阅读器可以据此做出反应。很多屏幕阅读器会在被强调的文字上改变语气或语速,<strong> 也可能被以区别于普通正文的方式呈现出来,这样你编码进去的重要性,才能真正传达给看不见粗体的人。可以嵌套使用来表达程度:<strong> 嵌在 <strong> 里表示更高的重要性,<em> 嵌在 <em> 里表示更重的语气。

<b> 和 <i> 是外观性的一对,而它们其实比"尽量别用"这种建议所暗示的更常常是正确选择。它们真正的定义范围很窄。<b> 出于实际的原因让文字引人注意,但不附带额外的重要性:摘要里的一个关键词,评测里的产品名。<i> 标记的是文字处于另一种语气或语域:第一次出现的技术术语、类似 Homo sapiens 这样的学名、一句外语短语、角色的内心想法。如果有更具体的元素可用(<cite> 表示作品标题、<dfn> 表示定义、<code> 表示代码),就该优先用那个;<b> 和 <i> 是当文字确实需要被区别对待、但又没有更强含义适用时的备选方案。

要避免的失败模式是:该用 <strong> 时用了 <b>,该用 <em> 时用了 <i>。它们外观完全一样,所以屏幕上没有任何东西提示你用错了,但你已经丢掉了无障碍工具所依赖的那份重要性或强调。要问的是这段文字意味着什么,不是它应该看起来是什么样:如果它很重要,用 <strong> 或 <em>;如果它只是需要被区别对待,用 <b> 或 <i>。

Juno强调:strong 与 b、em 与 i<strong> 和 <b> 都是加粗,<em> 和 <i> 都是斜体。刚开始学的话,某样东西重要时(比如一条警告)用 <strong>,想强调某个词时用 <em>,就像你会加重语气说话那样。这两个基本能覆盖你写的绝大多数内容。
Juno强调:strong 与 b、em 与 i<strong> 表示重要,<em> 表示强调,两者都带有含义。<b> 和 <i> 是同样的粗体和斜体,但背后不带含义,适合只是想要区别对待的文字。反正外观都一样,所以按文字的含义来选,而不是按它该长什么样来选。
Juno强调:strong 与 b、em 与 i 在屏幕上四个都是粗体或斜体;区别在于屏幕阅读器"听"到了什么。<strong> 和 <em> 编码了重要性和语气强调,可能被以不同方式播报出来,所以该用它们的地方却抓了 <b> 或 <i>,含义就悄悄丢了。<b> 和 <i> 适合只是需要被区别对待的文字——一个关键词或一个术语——而且没有更具体的元素可用时。

其他行内文字(引用、<code>、<abbr> 等) ​

除了粗体和斜体,HTML 还为一些常见的文字片段准备了小元素。一句简短的引言放进 <q>,浏览器会自动帮你加上引号。一段代码,比如某个命令的名字,放进**<code>**,浏览器会用等宽字体显示,让它和普通文字区分开来。

html
<p>我奶奶总说<q>心急吃不了热豆腐</q>。</p>
<p>用 <code>Ctrl S</code> 快捷键保存文件。</p>

这类元素还有一些,但 <q> 表示短引言、<code> 表示代码,是你最常遇到的两个。每一个都会包住一小段文字,并说明它是什么。

这些是行内元素:它们把一段文字包在段落内部,而不像 <p> 这样的块级元素那样另起一行。每一个都在说明这段文字片段是什么,所以要选用具体的元素,而不是给一个普通的 <span> 加样式来假装成这个效果。

值得了解的几个:

html
<p>这份报告两次引用了《程序员修炼之道》(<cite>The Pragmatic Programmer</cite>)。</p>
<p>运行 <code>npm install</code>,然后按 <kbd>Enter</kbd>。</p>
<p>这个房间的地面面积是 <strong>24m<sup>2</sup></strong>。</p>
<p>原价是 <del>¥280</del>,现价 <ins>¥220</ins>。</p>
<p>随着 <abbr title="HyperText Markup Language">HTML</abbr> 逐渐成熟,标签也稳定下来了。</p>

<cite> 用来标出作品的标题。<code> 标记代码,<kbd> 标记键盘输入,<samp> 标记程序输出。<sup> 和 <sub> 分别是上标和下标,用于指数、化学式之类的东西。度数符号本身就是一个字符 °,不需要用上标来表示。<del> 和 <ins> 分别标记被删除和被新增的文字,适合用来展示修改或价格变动。<abbr> 标记一个缩写,它的 title 属性存放完整的展开形式。

<q> 用于一句简短的行内引言,会自动加上引号。如果是更长、独立成段的引言,应该用 <blockquote>,它是一个块级元素。

这些都是行内元素,在一行文字内部流动,而不单独形成一个块。它们存在的意义,是让一段文字片段能在标记层面就带上自己的含义,正是这一点,让这份含义能被无障碍工具、搜索引擎,以及你自己的样式和脚本读取到。实际的做法是:用最适合的具体元素,只有当没有任何元素合适时,才退回用一个中性的 <span>。

真正会常用到的一组:

html
<p>参见《数据密集型应用系统设计》(<cite>Designing Data-Intensive Applications</cite>)第三章。</p>
<p>输入 <kbd>git status</kbd>,会看到 <samp>nothing to commit</samp>。</p>
<p>这个示例中始终使用了 <abbr title="Cascading Style Sheets">CSS</abbr> 变量。</p>
<p>修订后的数字:<del>1,200</del> <ins>1,450</ins> 条。</p>

<cite> 标记的是被引用作品(书、电影或论文)的标题,不是人名,这一点经常被用错。<code> 是一段计算机代码,<kbd> 是用户的键盘输入,这两者往往都渲染成等宽字体,但表示的是交互方向完全相反的两件事。<samp> 是程序输出的示例。<abbr> 标记一个缩写,并带有一个 title 属性存放完整的展开形式;屏幕阅读器可以朗读或提供这个展开内容,鼠标悬停时它也会显示为提示框,所以读者永远不需要去猜这几个字母代表什么。<del> 和 <ins> 表示一次修改,被移除的文字和被新增的文字,并会被相应地播报出来,这在修改本身就是重点的场合很重要,比如价格更正或者红线修订。

关于引言,<q> 是行内元素,通过 CSS 插入符合当前语言习惯的引号(这就是你不需要自己打引号的原因),而 <blockquote> 是用于大段独立引言的块级元素,两者都可以带一个可选的 cite 属性,存放来源的 URL。贯穿这些元素的共同逻辑是:元素本身承载含义,外观是你在 CSS 里单独设置的一层。按文字本身是什么去选标签,而不是按想要等宽字体或斜体的效果去选,才能让页面对那些"看不见"内容的工具依然清晰易读。

Juno其他行内文字(引用、code、abbr 等)<q> 包住一句简短引言并自动加上引号,<code> 用等宽字体显示代码,让它显得突出。这类小标签还有几个,但这两个最常遇到。每一个都包住一小段文字,并说明它是什么。
Juno其他行内文字(引用、code、abbr 等) 这些行内标签各自说明一段文字片段是什么:<code> 表示代码,<kbd> 表示按下的按键,<cite> 表示作品标题,<abbr> 配上 title 表示完整形式。用具体的那个,而不是给普通的 <span> 加样式。短引言用 <q>,独立成段的引言用 <blockquote>。
Juno其他行内文字(引用、code、abbr 等) 用最具体的行内元素,只有实在没有合适的才退回用 <span>。留意容易被用错的几个:<cite> 是作品标题,不是人名;<code> 和 <kbd> 外观相似,但表示的是交互中相反的两端。<abbr> 的 title 会被无障碍工具读出来,<q> 自带引号,所以不要自己再打一遍。