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

В чем разница между button и div помимо screen reader?

1.2 Junior🔥 91 комментариев
#HTML и CSS

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

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

Разница между button и div помимо доступности для screen reader

Основное различие между <button> и <div> выходит далеко за рамки поддержки экранных читателей. <button> — это специализированный семантический элемент, который имеет встроенное поведение и функциональность, которую <div> полностью лишён.

1. Встроенное поведение (Native Behavior)

Button имеет встроенное функционирование:

// ✅ Button: работает по умолчанию
<button onClick={() => console.log('clicked')}>Нажми меня</button>

// Нажимается по:
// - Клику мыши
// - Enter при фокусе
// - Space при фокусе (задержка)
// - Мобильный тап

// ❌ Div: требует дополнительной логики
<div onClick={() => console.log('clicked')}>Нажми меня</div>
// Работает только при клике мышью!
// Enter и Space не сработают
// На мобильных сложно определить длинный тап

Практический пример:

function MyButton() {
  const handleClick = () => console.log('Нажата кнопка');
  
  return (
    <>
      <button onClick={handleClick}>Button (правильно)</button>
      
      <div onClick={handleClick}>Div (неправильно)</div>
    </>
  );
}

// При нажатии Enter:
// - Button: сработает handleClick ✅
// - Div: ничего не произойдёт ❌

2. Стили по умолчанию (Default Styling)

Button имеет встроенные стили

/* Button стили браузера */
button {
  padding: 6px 12px;
  border: 1px solid #ccc;
  background-color: #f0f0f0;
  cursor: pointer;
  border-radius: 4px;
  font-family: inherit;
}

button:hover {
  background-color: #e0e0e0;
}

button:active {
  background-color: #d0d0d0;
}

button:focus {
  outline: 2px solid blue;
}

/* Div не имеет стилей */
div {
  /* ничего */
}

Визуальное сравнение:

<!-- Button выглядит как кнопка из коробки -->
<button>Нажми меня</button>

<!-- Div выглядит как обычный текст -->
<div>Нажми меня</div>

3. Типы button

Тег <button> имеет встроенные типы с разным поведением:

<!-- type="submit" (по умолчанию) -->
<form>
  <input type="text" name="user" />
  <button type="submit">Отправить форму</button>
  <!-- При нажатии отправит данные формы -->
</form>

<!-- type="reset" -->
<form>
  <input type="text" name="user" value="John" />
  <button type="reset">Очистить форму</button>
  <!-- При нажатии вернёт значение на default -->
</form>

<!-- type="button" -->
<button type="button" onclick="doSomething()">Просто действие</button>
<!-- Ничего не отправляет, только вызывает функцию -->

<!-- Div не имеет таких встроенных типов -->
<div onclick="doSomething()">Просто текст</div>

4. Фокусируемость (Focusability)

Button фокусируется по умолчанию

// ✅ Button: доступен в табуляции
<button>Я в Tab order</button>
// Tab переместит фокус на эту кнопку

// ❌ Div: не фокусируется
<div>Я НЕ в Tab order</div>
// Tab пропустит этот div

// ✅ Div с tabindex: искусственно фокусируется
<div tabindex="0">Я в Tab order благодаря tabindex</div>

Это критично для пользователей, использующих только клавиатуру:

function Navigation() {
  return (
    <nav>
      {/* ✅ Правильно: можно переходить между кнопками через Tab */}
      <button>Главная</button>
      <button>О нас</button>
      <button>Контакты</button>
      
      {/* ❌ Неправильно: нельзя выбрать эти элементы через Tab */}
      <div onclick="goHome()">Главная</div>
      <div onclick="goAbout()">О нас</div>
      <div onclick="goContact()">Контакты</div>
    </nav>
  );
}

5. Обработка Enter и Space

Button обрабатывает клавиши автоматически

function App() {
  const handleAction = () => console.log('Action');
  
  return (
    <>
      {/* ✅ Button: работает с Enter и Space */}
      <button onClick={handleAction}>Button</button>
      {/* onClick сработает при: мышь, Enter, Space */}
      
      {/* ❌ Div: работает только с мышью */}
      <div onClick={handleAction} role="button">Div</div>
      {/* onClick НЕ сработает при Space (требует doSomething) */}
    </>
  );
}

