应优先用语义化标签替代无意义div嵌套,删减仅用于样式布局的wrapper类div,配合display: contents隐藏无语义父节点,并在组件中使用fragment或template避免冗余节点。

用语义标签替代 div 堆叠,直接砍掉 2–3 层嵌套
深层 <div> 嵌套(比如 <code><div><div><div><p>内容</p></div></div></div>)不是语法错误,但会让 JS 查询变慢、屏幕阅读器迷失、CSS 选择器失控。真正该删的,是那些只为了 margin/padding/flex 容器而存在的 <div class="wrapper">。<p>实操建议:</p>
<ul><li>把 <code><div class="header"><div class="container">... 换成 <code><header class="header">...</header>,<header></header> 本身支持 display: flex 和 padding
<main></main> 必须且只能出现一次,别把它包进 <section></section> 或 <div> —— W3C 明确禁止,否则语义失效<li>导航栏不用 <code><div class="nav">,改用 <code><nav></nav>;文章章节优先用 <article></article> 或 <section></section>,且每个 <section></section> 内必须有 <h2></h2>–<h6></h6>用 display: contents 让无意义父节点“视觉消失”
有些嵌套不能删(比如框架生成的 <div data-v-xxx>),但又不想它参与布局计算——<code>display: contents 就是为此设计的:它让父元素退出渲染树,子元素直接受上层 flex/grid 控制,DOM 层级不变,但重排范围大幅收窄。
注意点:
- IE 完全不支持;Safari 15.4+、Chrome 65+、Firefox 63+ 支持;Edge 79+ 起支持
- 它不影响 DOM 结构和 JS 查询(
document.querySelector('.parent')仍能拿到),但getComputedStyle()对某些属性(如height)会返回auto - 别对
<form></form>或<table> 父级乱用——它们有强制渲染语义,<code>display: contents可能导致表单控件失焦或表格错位组件化模板里避免“金字塔缩进”,用 Fragment 替代包裹 div
Vue/React 中最常被忽略的嵌套来源,是
v-for或map()返回多个节点时,硬塞一个<div> 当父容器。这不仅加了一层 DOM,还可能破坏 CSS Grid/Flex 的直系子项规则。<p>正确做法:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill7009" title="Ainative React Sdk"><img src="https://img.php.cn/upload/skill/000/000/081/179125754152251.jpg" alt="Ainative React Sdk" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill7009" title="Ainative React Sdk" class="overflowclass">Ainative React Sdk</a> <p class="overflowclass">使用 @ainative/react-sdk 为 React 应用添加 AI 聊天和积分。适用于 (1) 安装 @ainative/react-sdk,(2) 使用 useChat hook 实现聊天完成。</p> </div> <a rel="nofollow" href="/xiazai/skill7009" title="Ainative React Sdk" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <ul><li>Vue:用 <code><template v-for></template>替代<div v-for>,<code><template></template>不生成真实节点 - React:用
>(Fragment)或<react.fragment></react.fragment>,尤其在列表项返回<img>+<p></p>时 - 不要为“统一 class”给 Fragment 加 class——它不支持;需要样式控制就抽成子组件,或用
data-*属性配合 CSS attribute 选择器 -
<ol type="A"><li>A. 主项<ol type="1"><li>1. 子项</li></ol> </li></ol>—— 子<ol></ol>必须是<li>的**直接子节点**,否则变成两个独立列表 -
<fieldset></fieldset>只用于逻辑强相关的表单分组(如「收货信息」「发票信息」),别用它包单个<input>,也别嵌套超过 2 层 - 超过 3 层嵌套的列表,辅助技术播报易混乱;法律/医疗类文档建议用 CSS
counter-increment实现 A.1.a 编号,但 DOM 层级压到 ≤3 层
嵌套列表和 fieldset 分组,别让语义和结构打架
嵌套 <ol></ol>/<ul></ul> 很容易出错:子列表没包在 <li> 里,编号就重置;<fieldset></fieldset> 套太深,Chrome 会延迟渲染。这不是写法问题,是语义误用。
关键判断:
真正难的不是“怎么删嵌套”,而是每次加标签前问一句:这个节点有没有不可替代的语义职责?如果答案是否定的,它大概率该被 display: contents 吞掉,或者直接从模板里拿掉。










