🧑💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣
大家好!😁。
Code Review 的時候,我最怕看到什麼?
不是複雜的算法,也不是什麼正則。而是明明一個 HTML 標籤就能搞定的事,有人非要寫幾百行 JS + CSS 去重新發明輪子 。
前幾天,我看到一個新同學為了寫一個摺疊面板(Accordion),引入了一個重型的第三方庫,還寫了一堆 useState、onClick 和動畫邏輯。
我默默地把他的代碼全刪了,換成了 3 行 <details>。他看我的眼神,彷彿在看一個外星人🤣。
在 2025 年的今天,瀏覽器原生 HTML 的能力早已今非昔比。很多我們習慣用 JS 去模擬的交互,現在不僅有原生支持,而且性能更好、兼容性更強、無障礙(a11y)更完善。
今天,我就來盤點 5 個被嚴重低估的HTML標籤👇。
<details> & <summary>:摺疊組件
你是不是還在寫這樣的 React 代碼?
// 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 原生寫法:
<details>
<summary>點擊展開</summary>
<div class="content">
這裏是展開後的內容,原生支持 Ctrl+F 頁內搜索!
</div>
</details>
- 沒有任何JS:自帶點擊展開/收起交互。
- 無障礙(a11y)滿分:屏幕閲讀器能完美識別,Tab 鍵、回車鍵原生支持。
- 頁內搜索:這是 JS 模擬版最大的痛點。如果內容被 JS 隱藏了(
display: none),瀏覽器的 Ctrl+F 往往搜不到。但<details>裏的內容,即使摺疊,瀏覽器也能搜到並自動展開!
配合 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 原生
<dialog id="myModal">
<form method="dialog">
<p>這是一個原生模態框</p>
<button>關閉(自動)</button>
</form>
</dialog>
<button onclick="myModal.showModal()">打開彈窗⏏</button>
- Top Layer(頂層特性) :瀏覽器會把它渲染在所有 DOM 的最上層,徹底無視父元素的
z-index和overflow: hidden。 - ::backdrop 偽元素:直接用 CSS 定製遮罩層樣式。
/* 背景遮罩 */
dialog::backdrop {
background: rgba(0, 0, 0, 0.45);
backdrop-filter: blur(3px);
transition: opacity .3s ease;
}
- 原生交互:自帶
Esc關閉,自帶焦點管理,表單提交自動關閉。
<datalist>:搜索自動補全
當產品經理要求做一個帶搜索建議的輸入框時,你的第一反應是不是:“快!引入 Select2 或者 Antd AutoComplete!😖
且慢。如果只是簡單的建議列表,幾 KB 的 JS 庫都顯得太重了。
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>
- 模糊搜索:瀏覽器原生支持模糊匹配(打 u 會出來 Vue)。
- 響應式:在手機上,它會調用系統原生的下拉選擇 UI,體驗比網頁模擬的更順滑。
- 解耦:它只是一個建議列表,用户依然可以輸入列表裏沒有的值(這點和 Select 不同)。
<fieldset> & disabled:一鍵禁用整個表單
場景:用户點擊提交按鈕後,為了防止重複提交,我們需要禁用表單裏的所有輸入框。
JS 笨辦法:
// 還要一個個去拿 DOM,或者維護一個 loading 狀態傳給所有組件 inputs.forEach(input => input.disabled = true); buttons.forEach(btn => btn.disabled = true);
<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 原生:
<input type="file" capture="environment" accept="image/*">
只要加上 capture 屬性,在移動端(iOS/Android)點擊上傳時,系統會直接拉起相機,而不是讓你去選文件。拍完照後,你拿到的就是一個標準的 File 對象。
不需要什麼 JS SDK,實現原生級體驗👍。
我總是強調 最好的代碼,是沒有代碼!