应直接用语义化html搭建搜索页:用、、、结果列表及加载提示,确保可访问性、seo与维护性。

直接用原生 HTML 搭建搜索展示页面,不是“先写完再重构”,而是从第一行就按可维护结构写——否则你重构的不是页面,是自己的时间成本。
为什么不能用 div 套 div 写搜索页
常见错误现象:搜索框和结果列表都塞在 <div id="search"> 里,JS 用 <code>document.getElementById('search') 绑定事件,结果改个 class 名或挪个位置,submit 就失效;更糟的是,屏幕阅读器读出来全是“group, group, group”,用户根本不知道哪是输入、哪是按钮、哪是结果。
语义缺失带来的实际影响:
-
<form></form>缺失 → 回车无法提交,移动端键盘“搜索”按钮不触发 -
<input type="search">写成type="text"→ iOS 不显示清除图标,Chrome 不自动记录搜索历史 - 结果列表用
<div class="result"> 而非 <code><ol></ol>或<ul></ul>→ 无法用aria-live做无障碍更新,自动化测试也难定位<form></form>必须带role="search"和autocomplete别只写
<form></form>就完事。浏览器和辅助技术靠属性识别意图,不是靠 class 名猜。正确写法示例:
关键点说明:
-
role="search"是显式声明用途,比仅靠<form></form>更可靠,尤其对旧版读屏软件 -
autocomplete="off"不是关闭所有提示,而是防止浏览器把搜索词填进登录框等敏感字段 -
novalidate表示 JS 自己控制校验逻辑,避免浏览器默认弹窗打断 UX 流程 -
<label for="q"></label>必须与id严格匹配,否则点击标签无法聚焦输入框(移动端尤其明显)
搜索结果区域要用
<section></section>+<ol></ol>,别用<div> <p>结果不是“一堆盒子”,是有序内容集合。用 <code><ol></ol>不仅语义正确,还能天然支持键盘导航(Tab 进入后用方向键切换)。结构要点:
- 外层用
<section aria-labelledby="search-results-heading"></section>,配合<h2 id="search-results-heading">找到 12 条结果</h2>,让读屏软件知道这是什么区域 - 每条结果用
<li role="article">(<article></article>在某些老浏览器中解析异常,role="article"更稳) - 结果项内必须有
<a href></a>或<button></button>,禁止纯<div onclick> —— 否则无法用空格/回车触发,也不被键盘焦点捕获 <li>加载中状态用 <code><div aria-live="polite">正在搜索…</div>,而不是靠 class 切换隐藏/显示 -
<input type="search">在 Safari 旧版本中会多出圆角和内部 X 图标,但若没设appearance: none,CSS 覆盖会失效;建议统一加input[type="search"]::-webkit-search-cancel-button { display: none; } - 移动端双击放大问题:没写
<meta name="viewport" content="width=device-width, initial-scale=1.0">的页面,iOS 会强制缩放搜索框,导致文字被截断 - 搜索词高亮逻辑若依赖 JS 插入
<mark></mark>,要确保服务端返回的原始文本不含 HTML 实体(如把&当成字面量渲染),否则<mark></mark>会被当成普通文本
容易被忽略的兼容性细节
最常被跳过的三件事,上线后才暴露:
重构不是重画 UI,是把 HTML 变成可信赖的契约——JS 靠它找节点,CSS 靠它选范围,读屏器靠它讲逻辑,搜索引擎靠它判权重。少一个
role,多一个div,契约就松一扣。 -











