源本科技 | 码上会

密码显示与隐藏

2026/01/12
14
0

学习目标

  • 掌握通过切换 <input>type 属性实现密码可见性控制

  • 学会使用图标(如 👁️/🙉)作为交互按钮提升用户体验

  • 理解事件监听器在 DOM 操作中的核心作用

  • 实践现代表单设计的最佳实践:安全与可用性兼顾

  • 构建响应式、美观的登录输入组件


功能需求说明

在注册或登录表单中,用户常因输错密码而反复尝试。“显示 / 隐藏密码” 功能可让用户:

  • 核对输入内容是否正确

  • 避免因大小写、特殊字符等导致的错误

  • 在安全环境下临时查看密码(如移动端)


HTML 结构搭建

<div class="container">
  <label for="password">请输入密码</label>
  <div class="input-container">
    <input id="password" type="password" placeholder="您的密码" />
    <span class="eye-icon" id="togglePassword">👁️</span>
  </div>
</div>

结构解析:

  • label[for="password"]:语义化标签,提升无障碍访问支持

  • input[type="password"]:默认隐藏输入内容(显示为圆点)

  • span.eye-icon:使用 👁️ 图标作为切换按钮,不使用 <button> 避免表单意外提交

  • id="togglePassword":便于 JavaScript 精准绑定事件


CSS 样式设计

body {
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background-color: #f4f4f4;
}

.container {
  background-color: white;
  padding: 30px;
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  width: 300px;
  text-align: center;
}

label {
  font-size: 18px;
  margin-bottom: 10px;
  display: block;
  color: #333;
}

.input-container {
  display: flex;
  align-items: center;
  position: relative;
}

input {
  width: 100%;
  padding: 10px 40px 10px 10px; /* 右侧留出图标空间 */
  margin: 10px 0;
  border: 2px solid #ccc;
  border-radius: 5px;
  font-size: 16px;
  box-sizing: border-box;
}

.eye-icon {
  position: absolute;
  right: 10px;
  cursor: pointer;
  font-size: 20px;
  color: #666;
  user-select: none; /* 禁止选中图标 */
  transition: color 0.2s;
}

.eye-icon:hover {
  color: #007bff;
}

设计亮点:

  • 图标绝对定位:覆盖在输入框右侧,不占用额外空间

  • 输入框内边距调整:右侧 padding 增加,防止文字被图标遮挡

  • 悬停反馈:鼠标悬停时图标变蓝,提示可点击

  • 禁用文本选择:避免用户误选 👁️ 符号


JavaScript 交互逻辑

// 获取 DOM 元素
const passwordInput = document.getElementById('password');
const toggleIcon = document.getElementById('togglePassword');

// 绑定点击事件
toggleIcon.addEventListener('click', function () {
  if (passwordInput.type === 'password') {
    // 切换为明文显示
    passwordInput.type = 'text';
    toggleIcon.textContent = '🙈'; // 或使用 🙉 表示“已隐藏”
  } else {
    // 切换为密码隐藏
    passwordInput.type = 'password';
    toggleIcon.textContent = '👁️';
  }
});

关键机制

操作

技术实现

类型切换

修改 input.type 属性("password""text"

图标变化

动态更新 textContent:👁️ → 🙈

事件绑定

使用 addEventListener 替代内联 onclick,更符合现代开发规范

状态判断

通过 input.type 当前值决定下一步行为


完整代码整合

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>密码显示/隐藏</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-color: #f4f4f4;
    }
    .container {
      background-color: white;
      padding: 30px;
      border-radius: 10px;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
      width: 300px;
      text-align: center;
    }
    label {
      font-size: 18px;
      margin-bottom: 10px;
      display: block;
      color: #333;
    }
    .input-container {
      display: flex;
      align-items: center;
      position: relative;
    }
    input {
      width: 100%;
      padding: 10px 40px 10px 10px;
      margin: 10px 0;
      border: 2px solid #ccc;
      border-radius: 5px;
      font-size: 16px;
      box-sizing: border-box;
    }
    .eye-icon {
      position: absolute;
      right: 10px;
      cursor: pointer;
      font-size: 20px;
      color: #666;
      user-select: none;
      transition: color 0.2s;
    }
    .eye-icon:hover {
      color: #007bff;
    }
  </style>
</head>
<body>
  <div class="container">
    <label for="password">请输入密码</label>
    <div class="input-container">
      <input id="password" type="password" placeholder="您的密码" />
      <span class="eye-icon" id="togglePassword">👁️</span>
    </div>
  </div>

  <script>
    const passwordInput = document.getElementById('password');
    const toggleIcon = document.getElementById('togglePassword');

    toggleIcon.addEventListener('click', () => {
      if (passwordInput.type === 'password') {
        passwordInput.type = 'text';
        toggleIcon.textContent = '🙈';
      } else {
        passwordInput.type = 'password';
        toggleIcon.textContent = '👁️';
      }
    });
  </script>
</body>
</html>

进阶优化

  1. 键盘支持:按 Enter 聚焦输入框,按 Space 切换可见性

  2. 自动隐藏:3 秒无操作后自动隐藏密码(提升安全性)

  3. A11Y 支持:为图标添加 aria-label="显示密码"role="button"

  4. SVG 图标替代 Emoji:更稳定、可定制颜色和大小

  5. 多字段支持:封装为函数,支持多个密码框复用

// 示例:通用切换函数
function setupPasswordToggle(inputId, iconId) {
  const input = document.getElementById(inputId);
  const icon = document.getElementById(iconId);
  icon.addEventListener('click', () => {
    // ... 切换逻辑
  });
}

重点总结

  • 核心原理:通过动态修改 input.type 实现密码可见性切换

  • 用户体验:图标反馈 + 悬停效果 + 无障碍设计

  • 安全边界:前端可见 ≠ 数据泄露,后端仍需加密处理

  • 工程规范:分离结构、样式、行为,避免内联事件

  • 现代实践:使用 addEventListener 而非 onclick 属性


思考题

  1. 如果页面中有“确认密码”字段,如何让两个密码框的显示 / 隐藏状态同步?

  2. 使用 Emoji 作为图标可能存在兼容性问题(如旧版 Windows)。如何改用 SVG 实现相同效果?

  3. 为什么我们不直接用 <button> 而是用 <span>?如果一定要用按钮,应如何防止表单提交?