autofocus / tabindex
autofocus 属性使页面加载时自动将焦点放到指定控件上,tabindex 属性控制元素在 Tab 键导航中的顺序。这两个属性对于表单交互体验和可访问性有重要影响,合理使用可以提升用户效率,但滥用可能造成困惑。
前置知识
阅读本节前,建议先了解:disabled / readonly
基础概念
autofocus 自动聚焦
autofocus 是一个布尔属性,添加后页面加载完成后浏览器会自动将焦点放在该控件上。主要特点:
- 页面加载时聚焦:只需在文档中设置,无需 JavaScript
- 仅一个有效:如果多个元素设置了
autofocus,只有第一个生效 - 提升效率:对于搜索框、登录框等首字段可以减少一次点击
- 移动端注意:自动聚焦会触发键盘弹出,可能影响布局
tabindex Tab 顺序
tabindex 属性控制元素是否可以通过 Tab 键获得焦点以及 Tab 顺序。主要特点:
- 正整数:按数值从小到大依次导航(1, 2, 3...)
- 0:按 DOM 顺序导航(默认行为)
- 负整数(-1):可通过编程获得焦点但不参与 Tab 导航
语法
autofocus 基本用法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>autofocus 示例</title>
</head>
<body>
<h2>搜索</h2>
<form>
<!-- 页面加载后自动聚焦搜索框 -->
<input type="search" name="q" autofocus placeholder="输入关键词搜索...">
<button type="submit">搜索</button>
</form>
</body>
</html>tabindex 基本用法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>tabindex 示例</title>
</head>
<body>
<h2>Tab 导航顺序</h2>
<form>
<!-- 按 tabindex 顺序导航 -->
<input type="text" name="last" placeholder="最后聚焦 (tabindex=3)" tabindex="3">
<input type="text" name="first" placeholder="首先聚焦 (tabindex=1)" tabindex="1">
<input type="text" name="middle" placeholder="其次聚焦 (tabindex=2)" tabindex="2">
</form>
<p>按 Tab 键,焦点按 1 → 2 → 3 的顺序跳转(非 DOM 顺序)。</p>
</body>
</html>详细说明
autofocus 最佳场景
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>autofocus 场景</title>
</head>
<body>
<!-- 场景一:登录框 -->
<h2>登录</h2>
<form>
<input type="text" name="username" autofocus placeholder="自动聚焦用户名">
<input type="password" name="password" placeholder="密码">
<button type="submit">登录</button>
</form>
<hr>
<!-- 场景二:搜索页 -->
<h2>搜索</h2>
<form>
<input type="search" name="q" autofocus placeholder="搜索...">
<button type="submit">搜索</button>
</form>
<hr>
<!-- 场景三:模态对话框 -->
<h2>确认对话框</h2>
<div style="padding: 20px; border: 2px solid #ddd; border-radius: 8px;">
<p>确定要删除此数据吗?</p>
<button type="button">取消</button>
<button type="button" autofocus>确认删除</button>
</div>
</body>
</html>tabindex 值说明
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>tabindex 值详解</title>
</head>
<body>
<h2>tabindex 三种值</h2>
<h3>tabindex="1"(正整数)</h3>
<p>按数值顺序导航,数值越小越先被聚焦:</p>
<div>
<input type="text" tabindex="3" placeholder="第三个 (tabindex=3)">
<input type="text" tabindex="1" placeholder="第一个 (tabindex=1)">
<input type="text" tabindex="2" placeholder="第二个 (tabindex=2)">
</div>
<h3>tabindex="0"(默认)</h3>
<p>按 DOM 顺序导航:</p>
<div>
<input type="text" tabindex="0" placeholder="第一个 (DOM 顺序)">
<input type="text" tabindex="0" placeholder="第二个 (DOM 顺序)">
<input type="text" tabindex="0" placeholder="第三个 (DOM 顺序)">
</div>
<h3>tabindex="-1"(不参与 Tab 导航)</h3>
<p>可通过 JavaScript focus() 聚焦,但不参与 Tab 导航:</p>
<div>
<input type="text" tabindex="-1" id="hidden-input" placeholder="Tab 跳不到这里">
<input type="text" tabindex="0" placeholder="正常 Tab 导航">
<button type="button" onclick="document.getElementById('hidden-input').focus()">
聚焦到上方输入框
</button>
</div>
</body>
</html>为非表单元素添加 tabindex
默认情况下,只有表单控件和链接可以通过 Tab 聚焦。使用 tabindex 可以为其他元素添加焦点支持:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>非表单元素 tabindex</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
.focusable {
padding: 12px 16px;
border: 2px solid #ddd;
border-radius: 6px;
margin-bottom: 8px;
cursor: pointer;
}
.focusable:focus {
border-color: #4a90d9;
outline: 3px solid rgba(74, 144, 217, 0.3);
background: #f0f7ff;
}
</style>
</head>
<body>
<h2>可聚焦的自定义元素</h2>
<p>按 Tab 键在这些 div 元素之间导航:</p>
<div class="focusable" tabindex="0" role="button">
卡片一(按 Tab 可聚焦)
</div>
<div class="focusable" tabindex="0" role="button">
卡片二(按 Tab 可聚焦)
</div>
<div class="focusable" tabindex="0" role="button">
卡片三(按 Tab 可聚焦)
</div>
<p>注意:为自定义可聚焦元素添加 <code>role</code> 属性有助于屏幕阅读器识别。</p>
</body>
</html>JavaScript 控制 tabindex
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>JS 控制 tabindex</title>
</head>
<body>
<h2>动态控制焦点</h2>
<form>
<input type="text" id="field1" placeholder="字段 1">
<input type="text" id="field2" placeholder="字段 2">
<input type="text" id="field3" placeholder="字段 3">
<button type="button" onclick="focusField('field2')">聚焦到字段 2</button>
<button type="button" onclick="disableTab('field3')">禁用字段3的Tab</button>
<button type="button" onclick="enableTab('field3')">启用字段3的Tab</button>
</form>
<script>
function focusField(id) {
document.getElementById(id).focus();
}
function disableTab(id) {
document.getElementById(id).tabIndex = -1;
}
function enableTab(id) {
document.getElementById(id).tabIndex = 0;
}
</script>
</body>
</html>实战示例
键盘友好的卡片导航
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>卡片导航</title>
<style>
body { font-family: sans-serif; max-width: 700px; margin: 40px auto; }
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.card {
padding: 20px;
border: 2px solid #ddd;
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.2s;
}
.card:hover { border-color: #4a90d9; }
.card:focus {
border-color: #4a90d9;
box-shadow: 0 0 0 3px rgba(74, 144, 217, 0.3);
outline: none;
}
.card .icon { font-size: 32px; margin-bottom: 8px; }
</style>
</head>
<body>
<h2>快捷操作</h2>
<p>使用 Tab 键导航到卡片,按 Enter 激活</p>
<div class="card-grid">
<div class="card" tabindex="0" role="button" onkeydown="if(event.key==='Enter') activateCard(this)">
<div class="icon">📝</div>
<div>新建文档</div>
</div>
<div class="card" tabindex="0" role="button" onkeydown="if(event.key==='Enter') activateCard(this)">
<div class="icon">📤</div>
<div>上传文件</div>
</div>
<div class="card" tabindex="0" role="button" onkeydown="if(event.key==='Enter') activateCard(this)">
<div class="icon">👁</div>
<div>搜索</div>
</div>
</div>
<p id="action-msg"></p>
<script>
function activateCard(card) {
const action = card.querySelector('div:last-child').textContent;
document.getElementById('action-msg').textContent = `已选择:${action}`;
}
</script>
</body>
</html>注意事项
不要滥用 autofocus
- 每个页面最多一个
autofocus - 避免在长页面中使用(可能自动滚动)
- 移动端自动聚焦会弹出键盘
- 无障碍用户可能被跳过其他内容困扰
避免过大的 tabindex 值
使用 tabindex="1", tabindex="2" 等小数值。如果值过大,后续维护时难以插入新的 Tab 位置。
非 0 tabindex 会打乱自然顺序
设置为正整数的元素会优先于 tabindex="0" 的元素被导航。
tabindex 在 modal 对话框中的应用
html
<!-- tabindex=-1 允许 JS 聚焦但不参与 Tab -->
<div class="modal" tabindex="-1" id="modal">
<!-- 打开时用 JS 聚焦到此 div -->
</div>
<script>
document.getElementById('modal').focus();
</script>最佳实践
- autofocus 限一个:每个页面最多一个 autofocus 元素
- Tab 顺序自然:尽量使用
tabindex="0"(DOM 顺序),避免自定义顺序 - 自定义组件支持 Tab:非原生可聚焦元素使用
tabindex="0"使其可 Tab 导航 - 配合 role 属性:为可聚焦的自定义元素添加
role提升可访问性 - 动态管理 tabindex:用 JavaScript 在需要时移除/添加 tabindex
- 避免 tabindex 大于 0:只在有明确需要时使用正整数 tabindex
下一节
继续学习:自定义验证消息