```HTML 可以做到这一点```
HTML Can Do That

原始链接: https://chrisburnell.com/html-can-do-that/

现代 HTML 已经演进到可以处理以往需要 JavaScript 才能实现的动态功能,从而减少了对自定义脚本的需求。现在浏览器原生内置的关键功能包括: * **UI 组件:** `popover` 属性、`

` 元素以及 `command`/`commandfor` 属性,无需 JS 即可实现轻量级模态框和交互式菜单。 * **折叠面板逻辑:** 在 `
` 元素上使用 `name` 属性,可以实现互斥的折叠面板,即打开一项时会自动关闭其他项。 * **浏览器原生工具:** 内置功能如输入选择器(颜色、范围、日期)、用于自动补全的 ``,以及图片的 `loading="lazy"` 属性,简化了常见的开发任务。 * **内容管理:** `hidden="until-found"` 属性允许浏览器在用户通过搜索导航到隐藏内容时,自动将其显示出来。 虽然这些工具为传统库提供了强大且轻量的替代方案,但作者提醒,不同浏览器的实现存在差异。开发者在处理样式不一致和潜在的无障碍功能缺陷时应保持谨慎。在实现这些现代 HTML 特性时,务必优先考虑包容性设计和无障碍测试,因为其中一些特性尚未“完善”或缺乏普遍支持。

这篇 Hacker News 的讨论探讨了原生 HTML 和 CSS 替代复杂 JavaScript 框架的能力。贡献者们指出,现代特性(如 `
`、`popover` 以及高级 CSS 选择器)可以在无需大量客户端代码的情况下处理折叠菜单、图像预览和响应式布局等交互。 然而,大家的共识并不绝对。尽管许多人赞赏“少即是多”的方法,参与者也指出了原生元素的关键局限性。例如,`` 元素常因缺乏模糊搜索、容错处理以及企业级表单所需的严格验证而备受诟病,这往往导致开发者仍需依赖专用库或“React islands”。 总的来说,该讨论反映出一种转向利用原生浏览器特性以提升性能和简洁性的趋势,但同时也考虑到原生 HTML 在处理复杂、高度交互的 UI 组件时仍显吃力。用户们依然渴望针对可排序表格等常见需求提供原生解决方案,而另一些人则提醒,不应在声明式语言中添加“尚未完善”的特性,以免导致各浏览器间支持不一致的问题。
相关文章

原文

HTML has been gobbling up swathes of what used to be JavaScript’s remit. This page lists a bunch of dynamic functionality that we can now achieve with just HTML.


Update : I originally built this page in one hour during HTML Day 2026 to write and celebrate HTML, but I’ve since made some edits to better express and highlight where the browser implementation of some of this stuff is severely lacking and/or completely fails to meet accessibility needs. So, by all means, try it out, but make it as accessible as you can!


popover

Available since January 2025
  • Chrome 114+
  • Edge 114+
  • Firefox 125+
  • Opera 100+
  • Safari 17+
  • Chrome Android 114+
  • Firefox for Android 125+
  • Opera Android 76+
  • Safari on iOS 17+
  • Samsung Internet 23+
  • WebView Android 114+

Light dismiss, Esc to close, no managing z-index to wrangle it onto a top later. All managed with popover and popovertarget attributes in HTML. (MDN)

No JavaScript, just modern browser magic, thanks to the wonderful folks speccing for the web and building our browsers!

<button popovertarget="example-popover">Toggle popover</button>
<div id="example-popover" popover>
	<p>No JavaScript, just modern browser magic, thanks to the wonderful folks speccing for the web and building our browsers!</p>
</div>

<dialog>

Available since March 2022
  • Chrome 37+
  • Edge 79+
  • Firefox 98+
  • Opera 24+
  • Safari 15.4+
  • Chrome Android 37+
  • Firefox for Android 98+
  • Opera Android 24+
  • Safari on iOS 15.4+
  • Samsung Internet 3+
  • WebView Android 37+

Similar thing going on as popover here, except this time with a dedicated element for modal dialog boxes. (MDN)

See command / commandFor below for another, more recently-landing feature that allows us to open and close dialog elements (and will be useful for lots of other non-JS functionality, one day!).

Once again the popover attribute is doing some heavy-lifting here!

<button popovertarget="example-dialog">Toggle popover</button>
<dialog id="example-dialog" popover>
	<p>Closed with just HTML via <code>&lt;form method="dialog"&gt;</code>, opened with the <code>popover</code> attribute.</p>
	<button popovertarget="example-dialog" popovertargetaction="hide">Close</button>
</dialog>

Even though it’s sort of against the spirit of this page, I want to include this short snippet of how to interact with dialog elements in JavaScript:

This one is opened with .showModal() and closed with .close(), both called from JavaScript.

Show JS-powered dialog code
<button id="example-dialog-js-open">Open dialog</button>
<dialog id="example-dialog-js">
	<p>This one is opened with <code>.showModal()</code> and closed with <code>.close()</code>, both called from JavaScript.</p>
	<button id="example-dialog-js-close">Close</button>
</dialog>
document.getElementById("example-dialog-js-open").addEventListener("click", () => {
	document.getElementById("example-dialog-js").showModal()
})
document.getElementById("example-dialog-js-close").addEventListener("click", () => {
	document.getElementById("example-dialog-js").close()
})

Grouped <details>

Available since September 2025
  • Chrome 120+
  • Edge 120+
  • Firefox 130+
  • Opera 106+
  • Safari 17.2+
  • Chrome Android 120+
  • Firefox for Android 130+
  • Opera Android 80+
  • Safari on iOS 17.2+
  • Samsung Internet 25+
  • WebView Android 120+

