← Назад к вопросам

Почему нельзя использовать div элемент вместо button в HTML?

2.0 Middle🔥 132 комментариев
#HTML и CSS#Оптимизация и производительность

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему DIV не должен заменять BUTTON

Это фундаментальный вопрос про семантику HTML и доступность. Расскажу почему это критично.

Проблема: неправильно сделанная кнопка

<!-- ПЛОХО - это не кнопка, а просто поле -->
<div class="button" onclick="handleClick()">
  Нажми на меня
</div>

<!-- ХОРОШО - это настоящая кнопка -->
<button onclick="handleClick()">
  Нажми на меня
</button>

Это не просто вопрос семантики - это влияет на функциональность!

1. Доступность (Accessibility)

Люди с ограничениями используют assistive technologies (скринридеры, клавиатура).

Скринридер не прочитает DIV как кнопку:

<!-- ПЛОХО - скринридер не знает что это кнопка -->
<div class="button" onclick="handleClick()">
  Удалить
</div>

<!-- Скринридер скажет: "Удалить" (просто текст)
     Не скажет что это интерактивный элемент!
     Пользователь может пропустить это
-->

<!-- ХОРОШО - скринридер понимает что это кнопка -->
<button onclick="handleClick()">
  Удалить
</button>

<!-- Скринридер скажет: "Кнопка Удалить"
     Пользователь знает что это нажимаемый элемент!
-->

2. Клавиатурная навигация

Многие пользователи используют клавиатуру (Tab, Enter, Space).

<!-- ПЛОХО - DIV не фокусируется по Tab -->
<div class="button" onclick="handleClick()">
  Отправить
</div>

<!-- Пользователь нажимает Tab - кнопка НЕ фокусируется
     Он может её вообще не увидеть
     Не может нажать Enter или Space
-->

<!-- ХОРОШО - BUTTON фокусируется автоматически -->
<button onclick="handleClick()">
  Отправить
</button>

<!-- Пользователь нажимает Tab - кнопка ФОКУСИРУЕТСЯ
     Он видит что кнопка выбрана (outline)
     Может нажать Enter или Space для активации
-->

3. Семантика HTML

HTML элементы имеют встроенный смысл (semantic meaning).

<!-- ПЛОХО - неправильная семантика -->
<div class="button" role="button" tabindex="0" onclick="...">
  Вход
</div>

<!-- Это выглядит как кнопка, но на самом деле DIV
     Браузер не знает какого поведения ожидать
     Поисковые системы не понимают назначение элемента
-->

<!-- ХОРОШО - правильная семантика -->
<button>
  Вход
</button>

<!-- Браузер ЗНАЕТ что это кнопка
     Применяет правильные стили по умолчанию
     Поддерживает правильное поведение
     SEO лучше индексирует
-->

4. Встроенное поведение браузера

BUTTON имеет встроенное поведение:

<!-- BUTTON автоматически обрабатывает -->
<button type="submit">Отправить</button>

<!-- Встроенное поведение:
  1. Enter активирует кнопку (не нужен onClick)
  2. Space активирует кнопку
  3. Поддерживает disabled состояние
  4. Показывает :focus состояние
  5. Показывает :active состояние
  6. Работает в формах
-->

<!-- DIV не имеет этого поведения -->
<div class="button" onclick="...">Отправить</div>

<!-- Нужно вручную реализовать:
  - Обработку клавиш
  - Обработку фокуса
  - Состояния
  - CSS для всех состояний
  - ARIA атрибуты
  -> Много лишнего кода!
-->

5. Встроенные стили и состояния

<!-- BUTTON имеет встроенные стили -->
<button>Нажми</button>

<!-- Браузер применяет стили по умолчанию
  - Видимая граница
  - Фон
  - Padding
  - Правильный cursor: pointer
  - :hover состояние
  - :active состояние
  - :disabled состояние
  - :focus состояние
-->

<!-- DIV требует стилизации -->
<div class="button">Нажми</div>

<!-- Нужно написать CSS:
  .button {
    border: ...
    background: ...
    padding: ...
    cursor: pointer;
  }
  .button:hover { ... }
  .button:active { ... }
  .button:focus { ... }
  -> Много кода!
-->

6. Правильный пример: React компонент

// ПЛОХО - DIV вместо button
function DeleteButton() {
  const handleClick = () => {
    deleteItem();
  };
  
  return (
    <div 
      className="delete-button"
      onClick={handleClick}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => e.key === 'Enter' && handleClick()}
      aria-label="Удалить"
    >
      Удалить
    </div>
  );
}

