都说HTML标签是网页的骨架,但骨架要是搭错位置,那画面可就太美不敢看了。尤其是那个掌管页面灵魂的<h1>主标题,到底该塞进<header>里,还是跟<main>玩贴贴,这事儿在圈子里简直能吵上三天三夜。今儿个咱就掰扯掰扯,这主标题的“风水宝地”到底在哪儿,顺便把那些一不留神就踩坑的细节给盘个明明白白。
语义化标签是啥,能吃吗?
简单说,语义化标签就是让代码自己会说话。好比给人穿衣服,<header>是帽子,<main>是身子,<h1>就是脸上最显眼的那个大标牌。浏览器和屏幕阅读器全靠这些标签来理解页面结构,要是标牌挂到了帽子上,人家可能就绕过去了,压根没瞅见你想强调的重点。
<h1>和<header>,这俩货啥关系
先看两种常见的“翻车”写法。第一种,把主标题塞进页头的<header>里:
<header>
<h1>今天吃啥,这是个问题</h1>
</header>
<main>
<!-- 这儿才是干饭攻略 -->
</main>第二种,把<header>套在<main>里面,标题再往里塞:
<main>
<header>
<h1>今天吃啥,这是个问题</h1>
</header>
<!-- 干饭攻略详情 -->
</main>这俩看着都挺像那么回事,但都有点小尴尬。第一种吧,<header>自带“横幅”属性,屏幕阅读器可能会把里头的内容当成站点导航之类的东西,要是访客用“跳过导航”直接跳到正文,那主标题就被完美错过了。第二种更离谱,<header>一旦进了<main>,它的“横幅”身份就失效了,变成了个普通盒子,屏幕阅读器就搞不清到底哪个才是页面的“大门”。
给屏幕阅读器留条活路
这时候就需要给<header>一个明确的角色定位。可以在<header>上加上role="banner"来强化它的身份,但这玩意儿毕竟不是长久之计。关键是结构得清晰,让辅助技术一眼就能看明白。比如用第三种方案,把主标题从<header>里解放出来:
<header role="banner">
<!-- 站点LOGO、导航栏啥的 -->
</header>
<main>
<h1>今天吃啥,这是个问题</h1>
<!-- 各种干饭推荐 -->
</main>这样一来,页头的<header>还是那个熟悉的横幅,主标题直接成了<main>的亲儿子,无论是用快捷键跳转还是用“跳过链接”,都能稳稳当当地找到它。
流体标题,别让字号把眼睛整瞎了
搞定了标题的位置,还得操心它长啥样。现在流行用clamp()函数做流体标题,让字号跟着屏幕宽度走,但这里头有个大坑,搞不好就把可访问性给干翻了。
别再只用vw了,那是给眼睛上刑
简单粗暴地用4vw做理想字号,看着挺美,但要是用户把浏览器页面放大了,这字号可能就跟不上节奏了,反而变得贼小。正确的做法是给“理想”值里掺点“非视口单位”的料。
看个例子,比如想把标题字号控制在18px到36px之间:
.article-heading {
font-size: clamp(1.125rem, 2vw + 1rem, 2.25rem);
}这里2vw + 1rem就是那个“理想”值。2vw让它能跟着屏幕大小动,1rem又让它尊重浏览器的默认字号设置。就算用户把字体调到24px,这标题也能跟着变大,不至于让人趴屏幕上看。
算个明明白白的流体标题
要是觉得这种写法还不够得劲,可以整点高级的。比如根据最小和最大字号,以及最理想的行字符数(一般40到80个字符),来精确计算这个理想值。
.article-heading {
--heading-smallest: 2.5rem; /* 最小40px */
--heading-largest: 5rem; /* 最大80px */
--ideal-char-range: 30; /* 30rem - 20rem,假设屏幕宽度从320px到1440px */
--m: calc((var(--heading-largest) - var(--heading-smallest)) / var(--ideal-char-range));
font-size: clamp(
var(--heading-smallest),
calc(var(--m) * 100vw),
var(--heading-largest)
);
}这套路子的精髓在于把字号的变化跟视口宽度绑定的同时,还考虑了最小和最大字号的差值,让标题在不同尺寸的屏幕上都能保持合适的视觉比重。不过得注意,这写法在某些浏览器里可能水土不服,尤其是Firefox对calc()里直接带单位做除法有点过敏,最好在var(--m)里就处理好单位的转换。
快看,CSS出了个新玩意儿:heading
聊完标题的“安家”和“美容”,再来说说CSS里一个即将闪亮登场的新朋友——:heading伪类。这玩意儿能让你给所有标题一次性上样式,不用再写那又臭又长的h1, h2, h3, h4, h5, h6选择器了。
一招搞定所有标题
比如要给所有标题来个默认样式,以前得写一堆:
h1, h2, h3, h4, h5, h6 {
margin-top: 1.5em;
font-weight: bold;
line-height: 1.2;
}现在直接:
:heading {
margin-top: 1.5em;
font-weight: bold;
line-height: 1.2;
}看着就清爽多了,再也不用担心漏掉哪个级别的标题了。
精准打击,只挑特定的标题
:heading()函数更灵活,能精确选择特定级别的标题。比如只给<h2>和<h3>加点下划线:
:heading(2, 3) {
border-bottom: 2px solid #f0f0f0;
}而且,:heading和:heading()只认正宗的标题标签,对那些用role="heading"伪装的家伙一概不理,既保证了语义的纯粹,又让样式控制更精准。
