应优先用header、main、aside、section等语义化标签替代div.row/col,结合grid-template-areas命名区域匹配结构,确保dom表达力与可访问性;aria仅作补充,不可替代语义标签。

用语义化HTML标签替代div.row和div.col
Grid本身不提供语义,但很多人仍习惯写一堆带row、col类名的div,这会让DOM失去表达力。屏幕阅读器只看到“一个div”,无法判断这是页眉、主内容还是侧边栏。
应直接改用HTML5语义标签作为Grid容器或项目:
-
header替代<div class="row header">,配合<code>role="banner"明确用途 -
main必须唯一,且应作为核心内容区域的网格项,不能嵌套在section里当普通容器用 -
aside天然对应侧栏列,比<div class="sidebar">更可信——即使CSS Grid把它放到顶部,语义仍是“补充信息” <li>若内部只有标题+几个<code>article,优先让article直属于main,而非包一层section -
grid-area值必须与grid-template-areas中的字符串完全一致,大小写敏感,空格也不能多一个 - 用
.表示空单元格,但别为了“对齐美观”强行补点——它代表真实空白区域,会影响阅读器遍历顺序 - 若某区块需跨多区域(如全宽横幅),用
grid-area: banner+grid-template-areas: "banner banner",别拆成两个同名区域再合并 - 如果把
footer用grid-row: 1提到最上面,它在Tab键循环中依然排在最后 - 若DOM顺序是
header→main→aside→footer,但CSS把它排成header→aside→main→footer,屏幕阅读器用户会先听到header,然后跳到main,中间漏掉aside的上下文 - 解决办法只有一个:调整HTML源码顺序,让它和视觉逻辑一致;Grid只负责呈现,不负责“修复”结构
- 给
<div class="sidebar">加<code>role="complementary",却没加aria-label或aria-labelledby,导致屏幕阅读器只读出“complementary”,没内容标识 - 用
role="region"包裹一大段内容却不配aria-labelledby,等于没说清这个区域是干啥的 - 在已有
main、nav等原生语义标签上再叠加role,反而可能覆盖浏览器默认行为
grid-template-areas命名区域必须与grid-area严格匹配
命名区域不是炫技,而是把布局意图写进CSS,让开发者和辅助技术都能对齐理解。比如grid-template-areas: "header header" "sidebar main" "footer footer",比计算grid-column: 2 / 4直观得多。
关键点:
视觉重排不等于DOM重排,tab顺序和阅读顺序不会变
CSS Grid允许你用order、grid-row、grid-column等属性随意调整视觉位置,但这些操作完全不影响非可视媒体中的顺序。屏幕阅读器仍按HTML源码顺序读取,键盘Tab也照着DOM流走。
这意味着:
ARIA role只是补充,不能替代语义标签
有些场景下你无法改HTML结构(比如CMS输出固定div),这时ARIA是最后防线。但注意:role只是“告诉”辅助技术这是什么,不改变DOM本质,也不影响样式或JS选择器。
常见误用:
真正关键的不是加了多少role,而是DOM是否能被准确推断出角色——这点永远优先于任何CSS技巧。











