写网页的时候碰到一段文字想突出一下,是加粗好还是倾斜好?更纠结的是,有时候想又加粗又倾斜,甚至还想加下划线,这堆标签摞在一起会不会出幺蛾子?HTML里专门管强调的 <strong> 和 <em> 这俩兄弟,看着像实则各有各的脾气。一个管“这事儿很要紧”,一个管“读的时候重音放这儿”。弄混了不光语义跑偏,屏幕 reader 念出来也怪怪的。更别说那种嵌套来嵌套去的骚操作,纯属给自己挖坑。这篇就掰扯掰扯这俩标签的正确打开方式,顺带教几招用 CSS 兜底的法子,让代码既干净又扛造。
以前碰上个老板,贼拉喜欢给文字加各种强调效果。那时候还没可视化编辑器,得手写 HTML 标签。那家伙整出来的东西大概是这样的:<p>I used to have this boss who <em>loved</em>, <strong>loved</strong>, <strong><em>loved</em></strong>, <strong><em><u>loved</u></em></strong> to emphasize words.</p> 一个词上叠了加粗、倾斜、下划线,看着就像在喊麦。这活儿干多了就琢磨,费劲巴拉写这么一长串,到底图个啥?浏览器渲染出来倒是没啥毛病,但语义上已经乱成一锅粥了。
啥是strong和em
HTML5 给 <strong> 和 <em> 划了明确的道。 <strong> 代表“强重要性、紧急性或严重性”,好比路边立个“前方施工,禁止通行”的牌子,内容本身就有份量。 <em> 则是“重音强调”,相当于说话时把某个词咬得特别重,比如“我吃了整整一盘子卷饼”跟“我吃了整整一盘子卷饼”,重音落不同地方,整句话意思就变了。前者强调数量多,后者强调是“一盘子”而不是几个。这俩标签给的都不是视觉效果,而是语义上的额外信息。
视觉样式别硬套语义标签
很多人一看到想倾斜的文字就扔个 <em>,想加粗就甩个 <strong>,这属于用跑鞋去踩水坑——路子不对。纯视觉的斜体应该用 <i> 标签,纯视觉的粗体用 <b> 标签。这俩老伙计在 HTML5 里被重新定义了:它们只改样式,不加任何语义重量。举个例子,引用一部电影名 <i>阿凡达:水之道</i> 就不需要屏幕阅读器加重语气读出来。还有 <cite> 用来标来源,<address> 用来放联系方式,这些标签渲染出来也是斜体,但语义完全不同。
处理引用块的时候经常踩坑。很多人喜欢给 <blockquote> 全局加斜体样式:
blockquote {
font-style: italic;
}这时候如果引用内容里提到一部电影名,按规矩得用 <i> 标出来,结果斜体套斜体,俩歪一块儿去了。正确的做法是让嵌套在斜体里的 <i> 恢复正体:
blockquote i {
font-style: normal;
}这么一搞,电影名就正常显示了,既保留了语义又没让样式翻车。
强调里面套强调纯属多余
有人手痒,非要在 <em> 里面再套个 <strong>,或者反过来,写成 <em><strong>整盘</strong></em> 这种。浏览器渲染出来没问题,现代浏览器都认。但这是典型的“我可以但没必要”。语法上没有任何一条规则要求双层强调。就跟写文章用感叹号一样,一个就够了,摞三个感叹号并不会让语气更强烈,反而显得业余。
更关键的是,屏幕阅读器处理嵌套强调的时候,并不会因为有两层就念两遍重音。辅助技术只认最内层或者干脆只认第一个标签,不同阅读器表现还不一样。所以嵌套强调既没语法收益,也没无障碍增益,纯属给自己找活干。
遇到死要强调的老板咋整
万一碰上那种非要又加粗又倾斜又下划线的需求,死磕语义标签就钻牛角尖了。正确姿势分三步走:
第一步,按真实语义选一个主标签。如果要表达“这事儿特别紧急”,就用 <strong>;如果要表达“读的时候重音放这儿”,就用 <em>。只选一个,别贪多。
第二步,把剩下的视觉效果用不带语义的标签补上。比如主标签用了 <em> 表示重音,但老板还想要加粗和下划线,那就往里套 <b> 和 <u>。
第三步,用 CSS 统一管理这些组合的样式,避免手写一堆乱七八糟的内联样式。
举个例子,老板想要那个“loved”又斜又粗还带下划线还变个橙色:
<p>
以前有个老板,对文字那是
<em>真爱<strong><u>啊</u></strong></em>
</p>然后写一段 CSS 专门伺候这种组合:
/* 当 em 里面包着 b 或者 u 标签时,给个橙色 */
em:has(b, u) {
color: #f8a100;
}这么干,语义上 em 仍然表示重音强调,粗体和下划线只是装饰,不会让屏幕阅读器误会。颜色变化纯属视觉骚操作,不干扰任何语义。
再整个防御性检测方案
写项目的时候经常是多人协作,保不齐哪个同事就把 <strong> 和 <em> 嵌套着用了。可以在样式表里加一段“报错”样式,把这种嵌套用法高亮成红色背景,方便开发阶段一眼看出来:
/* 语义标签套语义标签,给个红色半透明背景加虚线边框 */
em:has(strong),
strong:has(em) {
background: hsl(0deg 50% 50% / 0.25);
border: 1px dashed hsl(0deg 50% 50% / 0.25);
}这样只要页面里出现 <em><strong>...</strong></em> 或者 <strong><em>...</em></strong>,那段文字就会带上一圈淡红底色加虚线边框。测试环境里开着这个样式跑一遍,分分钟揪出所有嵌套强调的代码位置,挨个改掉就行。
字体文件没配齐也会翻车
用 <strong> 和 <em> 的时候,浏览器默认会去找字体的粗体版本和斜体版本。如果网页加载的自定义字体只配了常规字重(比如只加载了 400 ),没加载 700 的粗体文件,浏览器就会强行用算法把常规字重拉伸成粗体,那效果糊得一匹,边缘锯齿感拉满。同理,没加载斜体变体的话,浏览器直接把文字硬掰歪,字形都跟着走样。
所以搞字体文件的时候,至少得把 regular、bold、italic、bold italic 这四个变体都配上。要是嫌加载太多影响性能,就用 font-display: swap 让文字先显示回退字体,等自定义字体下载完再替换。千万别省那几个字体文件,省下来的是几 KB 流量,丢的是整段文字的阅读体验。
改写文案比加标签更管用
有时候折腾半天标签,还不如换个说法来得实在。比如想强调“这个 bug 必须今天修”,写成“今天必须把这个 bug 修了,不然发不了版”就自带紧迫感,根本不用加 <strong>。又比如想表达“不是张三干的,是李四干的”,写成“干这事的不是张三,恰恰是李四”,通过句式对比就把重音自然带出来了。
好的文案本身就有强调效果,标签只是锦上添花。写代码之前先花十秒钟想想,能不能把句子重新组织一下,让重点内容在字面意思上就突出。这招比任何 HTML 标签都好使,还兼容所有浏览器和屏幕阅读器,零成本高回报。
