Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> CSS

Cách ẩn mũi tên tăng/giảm (spinner) của input type number bằng CSS

Giới thiệu

Trình duyệt mặc định hiển thị spinner (mũi tên lên/xuống) cho <input type="number">. Để thiết kế tùy chỉnh hoặc tránh UX rối mắt, CSS cung cấp pseudo-elements để ẩn chúng trên WebKit/Blink (Chrome, Edge, Safari) và Firefox.

Ví dụ hoàn chỉnh

<!DOCTYPE html>
<html lang="vi">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ẩn Spinner Input Number</title>
  <style>
    * { box-sizing: border-box; }
    body { font-family: 'Segoe UI', system-ui, sans-serif; padding: 40px 20px; background: #f5f5f5; }
    .demo { max-width: 400px; margin: 0 auto; background: #fff; padding: 32px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
    h1 { text-align: center; margin: 0 0 8px; font-size: 22px; }
    .desc { text-align: center; color: #666; margin-bottom: 24px; font-size: 14px; }
    .number-input {
      width: 100%;
      padding: 14px 16px;
      font-size: 18px;
      text-align: center;
      border: 2px solid #e0e0e0;
      border-radius: 10px;
      background: #fafafa;
      transition: border-color 0.2s, box-shadow 0.2s;
    }
    .number-input:focus { outline: none; border-color: #667eea; box-shadow: 0 0 0 3px rgba(102,126,234,0.15); }
    /* CSS quan trọng: Ẩn spinner */
    input[type="number"]::-webkit-outer-spin-button,
    input[type="number"]::-webkit-inner-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
    input[type="number"] {
      -moz-appearance: textfield; /* Firefox */
    }
    /* Custom controls (tùy chọn) */
    .number-wrapper { position: relative; }
    .number-wrapper .spin-btn {
      position: absolute; right: 8px; width: 32px; height: 50%;
      background: #f0f0f0; border: none; color: #333;
      cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center;
      transition: background 0.2s;
    }
    .number-wrapper .spin-btn.up { top: 0; border-radius: 0 8px 0 0; border-bottom: 1px solid #e0e0e0; }
    .number-wrapper .spin-btn.down { bottom: 0; border-radius: 0 0 8px 0; }
    .number-wrapper .spin-btn:hover { background: #e0e0e0; }
    .number-wrapper input { padding-right: 44px; }
  </style>
</head>
<body>
  <div class="demo">
    <h1>Input Number Không Spinner</h1>
    <p class="desc">Mặc định trình duyệt ẩn spinner. Dưới có custom controls.</p>
    <label style="display:block; margin-bottom:8px; font-weight:500">Số lượng (mặc định)</label>
    <input type="number" class="number-input" value="10" min="0" max="100">
    <p style="margin:24px 0 8px; font-weight:500">Với custom tăng/giảm</p>
    <div class="number-wrapper">
      <input type="number" class="number-input" id="qty" value="1" min="1" max="99">
      <button type="button" class="spin-btn up" aria-label="Tăng"><i class="fas fa-chevron-up"></i></button>
      <button type="button" class="spin-btn down" aria-label="Giảm"><i class="fas fa-chevron-down"></i></button>
    </div>
  </div>
  <script>
    const input = document.getElementById('qty');
    document.querySelector('.spin-btn.up').addEventListener('click', () => {
      if (input.value < input.max) input.stepUp();
    });
    document.querySelector('.spin-btn.down').addEventListener('click', () => {
      if (input.value > input.min) input.stepDown();
    });
  </script>
</body>
</html>

CSS cốt lõi để ẩn Spinner

/* Chrome, Safari, Edge, Opera (WebKit/Blink) */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Firefox */
input[type="number"] {
  -moz-appearance: textfield;
}

Lưu ý quan trọng

  • Không dùng appearance: none cho toàn bộ input: Sẽ xóa cả style mặc định khác (border, padding...). Chỉ target pseudo-elements spinner.
  • Firefox: Cần -moz-appearance: textfield trên chính input.
  • Safari iOS: Vẫn có thể hiển thị stepper trên bàn phím số - không thể ẩn bằng CSS.
  • Validation: type="number" vẫn chặn ký tự không phải số, dù ẩn spinner.

Custom Controls (Khuyên dùng)

Thay spinner mặc định bằng nút +/- tùy chỉnh (như ví dụ):

  • Kiểm soát UI hoàn toàn (màu, size, shape).
  • Dùng input.stepUp() / input.stepDown() JS - giữ validation min/max.
  • Accessibility: aria-label trên nút, type="button" (không submit form).