Что помимо input и label нужно использовать для формы

Ответ

Обязательно добавляй <form> для семантики и обработки событий submit. Используй <button type="submit"> для отправки. Для валидации и доступности:

<form>
  <div>
    <label for="email">Email</label>
    <input type="email" id="email" required>
    <span class="error" aria-live="polite"></span>
  </div>

  <fieldset>
    <legend>Выберите вариант</legend>
    <input type="radio" id="opt1" name="options">
    <label for="opt1">Вариант 1</label>
  </fieldset>

  <button type="submit">Отправить</button>
</form>

Ключевые элементы:

  • fieldset и legend для группировки
  • required для обязательных полей
  • Валидационные сообщения
  • aria-* атрибуты для доступности
  • CSRF-токен для безопасности (если нужно)

Ответ 18+ 🔞

Слушай, а вот этот твой <form> — это ж, блядь, как та самая тётка на рынке, которая всё в одну авоську собирает, а потом орёт, что чего-то не хватает. Так и тут: если не обернуть всё как надо, получится пиздец, а не форма.

Вот смотри, в чём прикол. Ты ж не просто кучу <input> на страну кидаешь? Ты их в структуру, в логику собираешь. <form> — это и есть та самая авоська, которая говорит браузеру: «Эй, чувак, вот эти все поля — они вместе, и их надо куда-то отправить одним махом». Без неё кнопка «Отправить» будет просто куском красивой, но бесполезной хуйни.

А <button type="submit"> — это уже прямой пинок под жопу этой самой авоське. «Ну чё, поехали, нефиг тут выёбываться!». Не type="button", а именно submit, иначе никуда она не поедет, будет тупить на месте.

Теперь про валидацию и доступность — это, сука, как инструкция к микроволновке. Кажется, да похуй, засунул — греется. А потом оказывается, что контейнер не для СВЧ, всё расплавилось, и ты сидишь с ебалом, обосанным от горя. Так и тут.

  • required на инпуте — это как надпись «Не суй сюда металлические вилки, долбоёб». Браузер сразу орёт, если поле пустое.
  • <fieldset> с <legend> — это как раздел в холодильнике: «Молочка», «Овощи». Не смешивай всё в одну кучу, а то потом ищешь сыр, а он между пивом и селёдкой завалялся. Группируй связанные радио-кнопки, чтобы и скринридер, и пользователь не ебали мозг.
  • aria-live="polite" на спане для ошибок — это шепоток на ушко скринридеру: «Слышь, братан, тут пользователь косякнул, сообщение вылезло, прочитай ему, но не перебивай». Без этого слепой юзер просто не узнает, в чём его косяк.
  • А for у лейбла, привязанный к id инпута — это вообще основа основ. Это как связать носки резиночкой, чтобы не растерять. Кликнул по тексту «Email» — курсор уже мигает в поле ввода. Магия, блядь! А без этого — кликаешь, хуй тебе, а не фокус.

И да, про безопасность. CSRF-токен — это как штампик в паспорт на входе в клуб. Без него тебя не пустят, потому что думают, что ты левый мудак, который хочет отправить данные от чужого имени. Просто вставь скрытое поле в форму, и все будут спокойны.

Вот, смотри, как это выглядит вживую, по твоему же примеру:

<form action="/submit-your-data" method="POST">
  <!-- Токен, чтоб всякие пидарасы не налетели -->
  <input type="hidden" name="_csrf" value="тут_длинная_хуйня_из_символов">

  <div>
    <label for="email">Твой email, будь человеком</label>
    <input type="email" id="email" name="email" required aria-describedby="email-error">
    <!-- Место для сообщения об ошибке, которое появится, если накосячишь -->
    <span id="email-error" class="error" aria-live="polite"></span>
  </div>

  <!-- Группировка, ёпта! Чтоб понятно было, что выбираешь ОДИН из вариантов -->
  <fieldset>
    <legend>Выбери один вариант, не будь тварью</legend>

    <input type="radio" id="opt1" name="options" value="1">
    <label for="opt1">Вариант первый (обычно самый скучный)</label>
    <br>

    <input type="radio" id="opt2" name="options" value="2">
    <label for="opt2">Вариант второй (тут уже веселее)</label>
  </fieldset>

  <!-- КНОПКА-ПИНОК. Без type="submit" форма будет просто молча смотреть на тебя, как баран на новые ворота -->
  <button type="submit">Отправить всё это дело</button>
</form>

Вот и вся философия. Сделал по этим правилам — и форма будет не просто куском верстки, а рабочим, доступным и безопасным механизмом. А не сделаешь — получишь мартышку с гранатой, которая в любой момент может ебнуть пользователю прямо в лицо.