Для корректной работы div нужно добавить обработчик клавиш:

function CustomButtonDiv() {
  const handleClick = () => console.log('Action');
  
  const handleKeyDown = (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      handleClick();
    }
  };
  
  return (
    <div
      onClick={handleClick}
      onKeyDown={handleKeyDown}
      role="button"
      tabIndex={0}
    >
      Div как кнопка (много кода!)
    </div>
  );
}

6. Состояния disabled

Button имеет встроенное состояние disabled

<!-- ✅ Button: встроенный disabled -->
<button disabled>Я отключена</button>
<!-- Браузер автоматически:
  - Блокирует клики
  - Меняет внешний вид
  - Исключает из Tab order
  - Оповещает screen reader
-->

<!-- ❌ Div: нужно всё делать вручную -->
<div aria-disabled="true" class="disabled">Я отключена</div>
<!-- Нужно добавить стили, обработку клавиш, aria-disabled -->

Практический пример:

function SubmitForm() {
  const [loading, setLoading] = useState(false);
  
  return (
    <form>
      <input type="text" />
      
      {/* ✅ Правильно: браузер знает, что кнопка отключена */}
      <button disabled={loading} type="submit">
        {loading ? 'Загрузка...' : 'Отправить'}
      </button>
    </form>
  );
}

7. Form Submission

Button в форме имеет встроенное поведение

function MyForm() {
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Форма отправлена');
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="username" />
      
      {/* ✅ Button: при нажатии триггерит submit событие */}
      <button type="submit">Отправить</button>
      
      {/* ❌ Div: не триггерит submit */}
      <div onClick={() => handleSubmit()}>Отправить</div>
    </form>
  );
}

8. Мобильные браузеры

Button имеет встроенное поведение на мобилях

<!-- ✅ Button: оптимизирован для сенсорных устройств -->
<button>Нажми на мобиле</button>
<!-- Браузер добавляет hover эффект, точку фокуса -->

<!-- ❌ Div: требует дополнительной логики -->
<div onclick="action()">Нажми на мобиле</div>
<!-- Может быть сложно точно нажать -->

9. Стили для состояний

Button имеет встроенные styles для :active, :focus

/* ✅ Button: браузер знает эти состояния */
button:hover { background: #ddd; }
button:active { transform: scale(0.98); }
button:focus { outline: 2px solid blue; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

/* ❌ Div: нужно всё прописывать вручную */
.custom-button:hover { background: #ddd; }
.custom-button:active { transform: scale(0.98); }
.custom-button.focused { outline: 2px solid blue; }
.custom-button.disabled { opacity: 0.5; cursor: not-allowed; }

Полное сравнение в таблице

АспектButtonDiv
Клик мышью
Активация Enter
Активация Space
В Tab order✅ (auto)❌ (нужен tabindex)
Встроенный disabled
Стили по умолчанию
Form submission
Keyboard handling✅ (auto)❌ (manual)
Screen reader поддержка
Состояния (:hover, :focus)

Когда использовать что

// ✅ Используй BUTTON для действий
<button onClick={handleDelete}>Удалить</button>
<button type="submit">Отправить форму</button>
<button type="reset">Очистить</button>

// ✅ Используй DIV для структуры/контейнера
<div className="container">...</div>
<div className="card">...</div>
<div className="layout">...</div>

// ❌ НЕ используй DIV для действий (даже с onclick)
<div onClick={handleAction}>Это не кнопка</div>

// ❌ НЕ используй BUTTON только для стилей
<button className="fancy-box">Это контейнер, не кнопка</button>

Итоги

Использование <button> вместо <div> для интерактивных элементов — это не просто вопрос доступности. Это обеспечивает:

  • Встроенное поведение: Enter, Space, фокус
  • Встроенные стили: наглядность, что это кнопка
  • Встроенные состояния: disabled, hover, active, focus
  • Форма-интеграция: работа с формами
  • Мобильная оптимизация: лучшее сенсорное взаимодействие
  • Меньше кода: не нужно повторять логику
  • Лучший SEO: семантический HTML

Всегда используй семантический HTML для своего назначения — <button> для кнопок, а не <div>.