应使用 并包裹在 中,设 name="q" 和 action="/search",显式声明 method="GET",加 required 和 autofocus;清空按钮需用伪元素隐藏或自定义;搜索提交监听 submit 事件并用 FormData 取值;实时过滤必须防抖。

直接用 <input type="search">,别手写 type="text"
浏览器对 type="search" 有原生支持:自动加清空按钮、移动端弹“搜索”软键盘、历史下拉补全、屏幕阅读器识别为搜索用途。换成 type="text" 就全丢了——不是样式问题,是能力归零。
必须包在 <form></form> 里,且设 name="q"(行业惯例)和 action="/search"(哪怕 JS 拦截也要留着,方便降级)。漏掉 name,后端根本收不到参数;没 action,表单提交行为不可靠。
-
method推荐显式写method="GET",搜索参数本该暴露在 URL 中,利于缓存、分享、书签 - 加
required防空搜,加autofocus让页面加载后光标自动落进去 - 移动端想避免聚焦时页面跳动?禁用
position: fixed或动态锁body高度
清空按钮样式改不了?那就藏掉或重做
各浏览器对清空按钮的伪元素支持不一致:::-webkit-search-cancel-button(Chrome/Safari)、::-ms-clear(旧 Edge),它们不是普通 DOM 元素,无法用常规 CSS 调整颜色、尺寸,appearance: none 在 Safari 15.4+ 还得加 -webkit-appearance: none 才生效。
实操建议分两条路:
- 只隐藏:用
input::-webkit-search-cancel-button { -webkit-appearance: none; }+input::-ms-clear { display: none; } - 要自定义图标:放弃原生按钮,用绝对定位的
<button></button>覆盖,JS 控制显隐和input.value = '',同时记得input.focus()
不想跳转页面?监听 submit 事件,别碰 blur 或 change
回车、点击按钮、甚至语音搜索触发的提交,都走 form 的 submit 事件。监听 input 的 blur 或 change 容易误触(比如用户切出去又切回来),也不兼容回车。
关键动作只有三步:
- 给
<form></form>绑定submit事件,调event.preventDefault() - 用
new FormData(form).get('q')取值——比直接读input.value更健壮,自动处理空格、编码、空值 - 如果是 AJAX 搜索,记得禁用提交按钮防止重复点击:
form.querySelector('button').disabled = true,完成后恢复
实时过滤列表?防抖不是可选项,是必选项
监听 input 事件做实时过滤很常见,但没加防抖的话,用户连输 “react” 会触发 6 次过滤,DOM 重绘频繁,低端机卡顿明显。
最小可用防抖写法:
let timer;
input.addEventListener('input', () => {
clearTimeout(timer);
timer = setTimeout(() => {
const q = input.value.trim().toLowerCase();
const results = q ? pages.filter(p => p.title.toLowerCase().includes(q)) : [];
render(results);
}, 200);
});
注意点:
- 输入为空时,
results设为空数组,清空结果区,别留上一次残留 -
toLowerCase()统一大小写,否则 “FAQ” 匹配不到 “faq” - 如果数据量大(>100 条),考虑用
indexOf替代includes,或引入模糊匹配库如 Fuse.js
真正难的不是写出来,是把清空按钮行为、移动端聚焦、防抖时机、FormData 取值这四件事串成一条不崩的链——少一个环节,用户就会在某个设备上突然搜不出东西。

















