HTML 原生能力有多强?这些功能根本不需要 JavaScript

HTML1周前发布 admin
224 0

前端这几年被 JS 框架”惯坏”了。想做个折叠面板?先装个组件库。想做个弹窗?再引入一个 modal 插件。想做个下拉多选?继续加依赖。

但很多时候,浏览器早就把这些功能做好了,只是我们没用而已。这篇文章就聊聊那些不用写一行 JavaScript、纯靠 HTML 标签和属性就能实现的能力。看完你会发现,有些代码是真的可以删了。

1. 折叠面板:<details> + <summary>

以前做手风琴(accordion)折叠效果,标配是一个点击事件 + 一段 display: none/block 的切换逻辑。现在直接用两个标签就搞定:

<details>
  <summary>点击查看隐藏内容</summary>
  <p>这里是被折叠起来的内容,点击标题就能展开或收起。</p>
</details>

<details> 是容器,<summary> 是可点击的标题栏,浏览器自动帮你处理展开收起的状态和小箭头图标。想默认展开,加个 open 属性即可:<details open>

如果想做手风琴那种”同时只能展开一个”的效果,HTML 也支持了——给多个 <details> 设置同名的 name 属性:

<details name="faq">
  <summary>问题一</summary>
  <p>答案一</p>
</details>
<details name="faq">
  <summary>问题二</summary>
  <p>答案二</p>
</details>

这样点开一个,另一个会自动收起,跟单选按钮的逻辑一模一样。

2. 弹窗对话框:<dialog>

做过 Modal 组件的都知道,要处理的东西不少:遮罩层、居中定位、ESC 键关闭、焦点锁定(focus trap)……这些浏览器现在都内置了,用的就是 <dialog> 元素。

<dialog id="myDialog">
  <p>这是一个原生弹窗</p>
  <form method="dialog">
    <button>关闭</button>
  </form>
</dialog>

唯一需要一点点 JS 的是”打开”这个动作(dialog.showModal()),但关闭、遮罩、居中、ESC 键响应、焦点管理这些浏览器全包了。而且用 method="dialog" 的表单按钮点击后会自动关闭对话框,不需要额外绑定事件。

3. 表单校验:浏览器自带的”前端验证”

很多项目里,表单校验是靠 JS 库(比如某些校验插件)一条条写规则。但 HTML 的表单属性已经能覆盖大部分基础场景:

<form>
  <input type="email" required placeholder="请输入邮箱">
  <input type="number" min="1" max="100" required>
  <input type="text" pattern="[A-Za-z]{3,}" title="至少3个字母">
  <button type="submit">提交</button>
</form>
  • required:必填
  • type="email":自动校验邮箱格式
  • min / max:数字范围
  • pattern:正则校验
  • minlength / maxlength:长度限制

不满足条件时,浏览器会自动弹出提示气泡,阻止表单提交,完全不需要写校验函数。当然,生产环境一般还需要后端二次校验,但前端这层”防呆”完全可以交给浏览器。

4. 更丰富的输入控件

<input>type 属性远比大多数人用到的多,很多场景不需要自己撸 UI 组件:

<input type="color">      <!-- 颜色选择器 -->
<input type="range">      <!-- 滑动条 -->
<input type="date">       <!-- 日期选择器 -->
<input type="datetime-local"> <!-- 日期+时间 -->
<input type="file" multiple> <!-- 多文件选择 -->

这些控件的样式和交互(比如日期弹出的小日历面板)都是浏览器原生渲染的,兼容性也已经相当不错。虽然样式在不同浏览器下略有差异,但功能上是完整的,很多后台管理系统的日期选择、颜色配置需求,其实用不着额外的组件库。

5. 输入建议列表:<datalist>

想做一个”输入时有下拉建议”的搜索框,通常第一反应是自己写个下拉列表组件。其实 HTML 有现成方案:

