在日常写页面的过程中,大部分开发者对HTML属性的使用停留在class、id、href、src这一层。可HTML规范里其实定义了上百个属性,其中有不少冷门属性一旦用对地方,能省掉不少JavaScript代码,还能提升可访问性和性能。这篇文章挑出几个实用但出镜率不高的属性,配上代码示例逐个讲清楚它们能干什么、什么时候用。

download 属性:让链接变成下载而非跳转
当浏览器遇到一个指向图片、PDF或者压缩包的链接时,默认行为是尝试直接打开预览。如果希望用户点击后直接下载文件,不需要写JavaScript,只需要在<a>标签上加一个download属性即可:
<a href="report.pdf" download>下载报告</a> <!-- 还可以指定下载后的文件名 --> <a href="https://ippipp.com/ipipp.com/file/2024/data.csv" download="统计数据.csv">下载统计数据</a>
download属性有几个细节值得注意。第一,它只对同源URL或者blob:、data:协议的链接生效,跨域链接会被浏览器忽略,这是出于安全考虑的设计,防止恶意网站随意篡改用户下载的文件名。第二,如果属性值为空,浏览器会使用URL的最后一段作为文件名;如果给了值,就用这个值作为下载文件名。
这个属性最常见的进阶用法是配合Blob对象在前端动态生成文件,比如把页面上的表格数据导出成CSV,完全不需要请求后端:
<button id="exportBtn">导出配置</button>
<script>
document.getElementById('exportBtn').addEventListener('click', function () {
const data = JSON.stringify({ theme: 'dark', fontSize: 14 }, null, 2);
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'settings.json';
a.click();
URL.revokeObjectURL(url);
});
</script>这段代码在点击按钮时创建一个JSON内容的Blob,然后借助临时创建的链接和download属性触发下载,最后释放objectURL避免内存泄漏。整个流程纯前端完成,体验非常流畅。
translate 和 autocapitalize:控制输入与翻译行为
全球化站点经常遇到一个尴尬的问题:机器翻译插件会把代码片段、品牌名、按钮上的英文单词一起翻译掉,导致页面语义混乱。translate属性就是为解决这个问题而生:
<p>欢迎来到 <span translate="no">CodePilot</span> 平台</p> <pre translate="no">const app = createApp();</pre>
translate="no"会告诉浏览器和翻译插件不要翻译这个元素内部的内容。主流浏览器和Google翻译都支持这个属性。你也可以在html标签上统一设置<html translate="no">,然后对需要翻译的部分单独设置translate="yes",实现精细化控制。这个属性对技术文档类站点尤其重要,代码示例被翻译成中文绝对是灾难现场。
另一个相关的属性是autocapitalize,主要用于移动端表单。默认情况下iOS的Safari会在英文输入时自动把句首字母大写,这对邮箱、用户名这类字段非常不友好:
<input type="text" name="username" autocapitalize="none"> <input type="text" name="sentence" autocapitalize="sentences"> <input type="text" name="title" autocapitalize="words">
autocapitalize接受none、sentences、words、characters四个值,分别对应不大写、句首大写、每个单词首字母大写和全部大写。虽然桌面浏览器基本忽略它,但在移动端场景下能明显改善表单体验,尤其是登录页的用户名输入框。
hidden 和 inert:语义化地隐藏元素
提到隐藏元素,多数人第一反应是CSS的display:none。但HTML原生就提供了hidden属性,而且语义上更明确:
<div hidden>这段内容不会渲染,也不占据布局空间</div> <p hidden>等任务完成后通过JS移除hidden属性即可显示</p>
hidden属性的效果等价于display:none,元素不渲染、不占空间、不可聚焦、屏幕阅读器也不会朗读。它的优势在于语义化:任何看到hidden属性的人都能立刻明白这个元素当前处于隐藏状态,而CSS方案可能藏在几百行样式表的某个角落。需要注意的是,如果某个元素的CSS里显式设置了display:flex之类的值,会覆盖hidden的效果,这是个经典的坑,原因在于属性选择器的优先级低于具体的display声明。
比hidden更进一步的是inert属性,这是相对较新的标准,专门用于模态框场景:
<div id="page-content">
<!-- 页面主内容 -->
</div>
<dialog id="modal">
<p>确认删除这条记录吗?</p>
<button>确认</button>
</dialog>
<script>
const modal = document.getElementById('modal');
const content = document.getElementById('page-content');
modal.addEventListener('close', () => content.inert = false);
function openModal() {
content.inert = true; // 主内容区域不可交互、不可聚焦
modal.showModal();
}
</script>设置inert后,整个区域对用户完全不可交互:点击无效、Tab键无法聚焦进去、屏幕阅读器会跳过。这解决了模态框的一个老问题,打开弹窗后用户仍然可以用Tab键聚焦到底层页面的按钮上,导致焦点逃逸。以前需要复杂的焦点陷阱JavaScript来实现,现在一个属性就搞定,而且浏览器兼容性目前已经相当好了。
其他值得一试的小属性
除了上面重点介绍的几个,还有一些属性在特定场景下能派上大用场。
decoding属性用在img标签上,设置为async可以让浏览器异步解码图片,避免大图解码阻塞页面渲染:
<img src="banner.jpg" decoding="async" alt="横幅图片">
loading属性配合使用可以实现原生懒加载,值为lazy时浏览器会在图片快进入视口时才发起请求,替代了各种IntersectionObserver实现方案:
<img src="photo.jpg" loading="lazy" decoding="async" alt="照片">
inputmode属性能精确控制移动端弹出的键盘类型,比如inputmode="numeric"弹出纯数字键盘,inputmode="decimal"支持小数点,比type="number"在某些浏览器上的怪异行为更可控:
<input type="text" inputmode="numeric" placeholder="请输入手机号"> <input type="text" inputmode="decimal" placeholder="请输入金额">
dirname属性算是真正的冷门属性,它会随表单一起提交一个指示文字方向的字段,对阿拉伯语、希伯来语这类从右向左书写的语言很有用:
<form action="/comment" method="post"> <input type="text" name="comment" dirname="comment.dir"> <button type="submit">提交</button> </form>
提交时服务端除了收到comment字段,还会收到comment.dir,值为ltr或rtl,这样就能按正确的方向渲染用户输入的内容。
popover属性则是较新的能力,加上popover后元素变成一个由浏览器管理的弹出层,配合popovertarget的按钮就能实现开合交互,自动处理关闭、置顶和退出键行为:
<button popovertarget="menu">打开菜单</button> <div id="menu" popover> <ul><li>设置</li><li>退出登录</li></ul> </div>
这些属性的共同特点是:用声明式的HTML替代命令式的JavaScript,代码更短、行为更符合浏览器原生习惯、可访问性也更有保障。建议在下一个项目里试着用它们替换手写的弹窗管理和懒加载逻辑,你会明显感觉到代码量的减少和稳定性的提升。当然,使用前记得查一下Can I Use确认目标用户群体的浏览器支持情况,对于不支持的场景做好降级方案即可。
HTML属性hidden属性translate属性修改时间:2026-09-06 08:12:42