Skip to content

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">&#128221;</div>
            <div>新建文档</div>
        </div>
        <div class="card" tabindex="0" role="button" onkeydown="if(event.key==='Enter') activateCard(this)">
            <div class="icon">&#128228;</div>
            <div>上传文件</div>
        </div>
        <div class="card" tabindex="0" role="button" onkeydown="if(event.key==='Enter') activateCard(this)">
            <div class="icon">&#128065;</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>

最佳实践

  1. autofocus 限一个:每个页面最多一个 autofocus 元素
  2. Tab 顺序自然:尽量使用 tabindex="0"(DOM 顺序),避免自定义顺序
  3. 自定义组件支持 Tab:非原生可聚焦元素使用 tabindex="0" 使其可 Tab 导航
  4. 配合 role 属性:为可聚焦的自定义元素添加 role 提升可访问性
  5. 动态管理 tabindex:用 JavaScript 在需要时移除/添加 tabindex
  6. 避免 tabindex 大于 0:只在有明确需要时使用正整数 tabindex

下一节

继续学习:自定义验证消息

参考链接