不知道你在写页面的时候有没有纠结过一个问题:同一个网页里,明明正文和广告摆在一起,我用 div 包了一层 class="ad",搜索引擎和读屏软件就真的分得清吗?实测下来,光靠 class 名字根本不够。HTML5 里特意准备了一个标签来解决这类“次要内容、与主体间接相关”的语义问题,就是 aside。
这篇内容我打算用一个做内容站特别常见的场景来展开:侧边栏有广告位,文章中间也穿插了赞助内容,怎么用 aside 把广告位从正文里干净地切出来。文章适合三类人看:正在学 HTML 语义化的前端新人、自己做网站想优化 SEO 的站长、以及需要对页面做无障碍改造的开发者。我会把原理、写法、验证方法、踩坑经验都放进来,你可以直接照着抄。
1. 正文与广告的边界,HTML规范其实早就画好了
1.1 为什么div+class="ad"不能解决区分问题
很多人在第一次接触广告位代码时,拿到的模板都是这样的:
html复制<div class="ad-banner">
<a href="https://example.com" rel="nofollow">购买我们的产品</a>
</div>
这种写法在视觉上没有任何问题,CSS 一写,广告位照样展示。但它的问题是:div 本身没有任何语义,它就是一个普普通通的容器,机器读到这串代码的时候,只能知道“这里有个区块”,至于这个区块是广告、是正文、还是导航,HTML 层面完全无感知。
class="ad" 这个名字,是写给人看的,也是写给 CSS 和 JavaScript 看的,但搜索引擎爬虫和读屏软件并不依赖 class 名称去判断内容的性质。虽然很多搜索引擎确实会分析 class 命名,但它顶多算一种“信号”,远不如语义化标签和 ARIA 属性来得可靠。
更关键的是,广告位在内容性质上天然“低一等”:
- 它和页面的核心主题只有间接关系;
- 它应当可以被用户轻松跳过;
- 它在无障碍场景下需要明确标注,避免干扰阅读。
这些特性靠 div 表达不出来,但 HTML5 专门为这种情况准备了一个语义化标签:aside。
1.2 aside在正文与广告之间到底扮演什么角色
aside 是 HTML5 新增的区块标签,规范里对它的定义很明确:表示与页面主要内容仅有间接关系的部分。如果我在文档里给搜索工程师写注释,我会说“这部分内容拿掉之后,用户依旧能完整理解页面主体信息”,那这个内容就非常适合放进 aside。
我举个不太严谨但特别容易记住的类比:一个超市的入口通道,左右两边是当季促销商品,中间的购物主通道才是用户真正要走的路。促销商品区和主通道是有关系的,但没有它,顾客照样能逛完整个超市。aside 就是那个促销商品区,正文则是购物主通道。
实际开发中,aside 最常出现在两个位置:
- 页面级 aside:比如博客右侧的侧边栏,里面放着推荐阅读、友情链接、广告位,这一整块和文章正文是并列关系,彼此独立;
- 文章内 aside:藏在
<article>标签内部,比如某段话旁边的注释框、扩展阅读、投票组件,甚至是一段“小编推荐”的赞助商品卡片。
广告位这两种场景都会涉及。页面级广告位放在侧边栏,aside 是天然容器;文章内嵌广告放在段落之间,也可以用 aside 包一层,告诉浏览器“这段东西和正文有关联,但它是旁支,不是主线”。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 广告位语义化核心写法:aside加ARIA组合拳
2.1 认识aside的隐式角色,老浏览器用ARIA补位
如果只写一个 aside,它其实自带一个隐式的 ARIA 角色,叫 complementary,中文常翻译成“补充信息区域”。这个角色会告诉辅助技术:这里的内容和页面主体相关,但用户可以选择跳过阅读。
听起来很理想,但实际操作中我建议你显式把 role="complementary" 写上去,同时配上 aria-label。原因有两个:
第一,不是所有浏览器都对旧版 HTML 元素的角色映射得很一致。比如一些老版本 IE 和部分屏幕阅读器组合下,纯粹的 aside 未必被识别为 complementary,显式写上 ARIA 会更稳定。
第二,页面里很可能不止一个 aside。侧边栏有一个,正文中间又穿插一个,如果没有 aria-label 加以区分,读屏用户就会听到两遍“补充信息区域”,根本分不清哪边是广告、哪边是推荐阅读。
所以一个规范的广告位容器,至少长这样:
html复制<aside class="ad-slot" role="complementary" aria-label="广告">
...
</aside>
aria-label 的内容没有严格的格式规定,写“广告”“赞助商内容”“广告区域”都可以,关键是让人一听就明白。
2.2 页面级广告位:一个标准aside结构长什么样
页面级广告位,指的就是常驻侧边栏或者正文底部的通栏广告。这类广告全站性质比较强,很多页面都会复用。我建议的做法是把整个广告区块作为一个独立的 aside,放在 <main> 外面。
这里有个挺容易犯的错误:很多人觉得广告位是页面的一个组成部分,就直接塞进 <main> 里。但 <main> 表示的是“页面唯一的核心主题内容”,如果侧边栏广告用的是全站统一模板,那它就不属于当前页面的核心主题,放在 <main> 外面更合理。
一个典型的页面级广告位结构是这样:
html复制<body>
<header>网站导航</header>
<main>
<article>
<h1>这是一篇和核心主题有关的文章</h1>
<p>真正的内容在这里。</p>
</article>
</main>
<aside class="sidebar-ad" role="complementary" aria-label="广告区域">
<h2 class="sidebar-ad__title">赞助商推荐</h2>
<div class="sidebar-ad__content">
<a href="/go/sponsor" rel="sponsored nofollow">访问赞助商</a>
</div>
</aside>
<footer>版权信息</footer>
</body>
注意 rel="sponsored nofollow" 这个细节。对于付费广告链接,rel="sponsored" 让搜索引擎知道这是一个商业性质的链接,nofollow 则表示“不要通过这个链接传递权重”。这两个属性并不是 SEO 的必杀技,但它们是广告位语义化中最后的一环。
2.3 文章内嵌广告:aside放在article内外有讲究
相比页面级广告,文章内嵌广告的语义处理更考验理解。比如,一篇文章讲到一半,突然插进来一个“相关产品推荐”,或者一段“赞助内容”,这种内容和文章正文其实处在同一篇 <article> 的上下文里,那 aside 该放在 <article> 里面还是外面?
正确答案是:看它与整篇文章主体的关联程度。
如果这段广告只针对当前文章相关的产品或服务,那它可以放在 <article> 内部。因为 HTML 规范允许 aside 嵌套在 <article> 中,表示“与包含它的区块内容仅有间接联系的旁注”。比如:
html复制<article>
<h1>如何挑选机械键盘</h1>
<p>文章正文第一段……</p>
<aside class="in-article-ad" role="complementary" aria-label="赞助商内容">
<p>本文由某键盘品牌赞助,查看他们的最新产品:</p>
<a href="/go/keyboard" rel="sponsored nofollow">去看看</a>
</aside>
<p>文章正文第二段……</p>
</article>
如果这段广告是全站统一的品牌广告,放在文章里有点尴尬,那我建议放在 <article> 外面,或者干脆用 <div> 配合 aria-hidden 处理,不要让读屏用户被全站重复的广告打扰太多。
还有一种情况:广告位内部的文本内容非常少,比如只有一个图片链接。此时 aside 内部到底需不需要包裹一个 <div>?我的习惯是加一层容器,方便 CSS 定位、方便广告 SDK 填充内容,也让语义结构层次更清晰。这一层容器仍然用 <div> 就行,因为它已经是 aside 内部的纯样式容器。
3. 搜索引擎和读屏软件视角下的广告位语义
3.1 搜索引擎如何处理页面的广告区块
搜索引擎爬虫抓取页面时,确实会分析页面里各个区块之间的关系。虽然搜索引擎不会因为某个区块用了 class="ad" 就直接不抓取,但语义化结构会影响它理解“哪部分是页面要表达的核心内容”。
举个实际例子,我维护过一个资讯站,早期文章页结构是这样:正文、广告位、相关推荐全部平铺在几个 <div> 里,广告位的链接文字和文章里的正文文字在 DOM 结构上地位完全相同。过了一段时间,我发现搜索控制台里“正文含链接的Top点击量”统计特别混乱,广告链接也被算进去了一部分。
后来把广告位改成 <aside> 并标注 aria-label 后,最明显的变化是:搜索控制台里展示的爬虫抓取结构更清晰了,正文和广告区块的边界一眼就能看出来。所以从这个角度说,aside 对搜索引擎有正向作用,它是在帮助机器“去掉噪音、直奔主题”。
不过有一点要特别注意:搜索引擎非常反感把广告内容隐藏起来。如果你为了区分广告和正文,用 display:none 或者 visibility:hidden 把广告文本藏起来,这会被判定为隐藏文本,性质就从“语义化”变成“作弊”了。广告位可以声明为“广告”,但不能从视觉上消失。
3.2 读屏用户怎么识别“这块内容是广告”
读屏软件用户浏览网页时,可以通过快捷键快速在“地标区域”之间跳转。aside 映射成的 complementary 地标,就是这类用户可以主动跳转或跳过的区域之一。
如果页面没有标注广告区域的语义,用户听到的就是一连串毫无标识的文字。想象一下,盲人用户正在听一篇教程,听到一半突然冒出来“限时特惠、全场两折”,而且这段声音和正文没有任何区分,体验可以说非常糟糕。
一旦你用 aside 加 aria-label="广告" 标注之后,读屏软件通常会先提示“广告区域”,部分用户还会选择主动跳过整个区域。这是广告位语义化在无障碍层面最直接的价值。
还有个小细节:有些读屏软件在读 aria-label 时可能和相邻文本连在一起,所以 aria-label 的内容尽量简单明确,用“广告”“赞助商内容”比“这里是一个由某某品牌提供的广告位,内容包含……”简洁得多,后者会被读屏软件念得又臭又长。
3.3 不能用隐藏样式区分广告位的真实原因
我碰到过不少站长,为了“让正文和广告分离”,把广告位放进一个 aside,然后顺手给这个 aside 写了个 display: none。他们的逻辑是:反正搜索引擎也别来管我的广告,我把广告藏起来不就等于没有广告了吗?
这种做法非常危险,我说两件真实发生过的事情:
- 搜索引擎的抓取规则里,隐藏文本是被明令禁止的,做成白色文字、透明图层、零尺寸容器或者
display:none,都会被认定为伪装内容,轻则降权,重则整站人工审核; - 广告联盟的审核也很严格,把广告区域隐藏起来属于典型的违规操作,账号存在被封禁的风险。
所以广告位语义化的前提永远是“正常展示广告”,我们只是通过标签和属性告诉机器:这个区域是广告,它是真实存在的,但它不应该被当成核心正文。语义化解决的是“区分”,不是“隐藏”。
4. 一套能直接抄的广告位语义化模板
4.1 页面级广告位完整HTML骨架示例
我直接给一个我目前在内容站上使用的模板。这个模板兼顾了语义、SEO 和无障碍,你拿到以后可以根据自己的 CSS 框架改一改就能用。
html复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文章页 - 示例</title>
<style>
.layout {
display: grid;
grid-template-columns: 1fr 320px;
gap: 24px;
}
.sidebar-ad {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
}
.sidebar-ad__title {
font-size: 14px;
color: #888;
margin-bottom: 8px;
}
</style>
</head>
<body>
<header>
<nav>导航区域</nav>
</header>
<div class="layout">
<main>
<article>
<h1>机械键盘选购避坑指南</h1>
<p>这篇文章的核心内容是帮助新手熟悉机械键盘的轴体区别、键帽材质、购买预算规划。</p>
<p>第一段深入一点的内容……正文部分会在这里展开。</p>
<p>第二段继续展开,真正有价值的信息全都在 main 里。</p>
</article>
</main>
<aside class="sidebar-ad" role="complementary" aria-label="广告区域">
<h2 class="sidebar-ad__title">赞助商推荐</h2>
<div class="sidebar-ad__content">
<a href="/go/sponsor" rel="sponsored nofollow">某品牌机械键盘,现有新人优惠</a>
</div>
</aside>
</div>
<footer>版权信息</footer>
</body>
</html>
这个结构里,<main> 只包裹了真正属于页面核心的文章内容,广告区块 aside 和它并列,但不在 main 内。rel="sponsored nofollow" 标记了商业链接属性,aria-label="广告区域" 提供了无障碍上下文。
4.2 正文混排时的文章内广告位代码示例
文章内广告更常见的是插入在某一段正文的旁边或下面。这种位置比较考验设计,但语义化的写法相对固定:
html复制<article>
<h1>如何高效学习前端三件套</h1>
<p>HTML 负责结构,CSS 负责视觉,JavaScript 负责交互。这是很多新手刚接触前端时的第一印象。</p>
<p>随着实践深入,你会发现三者之间的边界并没有想象中那么清晰。</p>
<aside class="inline-ad" role="complementary" aria-label="赞助商内容">
<p class="inline-ad__label">赞助内容</p>
<a href="/go/frontend-course" rel="sponsored nofollow">
零基础前端入门课程,限时 5 折
</a>
</aside>
<p>接下来我们聊聊浏览器如何解析 HTML 文档,以及为什么语义化标签对搜索引擎如此重要。</p>
</article>
注意这里的 aria-label 是“赞助商内容”,而不是“广告”。读屏用户对这两个词的感觉完全不同,“赞助”听起来更中性,也更接近内容推荐的语气。如果你的广告位是直接从广告联盟获取的,联盟本身的素材里可能带有自己的文本,那 aria-label 写“广告”更保险,避免用户误把广告内容当成正文的一部分。
4.3 四种自查方法,确认语义标记生效
写完代码以后,别光靠眼睛看样式,我推荐你按下面四个步骤自查一遍:
- W3C Nu HTML 验证器:把页面代码贴进去,查看是否有标签嵌套错误,比如把
main放进了article、aside套了多层等; - Chrome DevTools 的 Accessibility 面板:在 Elements 面板选中
aside标签,右侧切到 Accessibility 标签页,看 Computed Properties 里 Role 是否为Complementary。如果是,说明浏览器已经正确识别了这个地标区域; - NVDA 或 macOS VoiceOver 走查:打开读屏软件,用
d键(NVDA 里跳转到下一个地标区域的快捷键)或者双指滑动(VoiceOver 快速导航模式)听一听,屏幕阅读器是否明确提示“补充信息区域 广告”; - 结构化数据测试工具:如果你的广告位还有对应的结构化数据,比如富媒体搜索结果标记,用 Google 的富结果测试工具检查是否能正常解析。
这四种方法里,最容易被忽略的是第二个。很多人检查过 DOM 树就以为万事大吉了,其实浏览器 DOM 表达和 Accessibility 树表达并不是完全一样的,aside 在某些异常嵌套下会被降级成 generic 角色。你必须在 Accessibility 树里确认,才算真正落实了语义。
5. 常见问题与避坑经验
5.1 广告位语义化问题速查表
我整理了一张表格,把常见问题、可能原因和解决办法放在一起,方便你日后排查。
| 问题现象 | 可能原因 | 处理方式 |
|---|---|---|
| 读屏软件不提示“广告区域” | 缺少 aria-label 或 role 属性 |
补上 role="complementary" 和 aria-label="广告" |
| aside 被搜索引擎视为正文 | aside 嵌套在 article 内部但内容与正文直接相关 | 判断相关性,必要时把广告位移到 main 外或 article 外 |
| 多个 aside 分不清 | 每个 aside 都没设置 aria-label |
按内容分别加“广告”“相关推荐”“工具”等标签 |
| 广告文字在搜索结果摘要中出现 | 广告文本与正文 DOM 结构层级扁平,没有语义边界 | 广告文本包进 aside,链接加上 rel="sponsored nofollow" |
| 广告区域被隐藏后站点被警告 | 错误使用 display:none 或透明化隐藏广告 |
删除隐藏样式,改用正常展示加 aside 语义 |
| 广告平台代码与语义化容器冲突 | 平台要求保留原始 div 结构 |
外层包 aside,平台代码保留在容器内部,不修改平台生成的脚本 |
表格里最后一项是我实际处理过最多的情况。很多广告联盟平台要求你不得修改它给出的广告代码,尤其是不能改动里面的 div 和脚本结构。这时候正确做法是“外面再套一层”:保留平台代码原样,在它的外层包一个 aside,把 role 和 aria-label 加在外层,平台代码结构一点不用动,两全其美。
5.2 我踩过的几个典型语义化坑
第一个坑是过度使用 aside。早年前我做网站,恨不得把页面所有边角料全塞进 aside,什么友情链接、备案信息、公告、广告、个人简介,全都用 aside 包。结果页面里全是“补充信息区域”,没有主次之分,读屏用户跳区域跳得怀疑人生。后来才明白,aside 是用来表达“次要与间接”,但“次要”不代表“越多越好”。全局导航用 nav,页脚用 footer,工具信息用 div 都行,不要什么都往 aside 里装。
第二个坑是忽略了 heading 的结构。一个广告位如果能加标题,最好加一个标题,比如“赞助推荐”“广告”,标题层级要和页面整体大纲一致。我之前有个页面,正文 <h2> 后面紧跟的广告里直接来了个 <h3>,视觉上没问题,但读屏用户听着大纲就会困惑:为什么文章里突然冒出一个子标题,而且还没内容?后来我在广告位外层再包一层 <aside>,标题降级为 <span class="ad-slot__title">,从根本上解决。
第三个坑是广告位浮层遮挡正文。这个和语义化没直接关系,但因为广告比较多,经常有广告容器使用绝对定位或者固定定位,结果把正文的按钮遮住了。语义化标签不会自动避免这些问题,还是要靠 CSS 布局和测试经验去兜底。
5.3 长期维护广告位语义的小习惯
最后分享一下我团队内部长期维护广告位代码的几条铁律:
第一,在代码规范里明确要求,凡是新增广告区块,必须先写 aside、role="complementary"、aria-label 三个属性,再谈样式。规范不靠自觉,靠代码评审和 lint 工具去约束,这个习惯一旦养成,整个站点的广告语义都不会走样。
第二,定期用自动化脚本扫描页面里的隐藏文本。我们每隔两周跑一次 grep 或者用 Lighthouse 检查,专门找有没有 display:none 的广告容器。不是所有隐藏文本都是坏事,比如响应式设计下移动端的一些装饰元素是要藏的,但广告容器如果被藏起来,必须立即拦截。
第三,广告位改动要追踪版本记录。广告联盟那边偶尔会更新代码模板,更新时很可能把你外面包的 aside 给冲掉,或者直接把广告代码替换成新的 div 结构。这种更新经常发生在半夜或者节假日,如果你有版本管理和自动化部署的提醒机制,就能尽早发现有没有破坏语义结构。
我自己做过一个简单的校验脚本:解析 HTML 后,统计页面里 class 含有 ad 的元素,看看它的祖先链路上是否存在 aside 或 role="complementary"。如果某个广告区块找不到,就输出一个 warning,提醒开发人员去检查。这个脚本不复杂,但对内容站的广告位质量把关非常有效。
广告位语义化这件事,说难不难,说简单也容易做漏。我的建议是:每次写广告位,先别管样式,把 aside 和 ARIA 属性写对,再把链接的 rel 属性补上,最后才去调 CSS。顺序对了,后面基本不会出大问题。