A shared name attribute turns a group of <details> into an exclusive accordion. Open one and the others close automatically. Magic! (MDN)

First

Open the seond one and watch this close on its own.

Second

First one’s hidden now.

<details name="example-group">
	<summary>First</summary>
	<p>Open the seond one and watch this close on its own.</p>
</details>
<details name="example-group">
	<summary>Second</summary>
	<p>First one’s hidden now.</p>
</details>

command & commandfor

Available since December 2025
  • Chrome 135+
  • Edge 135+
  • Firefox 144+
  • Opera 120+
  • Safari 26.2+
  • Chrome Android 135+
  • Firefox for Android 144+
  • Opera Android 89+
  • Safari on iOS 26.2+
  • Samsung Internet 29+
  • WebView Android 135+

Separate HTML buttons controlling one popover. No scripting. (MDN)

Note: So far only show-modal, close, request-close, toggle-popover, show-popover, and hide-popover have landed stable in browsers. We can look forward to invokers supported in the future to increment/decrement values, interact with media elements, copy text, etc.

show-popover opens this and hide-popover closes it!

<button command="show-popover" commandfor="example-command-popover">Open</button>
<button command="hide-popover" commandfor="example-command-popover">Close</button>
<dialog id="example-command-popover" popover>
	<p><code>show-popover</code> opens this and <code>hide-popover</code> closes it!</p>
	<button command="hide-popover" commandfor="example-command-popover">Close</button>
</dialog>

Native input pickers

Available since March 2017
  • Chrome: Colour 20+, Range 4+, Date 20+
  • Edge: Colour 14+, Range 12+, Date 12+
  • Firefox: Colour 29+, Range 23+, Date 57+
  • Opera: Colour 12+, Range 11+, Date 11+
  • Safari: Colour 12.1+, Range 3.1+, Date 14.1+
  • Chrome Android: Colour 25+, Range 57+, Date 25+
  • Firefox for Android: Colour 27+, Range 52+, Date 57+
  • Opera Android: Colour 12+, Range 11+, Date 11+
  • Safari on iOS: Colour 12.2+, Range 5+, Date 5+
  • Samsung Internet: Colour 1.5+, Range 7+, Date 1.5+
  • WebView Android: Colour 4.4+, Range 4.4+, Date 4.4+

Colour, range, and date pickers, built right into the browser. (MDN: Color Input, MDN: Range Input, MDN: Color Input)

Warning! Some of these elements feel a little unfinished. I’m hoping that we can expect form elements to receive some more love over the coming years, but at this point in time, the implementations shipping in browsers are still lacking. I would tread very carefully with using some of these. You can expect things like the default browser styles of these elements to vary pretty wildly between browsers and for the accessibility experienecs to be very poor. Be wary of the many pitfalls!

<label>Colour <input type="color" value="#5f8aa6" autocomplete="off"></label>
<label>Range <input type="range" min="0" max="100" value="50" autocomplete="off"></label>
<label>Date <input type="date" autocomplete="off"></label>

<datalist>

Available since March 2019
  • Chrome 20+
  • Edge 12+
  • Firefox 4+
  • Opera 9.5+
  • Safari 12.1+
  • Chrome Android 33+
  • Firefox for Android 79+
  • Opera Android 20+
  • Safari on iOS 12.2+
  • Samsung Internet 2+
  • WebView Android 4.4.3+

Native autocomplete suggestions, no dropdown library required. (MDN)

Warning! Support for this across input types is still pretty spotty, and there are also a number of issues in its implementation in browsers. See Adrian Roselli’s Under-Engineered Comboboxen for more info. You might even want to skip using this for now, and keep an eye on it to see if it improves over the new few years.

<label>Favourite HTML element <input type="text" id="example-datalist-input" list="example-datalist" autocomplete="off"></label>
<datalist id="example-datalist">
	<option value="a">
	<option value="abbr">
	<option value="address">
	<!-- ... -->
</datalist>

loading="lazy"

Available since March 2022
  • Chrome 77+
  • Edge 79+
  • Firefox 75+
  • Opera 64+
  • Safari 15.4+
  • Chrome Android 77+
  • Firefox for Android 79+
  • Opera Android 55+
  • Safari on iOS 15.4+
  • Samsung Internet 12+
  • WebView Android 77+

This image defers loading until it’s near the viewport. Not an IntersectionObserver in sight. (MDN)

Chris Burnell’s avatar.
<img src="/images/[email protected]" loading="lazy" width="200" height="200" alt="Chris Burnell’s avatar.">

hidden until-found

Available since December 2025
  • Chrome 102+
  • Edge 102+
  • Firefox 148+
  • Opera 88+
  • Safari 26.2+
  • Chrome Android 102+
  • Firefox for Android 148+
  • Opera Android 70+
  • Safari on iOS 26.2+
  • Samsung Internet 19+
  • WebView Android 102+

Navigating to the fragment link below reveals the hidden section. The browser automatically removes hidden="until-found". (MDN)

Note: This one’s still pretty new and only really plays nicely with browser default search, and not so well with screen reader search implementations, for example. Still, one to keep in the back pocket for another day down the road!

Jump to hidden content
<a href="#example-until-found">Jump to hidden content</a>
<div id="example-until-found" hidden="until-found">
	<p>Yahaha! You found me!</p>
</div>

Written and built by Chris Burnell for HTML Day 2026 during the Online Event run by Zachary Kai on .

联系我们 contact @ memedata.com