这 5 个冷门的 HTML 标签,能让你少写 100 行 JS

大家好!😁。

Code Review 的时候,我最怕看到什么?

不是复杂的算法,也不是什么正则。而是明明一个 HTML 标签就能搞定的事,有人非要写几百行 JS + CSS 去重新发明轮子

前几天,我看到一个新同学为了写一个折叠面板(Accordion),引入了一个重型的第三方库,还写了一堆 useStateonClick 和动画逻辑。

我默默地把他的代码全删了,换成了 3 行 <details>。他看我的眼神,仿佛在看一个外星人🤣。

在 2025 年的今天,浏览器原生 HTML 的能力早已今非昔比。很多我们习惯用 JS 去模拟的交互,现在不仅有原生支持,而且性能更好、兼容性更强、无障碍(a11y)更完善

今天,我就来盘点 5 个被严重低估的HTML标签👇。


<details> & <summary>:折叠组件

你是不是还在写这样的 React 代码?

JavaScript 复制代码
// JS 模拟版
const [isOpen, setIsOpen] = useState(false);
return (
  <div className="accordion">
    <div className="header" onClick={() => setIsOpen(!isOpen)}>
      点击展开 {isOpen ? '⬆️' : '⬇️'}
    </div>
    {isOpen && <div className="content">...</div>}
  </div>
);

为了这个功能,你还得写 CSS 动画,还得处理键盘事件(Tab 键能不能选到?回车能不能展开?等等)。

HTML 原生写法:

HTML 复制代码
<details>
  <summary>点击展开</summary>
  <div class="content">
    这里是展开后的内容,原生支持 Ctrl+F 页内搜索!
  </div>
</details>
  1. 没有任何JS:自带点击展开/收起交互。
  2. 无障碍(a11y)满分:屏幕阅读器能完美识别,Tab 键、回车键原生支持。
  3. 页内搜索 :这是 JS 模拟版最大的痛点。如果内容被 JS 隐藏了(display: none),浏览器的 Ctrl+F 往往搜不到。但 <details> 里的内容,即使折叠,浏览器也能搜到并自动展开!

配合 CSS 👇

css 复制代码
details {
  border: 1px solid #ccc;
  border-radius: 6px;
  padding: 8px;
}

summary {
  cursor: pointer;
  font-weight: bold;
}

/* 包住内容,让它能动画高度 */
details > .content {
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height .45s ease, opacity .3s ease;
}

/* details 处于 open 状态时 */
details[open] > .content {
  max-height: 200px; /* 你内容高度大概多少设多少,足够大即可 */
  opacity: 1;
}

依然可以做动画。


<dialog>:弹窗组件

写模态框(Modal)是前端最大的坑之一。你需要考虑:

  • z-index 层级会不会被遮挡?
  • 点击遮罩层关闭?
  • Focus Trap(焦点锁定) :打开弹窗后,Tab 键不能跑到底层页面去。
  • 按下 Esc 键关闭?

为了解决这些,我们通常会引入 Antd Modal 或者 React Portal。但在轻量级场景下,原生 <dialog> 才是神🫅。

HTML 原生:

HTML 复制代码
<dialog id="myModal">
  <form method="dialog">
    <p>这是一个原生模态框</p>
    <button>关闭(自动)</button>
  </form>
</dialog>

<button onclick="myModal.showModal()">打开弹窗⏏</button>
  1. Top Layer(顶层特性) :浏览器会把它渲染在所有 DOM 的最上层,彻底无视 父元素的 z-indexoverflow: hidden
  2. ::backdrop 伪元素:直接用 CSS 定制遮罩层样式。
css 复制代码
/* 背景遮罩 */
dialog::backdrop {
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(3px);
    transition: opacity .3s ease;
}
  1. 原生交互 :自带 Esc 关闭,自带焦点管理,表单提交自动关闭。

<datalist>:搜索自动补全

当产品经理要求做一个带搜索建议的输入框时,你的第一反应是不是:"快!引入 Select2 或者 Antd AutoComplete!😖

且慢。如果只是简单的建议列表,几 KB 的 JS 库都显得太重了。

HTML 原生版:

HTML 复制代码
<label>选择你喜欢的框架:</label>
<input list="frameworks" />

<datalist id="frameworks">
  <option value="React">
  <option value="Vue">
  <option value="Svelte">
  <option value="Angular">
  <option value="Solid">
</datalist>
  1. 模糊搜索:浏览器原生支持模糊匹配(打 u 会出来 Vue)。
  2. 响应式:在手机上,它会调用系统原生的下拉选择 UI,体验比网页模拟的更顺滑。
  3. 解耦:它只是一个建议列表,用户依然可以输入列表里没有的值(这点和 Select 不同)。

<fieldset> & disabled:一键禁用整个表单

场景 :用户点击提交按钮后,为了防止重复提交,我们需要禁用表单里的所有输入框

JS 笨办法:

JavaScript 复制代码
// 还要一个个去拿 DOM,或者维护一个 loading 状态传给所有组件
inputs.forEach(input => input.disabled = true);
buttons.forEach(btn => btn.disabled = true);

HTML 原生写法:

HTML 复制代码
<form>
  <fieldset disabled id="login-group">
    <legend>登录</legend>
    <input type="text" placeholder="用户名">
    <input type="password" placeholder="密码">
    <button>提交</button>
  </fieldset>
</form>

<script>
  // 一行代码搞定状态切换
  document.getElementById('login-group').disabled = true; 
</script>

这是一个极好的分组 思维。通过给 <fieldset> 设置 disabled,浏览器会自动禁用内部所有的 <input>, <select>, <button>。不用写循环,不用维护复杂的 State。


<input type="file" capture>:H5 调用手机相机

场景 :业务需要用户上传一张照片,可以是相册选的,也可以是当场拍的

很多新手的反应是:是不是要接微信 JSSDK?是不是要写个 Bridge 调原生 App 能力?

答案是不需要!

HTML 原生:

HTML 复制代码
<input type="file" capture="environment" accept="image/*">

只要加上 capture 属性,在移动端(iOS/Android)点击上传时,系统会直接拉起相机,而不是让你去选文件。拍完照后,你拿到的就是一个标准的 File 对象。

不需要什么 JS SDK,实现原生级体验👍。


我总是强调 最好的代码,是没有代码!

HTML 标准一直在进化,很多曾经需要重型 JS 才能实现的功能,现在已经成了浏览器的出厂设置了。

使用这些原生标签,不仅能减少打包体积,更能让你的应用在可访问性性能上天然领先。

下次再想 npm install 一个 UI 库之前,先查查 MDN。说不定,HTML 早就帮你做好了🤔。

相关推荐
特级业务专家2 小时前
Chrome DevTools 高级调试技巧:从入门到真香
前端·javascript·浏览器
爱学习的程序媛2 小时前
【Web前端】Angular核心知识点梳理
前端·javascript·typescript·angular.js
小时前端2 小时前
前端架构师视角:如何设计一个“站稳多端”的跨端体系?
前端·javascript·面试
p***h6432 小时前
JavaScript图像处理开发
开发语言·javascript·图像处理
袅沫2 小时前
Element-UI 番外表格组件
javascript·vue.js·ui
杰克尼2 小时前
vue_day06
前端·javascript·vue.js
DcTbnk2 小时前
ESM (放到打包里 import) 和 IIFE (URL 动态 loadScript)
前端·javascript
狗哥哥2 小时前
从文档到代码:工程化规则体系落地全指南
前端
San302 小时前
深入理解 JavaScript 中的 Symbol:独一无二的值
前端·javascript·ecmascript 6