// ХОРОШО - button элемент
function DeleteButton() {
  const handleClick = () => {
    deleteItem();
  };
  
  return (
    <button onClick={handleClick} aria-label="Удалить">
      Удалить
    </button>
  );
}

// Второй вариант:
// - Короче
// - Понятнее
// - Доступнее
// - Работает везде

7. Используй правильные элементы

<!-- Для кнопки -->
<button>Действие</button>
<button type="submit">Отправить форму</button>
<button type="reset">Очистить форму</button>
<button type="button" disabled>Отключена</button>

<!-- Для ссылки -->
<a href="/page">Перейти на страницу</a>

<!-- Для input поля -->
<input type="text" placeholder="Введи текст">
<input type="email" placeholder="Email">
<input type="password" placeholder="Пароль">

<!-- Для текста -->
<p>Обычный текст</p>
<h1>Заголовок</h1>
<strong>Важное</strong>
<em>Выделенное</em>

<!-- Не использовать DIV для этого! -->
<div onclick="...">❌ НЕ ПРАВИЛЬНО</div>

8. ARIA атрибуты - это костыль

<!-- DIV с ARIA - плохое решение -->
<div 
  role="button"
  tabindex="0"
  aria-pressed="false"
  aria-label="Лайк"
  onclick="toggleLike()"
>
  ♥ Лайк
</div>

<!-- Это работает благодаря ARIA, НО:
  - Нужно вручную управлять фокусом
  - Нужно обрабатывать клавиши вручную
  - Нужны CSS состояния вручную
  - Это костыль над костылём
  - Легче ошибиться
-->

<!-- BUTTON - естественное решение -->
<button aria-pressed="false" aria-label="Лайк" onclick="toggleLike()">
  ♥ Лайк
</button>

<!-- Это просто работает:
  - Фокус управляется браузером
  - Клавиши обрабатываются браузером
  - Стили есть по умолчанию
  - Меньше ошибок
  - Меньше кода
-->

9. Проверка: правильно ли я сделал?

// Вопрос 1: Это действие или навигация?
// - Действие (удалить, отправить, сохранить) -> BUTTON
// - Навигация (перейти на страницу) -> LINK <a>

// Вопрос 2: Использую ли я click handler?
// - Да (onclick=...) -> probably BUTTON
// - Нет (обычная навигация) -> LINK

// Вопрос 3: Это часть формы?
// - Да (submit, reset) -> BUTTON
// - Нет -> BUTTON or LINK

// Вопрос 4: Может ли пользователь использовать клавиатуру?
// - Нет -> ПЛОХО, нужно исправить
// - Да -> ХОРОШО

// Вопрос 5: Может ли пользователь табуляции табом?
// - Нет -> ПЛОХО
// - Да -> ХОРОШО

10. Реальный пример: toggle кнопка

// ПЛОХО - DIV
function ToggleDarkMode() {
  const [isDark, setIsDark] = useState(false);
  
  return (
    <div 
      className={`toggle ${isDark ? 'dark' : 'light'}`}
      onClick={() => setIsDark(!isDark)}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          setIsDark(!isDark);
        }
      }}
    >
      {isDark ? '🌙' : '☀️'}
    </div>
  );
}

// ХОРОШО - button
function ToggleDarkMode() {
  const [isDark, setIsDark] = useState(false);
  
  return (
    <button 
      className={`toggle ${isDark ? 'dark' : 'light'}`}
      onClick={() => setIsDark(!isDark)}
      aria-label={isDark ? 'Включить светлую тему' : 'Включить тёмную тему'}
    >
      {isDark ? '🌙' : '☀️'}
    </button>
  );
}

// Второй вариант:
// - 40% меньше кода
// - Работает с клавиатурой
// - Доступен для скринридеров
// - Правильная семантика
// - Лучше для SEO

Итого

НИКОГДА не используй DIV вместо BUTTON потому что:

  1. Доступность - скринридеры не поймут
  2. Клавиатура - Tab и Enter не работают
  3. Семантика - неправильное значение
  4. Поведение - нет встроенного поведения браузера
  5. CSS - нужно писать много кода
  6. Состояния - focus, hover, disabled не работают
  7. SEO - поисковики не понимают
  8. Проще - BUTTON это стандартный элемент

Правильное правило:

  • Кнопка = <button>
  • Ссылка = <a href>
  • Текст = <p>, <div>
  • Input = <input>
  • Не нарушай семантику HTML!
Почему нельзя использовать div элемент вместо button в HTML? | PrepBro