<input list="cityList" placeholder="输入城市">
<datalist id="cityList">
  <option value="北京">
  <option value="上海">
  <option value="广州">
  <option value="深圳">
</datalist>

用户输入时,浏览器会自动根据 datalist 里的内容过滤匹配项并展示下拉建议。适合简单的联想输入场景,不需要精细定制样式的话完全够用。

6. 弹出层新贵:popover 属性

这是相对较新的能力(主流浏览器已经支持),用来做提示气泡、下拉菜单这类”浮层”内容:

<button popovertarget="myPopover">打开提示</button>
<div id="myPopover" popover>
  这是一个原生弹出层,点击外部会自动关闭。
</div>

popover 属性会让这个元素脱离正常文档流,浮在页面最上层显示,并且自带”点击外部自动关闭””按 ESC 关闭”的行为,这些以前都得自己写事件监听和 z-index 管理。

7. 图片自适应与懒加载

响应式图片以前得靠 JS 判断视口宽度动态换图,现在 <picture>srcset 直接由浏览器决定加载哪张图:

<img src="small.jpg" 
     srcset="small.jpg 480w, large.jpg 1080w" 
     sizes="(max-width: 600px) 480px, 1080px"
     loading="lazy"
     alt="示例图片">

loading="lazy" 这一个属性,就能让图片在滚动到可视区域附近时才开始加载,完全不需要引入专门的图片懒加载库,也不用手写 IntersectionObserver

8. 进度和度量:<progress><meter>

进度条和”仪表盘式”的数值展示,也有对应的原生标签:

<progress value="70" max="100"></progress>
<meter value="0.6" min="0" max="1">60%</meter>

<progress> 用于表示任务进度(比如上传进度),<meter> 用于表示某个范围内的数值(比如磁盘使用率、电量)。两者语义不同,浏览器也会用不同的默认样式区分它们。

9. 输出计算结果:<output>

配合表单做实时计算展示(比如两个数字相加、滑动条联动数值),<output> 是专门为此设计的标签,语义上比一个普通 <span> 更准确,屏幕阅读器也能更好地识别它是”计算结果”:

<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
  <input type="number" id="a" value="0"> +
  <input type="number" id="b" value="0"> =
  <output name="result" for="a b">0</output>
</form>

这里确实用到了一点点 JS 做加法运算,但 <output> 本身的语义化标签能力是原生的。

10. 一些容易被忽略的小属性

除了上面这些”大件”,还有几个属性平时用得上,但很多人没注意到:

  • download:给 <a> 标签加上这个属性,点击链接就是下载文件而不是跳转打开,<a href="file.pdf" download>下载文件</a>
  • contenteditable:让任意元素变成可编辑区域,<div contenteditable="true">,相当于一个简易富文本编辑器的地基。
  • inert:给一个区域加上 inert,里面的所有元素都会失去焦点和交互能力,常用于弹窗打开时”冻结”背景内容,不用手动给每个子元素禁用事件。
  • autofocus:页面加载完自动聚焦到某个输入框,不需要 element.focus()

为什么要关注这些原生能力

写这篇文章不是说”JS 框架没用了”,复杂的交互、状态管理、组件复用,该用框架还是得用。但很多简单场景——一个折叠面板、一个表单校验、一个弹窗——完全可以用浏览器原生能力解决,好处很实在:

  • 代码量更少:少写逻辑,少踩 bug。
  • 性能更好:浏览器原生实现通常比 JS 模拟的更高效,尤其是弹窗的焦点管理、表单校验这些细节逻辑。
  • 无障碍支持更好:原生标签自带语义和键盘操作支持,比如 <dialog> 的 Tab 焦点循环、<details> 的键盘展开,这些是很多自己手写的组件容易忽略的。
  • 维护成本更低:少一个依赖,就少一次因为库升级或废弃带来的麻烦。

下次做需求评审的时候,不妨先想一下:这个功能,浏览器是不是早就帮我做好了?

© 版权声明

相关文章

暂无评论

none
暂无评论...