在捣鼓网页的时候,经常碰到一个让人头大的问题:明明代码写得挺顺眼,屏幕上的字也看得清清楚楚,但总觉得哪里不对劲。后来跟几个前端老炮儿聊天才发现,问题可能就出在那些看似简单的标题上。这些标题不光是要长得好看,它们还肩负着给屏幕阅读器指路、让网页在手机上缩放不崩坏的重任。今天就扒一扒那些关于标题的“隐藏关卡”,把踩过的坑和填坑的法子都抖落出来。
别再乱放 <h1>,它真不是装饰品
刚写页面那会儿,习惯性地把整个网站的标题和页面的主标题都塞进<header>里,觉得这样代码看起来整整齐齐。直到有一天用屏幕阅读器跑了一遍,才发现这操作有多坑。那个最重要的主标题,有时候会跟着导航栏一起被当成“横幅”内容,而真正的主角<main>里反而没了主心骨。
错误姿势一:标题困在页头里
好多新手都会这么干,把<h1>塞在<header>里面,外面再套个<main>。这么写,视觉上好像没啥毛病,但辅助技术就不这么认为了。<header>在无障碍树里默认是个banner角色,就像商店门口的迎宾牌。把主标题放这儿,屏幕阅读器用户跳到主要内容时,很可能直接把这个标题给跳过去了。就像进电影院,门口的巨幅海报看了半天,结果正片开场愣是没找着座位。
<!-- 这种写法容易让主标题被忽略 -->
<header>
<h1>一部电影的影评</h1>
</header>
<main>
<p>这部电影真的绝了...</p>
</main>错误姿势二:在主角里又套个壳
另一种常见的情况是,为了保持结构统一,在<main>里面再嵌套一个<header>,然后把<h1>放在里面。这相当于在电影院里又搭了个小门厅,告诉观众“嘿,主要内容在这呢”。结果屏幕阅读器进去之后,还得再跨一道门槛才能摸到正文。更麻烦的是,这个内嵌的<header>会丢失它作为全局页头的语义,直接降级成一个没啥意义的<div>或<section>,让人搞不清楚到底哪里才是页面的主入口。
<main>
<header>
<h1>电影影评</h1>
</header>
<p>这部电影真的绝了...</p>
</main>靠谱方案:标题直接扎根主要内容区
正确的打开方式,是把<h1>大大方方地放在<main>里,而且是作为<main>的直接孩子,不套任何多余的壳子。这样<header>还是那个独立的全局页头,负责展示网站名称、导航这些“门面”活儿。而<main>里面的<h1>就是内容的真正领路人。屏幕阅读器用快捷键跳转时,能从“横幅”区域干净利落地切到“主要内容”区域,第一个听到的就是这个标题,逻辑清晰得一匹。
<header>
<!-- 网站导航、Logo等 -->
</header>
<main>
<h1>关于电影标题的那些事</h1>
<p>正文内容从这里开始...</p>
</main>这么改完,整个页面的语义就通透了。<header>还是那个独立的“店面招牌”,<h1>成了“店内爆款”的标签,两者各司其职。对于依赖辅助技术的用户来说,就像从店门口直接迈进商品陈列区,中间没有乱七八糟的过道,体验丝滑多了。刚开始可能觉得多此一举,但养成习惯后,会发现这种结构维护起来特别清爽,不管后期怎么改版,标题和内容的关联都不会乱。
玩转流体标题,别让缩放卡住脖子
现在做响应式页面,谁还不用个clamp()函数呢。但这里面有个坑,很多人直接拿vw(视口宽度单位)做中间值,结果用户一放大页面,标题反而小得看不清,或者大得离谱。这就像给标题装了个弹簧,但弹簧的弹性完全跟着窗口走,不跟着用户的视力走,这就尴尬了。
普通做法:直接上 vw 当弹性值
最偷懒的写法就是直接指定一个vw值作为中间理想尺寸。比如font-size: clamp(18px, 4vw, 36px),意思是最小18像素,最大36像素,中间跟着窗口宽度走。在浏览器正常缩放时,确实很顺滑。但一旦用户用浏览器的缩放功能放大到150%或200%,这个4vw的计算结果也跟着放大,标题可能就冲出容器,或者跟周围文字的比例严重失调。这相当于用户想用放大镜看细节,结果放大镜把整个画面都扭曲了,还不如不放大。
/* 常见但有小隐患的写法 */
.article-heading {
font-size: clamp(18px, 4vw, 36px);
}进阶方案:引入 rem 稳定军心
要解决这个问题,得让中间那个“理想值”不光看窗口宽度,还得认用户的默认字号。rem单位就是干这个的,它相对于根元素(<html>)的字号。当用户在浏览器设置里把默认字号调大时,所有rem单位都会跟着变。把vw和rem结合起来,就能让标题既随窗口流动,又尊重用户的偏好。
一种比较靠谱的思路是,把最小和最大值用rem定死,然后中间那个弹性值通过计算得出。计算逻辑大概是这样的:设定一个最小的视口宽度(比如320px)对应最小的标题字号(比如2.5rem),最大的视口宽度(比如1920px)对应最大的标题字号(比如5rem)。然后算出斜率,让标题字号在这两个端点之间线性变化。这样不管窗口怎么缩放,标题都保持在一个合理的视觉比例里,用户放大页面时,rem基数变大,标题也随之变大,但vw部分又限制了它不会无限膨胀,两者互相制衡。
.article-heading {
--heading-smallest: 2.5rem;
--heading-largest: 5rem;
/* 计算斜率,这里假设视口宽度从20rem到30rem */
--m: calc((var(--heading-largest) - var(--heading-smallest)) / (30 - 20));
font-size: clamp(
var(--heading-smallest),
calc(var(--m) * 100vw),
var(--heading-largest)
);
}这个计算过程有点像做衣服,先量好最小号(320px设备)和最大号(大屏设备)的尺码,然后中间每个尺码都按比例来。虽然calc()里用单位相除在部分浏览器里可能有点水土不服,但核心思路是通用的。实际开发中,可以直接用在线工具算好数值,或者借助Sass、PostCSS这类工具来生成。改完之后,在手机上横竖屏切换、在电脑上用浏览器缩放,标题都能优雅地适应,再也不会出现“标题遮住正文”或者“标题小到看不清”的尴尬场面。
让CSS选择器更懂你的标题
如果还在用h1, h2, h3, h4, h5, h6来一股脑地给所有标题加样式,那简直太糙了。有时候只想给二级和三级标题加点花活儿,就得写一长串选择器。最近浏览器里冒出来个新玩意儿——:heading伪类,专门来解决这种“标题选择困难症”。
解放手指:用 :heading 一网打尽
以前要给所有标题统一样式,得把六个标题全列出来,代码又臭又长。现在只要写:heading就能全部选中,简直不要太爽。这相当于给所有标题发了一张“集体照”,想统一加个下划线、改个颜色,一行代码就搞定。对于经常做内容型网站的人来说,这个特性能让样式表瞬间瘦身一大圈。
/* 以前要写那么长 */
h1, h2, h3, h4, h5, h6 {
font-family: 'Inter', sans-serif;
}
/* 现在一行搞定 */
:heading {
font-family: 'Inter', sans-serif;
}精准狙击:用 :heading() 按编号筛选
更厉害的是:heading()函数,它可以带参数,指定要选哪些等级的标题。比如只想给二级标题和三级标题加个特殊的上边距,以前得写h2, h3,现在写:heading(2, 3),语义更清晰。这就像在聚餐时,不用一个一个喊名字,直接喊“第2桌和第3桌的兄弟姐妹过来一下”,简单粗暴又高效。
/* 精准控制 */
:heading(2, 3) {
margin-top: 1.5em;
border-left: 4px solid #f0f;
}不过得注意,这个:heading伪类目前还在比较新的浏览器里才支持,正式项目里用的话得留意一下兼容性。但它代表了一个趋势——CSS正在变得越来越智能,越来越懂开发者想要表达的结构化意图。等这个特性普及开来,以后维护标题样式会像搭积木一样,指哪打哪,再也不用在一堆逗号里找花眼了。
