Вывод сообщения об ошибке html

Welcome to a quick tutorial on how to show error messages in HTML forms. This is probably one of the major bugbears for some beginners, how do we handle and show error messages for HTML forms?

There are no fixed ways to show errors in HTML forms, but the common methods to display error messages are:

  1. Simply add checking attributes to the HTML form fields, and the browser will automatically show the errors. For example, <input type="text" required>
  2. Use Javascript to show custom error messages as the user types in the fields.
  3. Collectively show all error messages in a popup box when the user submits an invalid form.
  4. Show error messages below the invalid fields.

That covers the broad basics, let us walk through detailed examples in this guide – Read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

TABLE OF CONTENTS

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

DISPLAY ERROR MESSAGES

All right, let us now get into the various examples of displaying error messages in an HTML form.

EXAMPLE 1) DEFAULT ERROR DISPLAY

1-default.html

<form onsubmit="return false;">
  <label for="fname">Name</label>
  <input type="text" name="fname" id="fname" required minlength="2" maxlength="8">

  <label for="fnumber">Number</label>
  <input type="number" name="fnumber" id="fnumber" min="1" max="12">

  <label for="fyes">Enter "Yes"</label>
  <input type="text" name="fyes" id="fyes" required pattern="Yes">

  <input type="submit" value="Go!">
</form>

Oh no, displaying error messages is SO DIFFICULT! Not. Just add the form checking attributes to the fields:

  • required Self-explanatory. A required field that cannot be left blank.
  • min-length max-length The minimum and maximum number of characters allowed.
  • min max For number fields only, the minimum and maximum allowed values.
  • pattern This field must match the custom pattern. Will leave a link in the extras section below if you want to learn more.

Yes, that’s all. The browser will do the rest of the magic.

EXAMPLE 2) SHOW ERRORS AS-YOU-TYPE

2-type.html

<!-- (A) HTML FORM -->
<form onsubmit="return false;">
  <label for="fname">Name</label>
  <input type="text" name="fname" id="fname" required minlength="2" maxlength="8">
 
  <input type="submit" value="Go!">
</form>
 
<!-- (B) SET CUSTOM ERROR MESSAGE -->
<script>
var fname = document.getElementById("fname");
fname.addEventListener("input", () => {
  if (fname.validity.tooLong || fname.validity.tooShort || fname.validity.valueMissing) {
    fname.setCustomValidity("Name must be 2-8 characters.");
    fname.reportValidity();
  } else { fname.setCustomValidity(""); }
});
</script>

This one is a little naggy and requires some Javascript. A couple of functions and properties to take note of here:

  • document.getElementById("ID") Get element by ID. Captain Obvious.
  • FIELD.addEventListener("input", FUNCTION) Run this function whenever the user types something in the field.
  • FIELD.validity.tooLong FIELD.validity.tooShort FIELD.validity.valueMissing We can actually target various invalid statuses and show different messages. Will leave a link in the extras section below to the full list.
  • FIELD.setCustomValidity("MESSAGE") and FIELD.reportValidity() Show custom error message.

EXAMPLE 3) DISPLAY ERROR MESSAGES IN POPUP

3-alert.html

<!-- (A) HTML FORM -->
<form onsubmit="return check()" novalidate>
  <label for="fname">Name</label>
  <input type="text" name="fname" id="fname" required minlength="2" maxlength="8">

  <label for="fnumber">Number</label>
  <input type="number" name="fnumber" id="fnumber" required min="1" max="12">

  <input type="submit" value="Go!">
</form>
 
<!-- (B) FORM CHECK -->
<script>
function check () {
  // (B1) INIT
  var error = "", field = "";
 
  // (B2) NAME
  field = document.getElementById("fname");
  if (!field.checkValidity()) {
    error += "Name must be 2-4 charactersrn";
  }

  // (B3) NUMBER
  field = document.getElementById("fnumber");
  if (!field.checkValidity()) {
    error += "Num must be between 1-12rn";
  }

  // (B4) RESULT
  if (error=="") { return true; }
  else {
    alert(error);
    return false;
  }
}
</script>

The less naggy method, where all the error messages are compiled into a single popup. Take note:

  • A novalidate has been added to the <form> tag. This disables the default browser form checking, and we do our own in Javascript using onsubmit="return check()".
  • The Javascript is pretty long-winded but straightforward.
    • Use var error = "" to collect all the error messages.
    • Fetch the field we want to check field = document.getElementById("ID").
    • Add a message if it is invalid if (!field.checkValidity()) { error += "ERROR"; }
    • That’s all, repeat the check for all fields.
    • Lastly, show the error message if not empty and don’t allow the form submission if (error !="") { alert(error); return false; }

EXAMPLE 4) SHOW ERROR MESSAGE UNDER FIELD

4-below.html

 <!-- (A) SOME SIMPLE ERROR STYLES -->
<style>
.err { background: #ffe6ee; border: 1px solid #b1395f; }
.emsg { color: #c12020; font-weight: bold; }
</style>
 
<!-- (B) HTML FORM -->
<form onsubmit="return check()" novalidate>
  <label for="fname">Name</label>
  <input type="text" name="fname" id="fname" required minlength="2" maxlength="8">
  <div id="cname" class="emsg"></div> 
 
  <label for="fnumber">Number</label>
  <input type="number" name="fnumber" id="fnumber" required min="1" max="12">
  <div id="cnumber" class="emsg"></div>
 
  <input type="submit" value="Go!">
</form>
 
<!-- (C) FORM CHECK -->
<script>
function check () {
  // (C1) INIT
  var valid = true, error = "", field = "";

  // (C2) NAME
  field = document.getElementById("fname");
  error = document.getElementById("cname");
  if (!field.checkValidity()) {
    valid = false;
    field.classList.add("err");
    error.innerHTML = "Name must be 2-4 charactersrn";
  } else {
    field.classList.remove("err");
    error.innerHTML = "";
  }

  // (C3) NUMBER
  field = document.getElementById("fnumber");
  error = document.getElementById("cnumber");
  if (!field.checkValidity()) {
    valid = false;
    field.classList.add("err");
    error.innerHTML = "Num must be between 1-12rn";
  } else {
    field.classList.remove("err");
    error.innerHTML = "";
  }

  // (C4) RESULT
  return valid;
}
</script>

Lastly, this is pretty much similar to the popup example.

  • Use novalidate and onsubmit to do our own customization.
  • But instead of showing in a popup, we attach a <div class="emsg"> below all fields.
  • On an invalid input, we show the error message in the <div>  instead.

LINKS & REFERENCES

  • HTML Pattern – MDN
  • Validity State – MDN
  • Form Validation – MDN
  • HTML Form Validation Without Javascript – Code Boxx

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

For show an error message below this it if a user puts some wrong value inside that field, yes you are talking about showing validation errors. There are two types of these validation error messages available in HTML 5:

  1. Automatic messages
  2. Custom messages

Automatic Messages

Automatic messages simply use HTML5 form attributes. But the disadvantage is they are automatic, not customizable by default. For example if you require an email, the default error message on Firefox, when you specify an email input and fail to write one: Please enter an email address, you would not be able to change this using just HTML and CSS.

Another disadvantage is the default message depends on the browser locale, so if for example you are borrowing your friend’s French computer to view an English website, those default error messages will then display in French:

screenshot Firefox rendering of error message

Source: Mozilla Developer Network article: Data form validation

Custom messages

As Data form validation says:

To customize the appearance and text of these messages, you must use JavaScript; there is no way to do it using just HTML and CSS.

HTML5 provides the constraint validation API to check and customize the state of a form element.

The example from Data form validation:

<form>
  <label for="mail">I would like you to provide me an e-mail</label>
  <input type="email" id="mail" name="mail">
  <button>Submit</button>
</form>
var email = document.getElementById("mail");

email.addEventListener("keyup", function (event) {
  if (email.validity.typeMismatch) {
    email.setCustomValidity("I expect an e-mail, darling!");
  } else {
    email.setCustomValidity("");
  }
});

So yes, you can have messages below the input in HTML5. Just beware that they will either be the automatic type, or, to customize, you need to look into using the constraint validation API to write your own messages using JavaScript.

Валидация форм на стороне клиента

  • Назад (en-US)
  • Обзор: Forms
  • Далее

Перед отправкой данных на сервер важно убедиться, что все обязательные поля формы заполнены данными в корректном формате. Это называется валидацией на стороне клиента и помогает убедиться, что данные, введённые в каждый элемент формы, соответствуют требованиям. Данная статья проведёт вас через основные концепци и примеры валидации на стороне клиента.

Начальные требования: Владение компьютером, достаточное понимание HTML, CSS, и JavaScript.
Цель: Понять, что такое валидация на стороне клиента, почему это важно и как применять различные техники для её реализации.

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

Однако, не следует рассматривать валидацию на стороне клиента как достаточную меру безопасности! Любые данные, отправляемые через форму, необходимо дополнительно проверять на безопасность и на стороне сервера, поскольку валидацию на стороне клиента достаточно просто обойти и она может не остановить злоумышленников. Чтобы лучше понимать потенциальные угрозы, рекомендуем ознакомиться с разделом Безопасность вебсайтов; валидация на стороне сервера выходит за рамки этого модуля, но о ней следует помнить.

Что такое валидация формы?

Зайдите на любой популярный сайт, имеющий форму регистрации. Вы заметите, что при вводе данных в неправильном формате, пользователя сразу уведомляют о наличии проблемы. Вы получите примерно такое сообщение:

  • «Обязательное поле» (Вы не можете оставить поле пустым).
  • «Пожалуйста, введите номер телефона в формате xxx-xxxx» (Чтобы данные считались корректными, их необходимо указать в определённом формате).
  • «Пожалуйста, введите корректный email-адрес» (вы ввели данные в неправильном формате).
  • «Длина пароля должна быть от 8 до 30 символов и включать одну заглавную букву, один символ, и одну цифру.» (Требования к формату данных достаточно конкретные).

Это называется валидацией формы. По мере ввода, браузер и/или сервер проверяют данные, чтобы определить, соответствуют ли они требуемому формату. Валидация, выполняемая в браузере, называется валидацией на стороне клиента, а выполняемая на сервере — валидацией на стороне сервера. В этом разделе мы сосредоточимся на валидации, выполняемой на стороне клиента.

Если формат корректен, приложение позволяет отправить данные на сервер и (обычно) сохранить в базу данных; в противном случае выводится сообщение с описанием того, что нужно исправить, позволяя ввести данные снова.

Мы хотим максимально упростить заполнение веб-форм. Тогда почему мы настаиваем валидации данных? На это есть три основные причины:

  • Мы хотим получать правильные данные в правильном формате. Наши приложения не будут работать должным образом, если данные от пользователей хранятся в неправильном формате, некорректны сами по себе или вовсе пропущены.
  • Мы хотим защитить данные пользователей. Принуждение пользователей вводить надёжные пароли облегчает защиту их аккаунтов.
  • Мы хотим защитить себя. Существует множество способов, позволяющих злоумышленникам с помощью незащищённых форм навредить приложению (смотрите Безопасность вебсайтов).

    Предупреждение: Никогда не доверяйте данным, передаваемым на сервер клиентской программой. Даже если ваша форма правильно валидируется и не допустит введение потенциально вредоносных данных на стороне клиента, злоумышленники по-прежнему могут изменить сетевой запрос.

Типы валидации на стороне клиента

Существует два типа валидации на стороне клиента, с которыми вы столкнётесь в Интернете:

  • Встроенная валидация форм использует функционал валидации HTML5, который мы неоднократно обсуждали в этом модуле. HTML5-валидация обычно не требует большого количества JavaScript-кода и демонстрирует лучшую производительность, но не настолько настраиваема, как валидация с помощью JavaScript.
  • JavaScript-валидация кодируется с помощью JavaScript. Она полностью настраиваема, но требует программирования всей логики (или использования библиотеки).

Использование встроенной валидации форм

Одной из самых важных функций элементов форм HTML5 (en-US) является способность валидировать бóльшую часть пользовательских данных без использования JavaScript. Это выполняется с помощью атрибутов валидации у элементов формы. Многие из них мы уже рассмотрели в этом курсе:

  • required: Определяет, что для отправки формы данное поле предварительно должно быть заполнено.
  • minlength и maxlength: Задаёт минимальную и максимальную длину текстовых данных (строк)
  • min и max: Задаёт минимальное и максимальное значение для поля, расчитанного на числовой тип данных
  • type: Определяет тип данных, на который рассчитано поле: число, email-адрес или какой-то другой предустановленный тип
  • pattern: С помощью регулярного выражения, определяет шаблон, которому должны соответствовать вводимые данные.

Если данные, введённые в поле формы, соответствуют правилам перечисленных выше атрибутов, они считаются валидными, если нет — не валидными

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

  • Элемент соответствует CSS-псевдоклассу :valid, позволяющему стилизовать только валидные элементы.
  • Если пользователь пытается отправить данные, браузер отправит форму при условии, что ничто другое (например, JavaScript) не помешает ему это сделать

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

  • Элемент соответствует CSS-псевдоклассу :invalid или, в зависимости от ошибки, другим псевдоклассам (например, :out-of-range), которые позволяют применять определённые стили к элементам, не являющимся валидными.
  • Если пользователь пытается отправить данные, браузер заблокирует форму и выведет сообщение об ошибке.

Примеры встроенной валидации форм

В этом разделе мы протестируем некоторые из атрибутов, которые обсуждали выше.

Простой начальный файл

Давайте начнём с простого примера: поле, позволяющее указать своё предпочтение — банан или вишня. Этот пример включает обычное текстовое поле <input>, связанный с ним элемент <label> и кнопку отправки формы <button>. Исходный код можно найти на GitHub по адресу fruit-start.html, а ниже приведён рабочий пример.

<form>
  <label for="choose">Would you prefer a banana or cherry?</label>
  <input id="choose" name="i_like">
  <button>Submit</button>
</form>
input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}

Для начала скопируйте файл fruit-start.html в новую папку на вашем жёстком диске.

Атрибут required

Самым простым в HTML5-валидации является атрибут required. Добавьте его к элементу, чтобы сделать заполнение обязательным. Элемент с данным атрибутом соответствует CSS-псевдоклассу :required, а если поле ввода пустое, вместо отправки формы отобразится сообщение об ошибке. Пока поле пустое, оно также будет соответствовать CSS-псевдоклассу :invalid.

Добавьте к полю атрибут required, как показано ниже.

<form>
  <label for="choose">Would you prefer a banana or cherry? (required)</label>
  <input id="choose" name="i_like" required>
  <button>Submit</button>
</form>

Обратите внимание на CSS, который включён в файл примера:

input:invalid {
  border: 2px dashed red;
}

input:invalid:required {
  background-image: linear-gradient(to right, pink, lightgreen);
}

input:valid {
  border: 2px solid black;
}

Данный CSS задаёт полю красную пунктирную рамку, когда оно не валидно, а когда валидно — сплошную чёрную. Мы также добавили фоновый градиент для обязательных не валидных полей. Проверьте новое поведение в примере ниже:

Попробуйте отправить форму без введения значения. Обратите внимание, что не валидное поле получает фокус, появляется сообщение об ошибке («Заполните это поле») и блокируется отправка формы.

Наличие атрибута required у любого элемента, который его поддерживает, означает, что элемент соответствует CSS-псевдоклассу :required, независимо от того, имеет он значение или нет. Если элемент <input> не содержит значение, он будет соответствовать псевдоклассу :invalid.

Примечание: Для повышения удобства взаимодействия указывайте пользователям, какие поля являются обязательными. К тому же, этого требует руководство по обеспечению доступности WCAG. Требуйте обязательного ввода только тех данных, которые вам действительно нужны: например, так ли важно знать пол или должность пользователя?

Валидация с помощью регулярного выражения

Ещё одной полезной функцией валидации является атрибут pattern, который в виде значения принимает Регулярное выражение. Регулярное выражение (regex) — это шаблон, который может быть использован для сопоставления набора символов в текстовой строке, поэтому они идеально подходят для валидации формы и используются для множества других целей в JavaScript.

Регулярные выражения достаточно сложны, и мы не будем подробно рассматривать эту тему в данной статье. Ниже приведены несколько примеров, чтобы дать вам представление о том, как они работают.

  • a — Соответствует одному символу a (не b, не aa, и так далее).
  • abc — Соответствует символу a, за которой следует b, за которой следует c.
  • ab?c — Соответствует символу a, за которым опционально может следовать b, за которым следует c. ( ac или abc)
  • ab*c — Соответствует символу a, за которым опционально может следовать любое количество символов b, за которыми следует c. ( ac , abc, abbbbbc, и так далее).
  • a|b — Соответствует символу a или b.
  • abc|xyz — Соответствует в точности abc или в точности xyz (но не abcxyz или a или y, и так далее).

Есть еще много возможностей, которые мы не упомянули. Полный список со множеством примеров можно найти в документации по Регулярным выражениям

Давайте рассмотрим пример. Добавьте в атрибут pattern следующий шаблон:

<form>
  <label for="choose">Would you prefer a banana or a cherry?</label>
  <input id="choose" name="i_like" required pattern="[Bb]anana|[Cc]herry">
  <button>Submit</button>
</form>
input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}

Это даёт нам следующее обновление — опробуйте его:

В этом примере элемент <input> принимает одно из четырёх возможных значений: строку «banana», «Banana», «cherry», или «Cherry». Регулярные выражения чувствительны к регистру, но с помощью шаблона «Aa», вложенного в квадратные скобки, мы сделали поддержку написания слова как с большой, так и с маленькой буквы.

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

Если не пустое значение элемента <input> не соответствует шаблону регулярного выражения, input будет соответствовать псевдоклассу :invalid.

Примечание: Некоторым типам элементов <input> для валидации с помощью регулярного выражения не требуется атрибут pattern. Например, поле с типом email валидирует значение по шаблону одного email-адреса или, если присутствует атрибут multiple (en-US), шаблону списка email-адресов, разделённых запятыми.

Ограничение длины вводимых значений

Можно ограничить максимально допустимое количество символов для текстовых полей <input> или <textarea> (en-US) используя атрибуты minlength (en-US) и maxlength. Поле будет не валидным, если количество символов его содержимого будет меньше minlength (en-US) или больше maxlength.

Зачастую браузеры не позволяют пользователям вводить в текстовое поле значение, длина которого превышает максимально допустимую. Можно существенно повысить удобство использования, если помимо ограничения в атрибуте maxlength добавить доступный индикатор, отображающий текущее и максимально допустимое количество символов, что даст пользователю возможность уместить содержимое в заданные рамки. Хорошим примером является окно написания твита в Twitter. Для реализации такого функционала можно использовать JavaScript, включая решения, использующие maxlength.

Ограничение допустимых значений

В полях, предназначенных для ввода чисел (например, <input type="number">), диапазон допустимых значений можно определить с помощью атрибутов min и max. Если поле содержит значение за пределами данного диапазона, оно будет не валидным.

Давайте рассмотрим другой пример. Создайте новую копию файла fruit-start.html.

Содержимое элемента <body> замените на:

<form>
  <div>
    <label for="choose">Would you prefer a banana or a cherry?</label>
    <input type="text" id="choose" name="i_like" required minlength="6" maxlength="6">
  </div>
  <div>
    <label for="number">How many would you like?</label>
    <input type="number" id="number" name="amount" value="1" min="1" max="10">
  </div>
  <div>
    <button>Submit</button>
  </div>
</form>
  • Здесь мы в поле с типом text атрибутам minlength и maxlength, задали одинаковое значение 6, что соответствует количеству символов в словах banana и cherry.
  • В поле с типом number атрибуту min мы задали значение 1, а атрибуту max значение 10. При вводе чисел за пределами данного диапазона, поле будет становиться не валидным; с помощью стрелок увеличения/уменьшения пользователи не смогут выйти за границы диапазона. Текущее поле не является обязательным для заполнения, поэтому даже после очистки будет оставаться валидным.
input:invalid {
  border: 2px dashed red;
}

input:valid {
  border: 2px solid black;
}

div {
  margin-bottom: 10px;
}

Демонстрационный пример:

Примечание: <input type="number"> (и другие типы, такие как range и date) могут также принимать атрибут step (en-US), который задаёт шаг увеличения или уменьшения значения при использовании кнопок вверх и вниз. В примере выше мы явно не указывали атрибут step, поэтому он получает значение по умолчанию, равное 1. Это значит, что дробные числа, такие как 3.2, будут не валидными.

Полный пример

Ниже представлен полный пример, демонстрирующий использование встроенного функционала валидации. Сначала немного HTML:

<form>
  <p>
    <fieldset>
      <legend>Do you have a driver's license?<abbr title="This field is mandatory" aria-label="required">*</abbr></legend>
      <!-- Так как в группе радио-кнопок, имеющих одинаковое имя, выбранной может быть
          только одна, то и атрибут "required" достаточно задать хотя бы одной кнопке,
          чтобы сделать всю группу обязательной для заполнения -->
      <input type="radio" required name="driver" id="r1" value="yes"><label for="r1">Yes</label>
      <input type="radio" required name="driver" id="r2" value="no"><label for="r2">No</label>
    </fieldset>
  </p>
  <p>
    <label for="n1">How old are you?</label>
    <!-- Атрибут "pattern" может выступать фолбэком для браузеров, которые
        не поддерживают поля ввода c числовым типом данных. Те браузеры,
        которые такие поля поддерживают, будут просто игнорировать его.
        Как раз, ниже атрибут "pattern" выполняет роль фолбека.
     -->
    <input type="number" min="12" max="120" step="1" id="n1" name="age"
           pattern="d+">
  </p>
  <p>
    <label for="t1">What's your favorite fruit?<abbr title="This field is mandatory" aria-label="required">*</abbr></label>
    <input type="text" id="t1" name="fruit" list="l1" required
           pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range">
    <datalist id="l1">
      <option>Banana</option>
      <option>Cherry</option>
      <option>Apple</option>
      <option>Strawberry</option>
      <option>Lemon</option>
      <option>Orange</option>
    </datalist>
  </p>
  <p>
    <label for="t2">What's your e-mail address?</label>
    <input type="email" id="t2" name="email">
  </p>
  <p>
    <label for="t3">Leave a short message</label>
    <textarea id="t3" name="msg" maxlength="140" rows="5"></textarea>
  </p>
  <p>
    <button>Submit</button>
  </p>
</form>

И немного CSS для стилизации HTML:

form {
  font: 1em sans-serif;
  max-width: 320px;
}

p > label {
  display: block;
}

input[type="text"],
input[type="email"],
input[type="number"],
textarea,
fieldset {
  width : 100%;
  border: 1px solid #333;
  box-sizing: border-box;
}

input:invalid {
  box-shadow: 0 0 5px 1px red;
}

input:focus:invalid {
  box-shadow: none;
}

Получим следующее:

В статье Атрибуты валидации (en-US) можно найти полный список атрибутов, которые можно использовать для ограничения допустимых значений ввода и типов полей input, которые их поддерживают.

Валидация форм с помощью JavaScript

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

Constraint Validation API

Большинство браузеров поддерживают Constraint Validation API, который состоит из набора свойств и методов, доступных на DOM-интерфейсах следующих элементов форм:

  • HTMLButtonElement (представляет элемент <button>)
  • HTMLFieldSetElement (представляет элемент <fieldset>)
  • HTMLInputElement (представляет элемент <input>)
  • HTMLOutputElement (представляет элемент <output>)
  • HTMLSelectElement (представляет элемент <select>)
  • HTMLTextAreaElement (представляет элемент <textarea>)

Для перечисленных выше элементов Constraint Validation API делает доступными следующие свойства.

  • validationMessage: Возвращает локализованное сообщение, описывающее ограничения валидации (если таковые имеются), которым не удовлетворяет определённый элемент. Если элемент не участвует в валидации (willValidate установлено в false) или значение элемента удовлетворяет установленным ограничениям (является валидным), будет возвращена пустая строка.
  • validity: Возвращает объект ValidityState, который содержит несколько свойств, описывающих состояние валидности элемента. Подробное описание всех свойств доступности можно найти на странице справочника ValidityState; ниже приведён список наиболее используемых:
    • patternMismatch: Возвращает true, если значение не соответствует шаблону, указанному в атрибуте pattern, и false если соответствует. Если true, элемент соответствует CSS-псевдоклассу :invalid.
    • tooLong: Возвращает true, если значение длиннее максимальной длины, указанной в атрибуте maxlength, и false если оно короче или равно ей. Если true, элемент соответствует CSS-псевдоклассу :invalid.
    • tooShort: Возвращает true, если значение короче минимальной длины, указанной в атрибуте minlength, и false если оно длинее или равно ей. Если true, элемент соответствует CSS-псевдоклассу :invalid.
    • rangeOverflow: Возвращает true, если значение больше указанного в атрибуте max максимума, и false если меньше или равно ему. Если true, элемент соответствует CSS-псевдоклассам :invalid и :out-of-range
    • rangeUnderflow: Возвращает true, если значение меньше указанного в атрибуте min, и false если больше или равно ему. Если true, элемент соответствует CSS-псевдоклассу :invalid и :out-of-range.
    • typeMismatch: Возвращает true, если значение не соответствует требуемому синтаксису (когда для type задано значение email или url), и false если синтаксис корректный. Если true, элемент соответствует CSS-псевдоклассу :invalid.
    • valid: Возвращает true, если элемент соответствует всем ограничениям валидации — следовательно, считается валидным, и false если не соответствует какому-то ограничению. Если true, элемент соответствует CSS-псевдоклассу :valid; иначе :invalid.
    • valueMissing: Возвращает true, если у элемента есть атрибут required, но не введено значенение, иначе возвращает false. Если true, элемент соответствует CSS-псевдоклассу :invalid.
  • willValidate: Возвращает true, если элемент будет участвовать в валидации при отправке формы; иначе возвращает false.

Также для перечисленных выше элементов Constraint Validation API делает доступными следующие методы.

  • checkValidity(): Возвращает true, если значение элемента проходит валидацию, иначе возвращает false. Если элемент не валиден, данный метод также запускает на нём событие invalid.
  • setCustomValidity(message): Позволяет добавить в элемент кастомное сообщение об ошибке; при этом элемент будет считаться не валидным и отобразится указанная ошибка. Это позволяет использовать JavaScript-код, чтобы представить ошибку валидации иначе, чем это предусмотрено стандартными средствами валидации HTML5. При сообщении об ошибке данное кастомное сообщение показывается пользователю.

Реализация кастомного сообщения об ошибке

Как вы видели в примерах HTML5-валидации выше, каждый раз, когда пользователь пытается отправить не валидную форму, браузер отображает сообщение об ошибке. Способ отображения сообщения зависит от браузера.

У этих автоматических сообщений есть два недостатка:

  • Не существует стандартного способа их стилизации с помощью CSS.
  • Они зависят от локали браузера, из-за чего страница может быть на одном языке, а сообщение об ошибке — на другом, как показано на следующем скриншоте браузера Firefox.

Пример сообщения об ошибке на англоязычной странице в браузере Firefox с настроенным французским языком

Настройка таких сообщений об ошибках является одной из наиболее распространённых причин использования Constraint Validation API. Давайте рассмотрим простой пример, как это делается.

Начнём с простого HTML (Не стесняйтесь поместить это в пустой HTML-файл. Вы можете взять за основу свежую копию fruit-start.html, если хотите):

<form>
  <label for="mail">I would like you to provide me with an e-mail address:</label>
  <input type="email" id="mail" name="mail">
  <button>Submit</button>
</form>

Добавьте на страницу следующий JavaScript:

const email = document.getElementById("mail");

email.addEventListener("input", function (event) {
  if (email.validity.typeMismatch) {
    email.setCustomValidity("I am expecting an e-mail address!");
  } else {
    email.setCustomValidity("");
  }
});

Здесь мы сохраняем ссылку на поле email, а затем добавляем к нему обработчик события, который запускает код обработчика каждый раз, когда в поле меняется значение.

В коде обработчика мы проверяем, возвращает ли свойство поля email validity.typeMismatch значение true, что значит, что содержащееся значение не соответствует шаблону корректного email-адреса. Если возвращается true, мы вызываем метод setCustomValidity() (en-US) с кастомным сообщением. Это делает поле не валидным, поэтому попытка отправить форму приводит к ошибке и отображается кастомное сообщение об ошибке.

Если свойство validity.typeMismatch возвращает false, мы вызываем метод setCustomValidity() с пустой строкой. Это делает поле валидным, поэтому форма может быть успешно отправлена.

Попробовать пример можно ниже:

Более подробный пример

Теперь, когда мы разобрали простой пример, давайте посмотрим, как можно использовать данный API для создания более сложной валидацию.

Во-первых, HTML. Опять же, не стесняйтесь писать его вместе с нами:

<form novalidate>
  <p>
    <label for="mail">
      <span>Please enter an email address:</span>
      <input type="email" id="mail" name="mail" required minlength="8">
      <span class="error" aria-live="polite"></span>
    </label>
  </p>
  <button>Submit</button>
</form>

Эта простая форма использует атрибут novalidate, который отключает автоматическую валидацию браузером; это позволяет нашему скрипту взять управление валидацией на себя. Однако, это не отменяет поддержку Constraint Validation API или псевдоклассов, таких как :valid или ему подобных. Это значит, что хотя браузер автоматически и не проверяет валидность формы перед отправкой данных, вы можете сделать это самостоятельно и соответствующим образом стилизовать форму.

Объектом валидации является обязательный для заполнения <input type="email">, длина которого не должна быть меньше 8 символов. Давайте напишем код, проверяющий эти критерии, и покажем кастомное сообщение об ошибке в случае несоблюдения какого-то из них.

Мы хотим показывать сообщение об ошибке внутри элемента <span>. Данному элементу задан атрибут aria-live, чтобы гарантировать, что наше кастомное сообщение об ошибке будет доступно всем, включая пользователей скринридеров.

Примечание: Ключевым моментом здесь является то, что добавление к форме атрибута novalidate отключает отображение встроенных сообщений об ошибке и позволяет вместо этого добавлять в DOM кастомные сообщения.

Перейдём к базовому CSS, чтобы немного улучшить внешний вид формы и обеспечить визуальную обратную связь при введении не валидных данных:

body {
  font: 1em sans-serif;
  width: 200px;
  padding: 0;
  margin : 0 auto;
}

p * {
  display: block;
}

input[type=email]{
  -webkit-appearance: none;
  appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  box-sizing: border-box;
}

/* Это стили для не валидных полей */
input:invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus:invalid {
  outline: none;
}

/* Это стили для кастомных сообщений об ошибке */
.error {
  width  : 100%;
  padding: 0;

  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;

  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}

Теперь давайте рассмотрим JavaScript, который реализует кастомную валидацию.

// Существуют разные способы получить DOM-узел; здесь мы определяем саму форму и
// поле ввода email и элемент span, в который поместим сообщение об ошибке
const form  = document.getElementsByTagName('form')[0];

const email = document.getElementById('mail');
const emailError = document.querySelector('#mail + span.error');

email.addEventListener('input', function (event) {
  // Каждый раз, когда пользователь что-то вводит,
  // мы проверяем, являются ли поля формы валидными

  if (email.validity.valid) {
    // Если на момент валидации какое-то сообщение об ошибке уже отображается,
    // если поле валидно, удаляем сообщение
    emailError.textContent = ''; // Сбросить содержимое сообщения
    emailError.className = 'error'; // Сбросить визуальное состояние сообщения
  } else {
    // Если поле не валидно, показываем правильную ошибку
    showError();
  }
});

form.addEventListener('submit', function (event) {
  // Если поле email валдно, позволяем форме отправляться

  if(!email.validity.valid) {
    // Если поле email не валидно, отображаем соответствующее сообщение об ошибке
    showError();
    // Затем предотвращаем стандартное событие отправки формы
    event.preventDefault();
  }
});

function showError() {
  if(email.validity.valueMissing) {
    // Если поле пустое,
    // отображаем следующее сообщение об ошибке
    emailError.textContent = 'You need to enter an e-mail address.';
  } else if(email.validity.typeMismatch) {
    // Если поле содержит не email-адрес,
    // отображаем следующее сообщение об ошибке
    emailError.textContent = 'Entered value needs to be an e-mail address.';
  } else if(email.validity.tooShort) {
    // Если содержимое слишком короткое,
    // отображаем следующее сообщение об ошибке
    emailError.textContent = `Email should be at least ${ email.minLength } characters; you entered ${ email.value.length }.`;
  }

  // Задаём соответствующую стилизацию
  emailError.className = 'error active';
}

Комментарии объясняют логику хорошо, но кратко:

  • При каждом изменении значения поля, мы производим его валидацию. Если данные валидны, удаляем ранее отображаемые сообщения об ошибках. Если данные не валдны, запускаем showError(), чтобы показать соответствующую ошибку.
  • При каждой попытке отправить форму, мы снова производим валидацию. Если данные валидны, позволяем отправку формы. Если данные не валидны, запускам showError(), чтобы показать соответствующее сообщение об ошибке, а также предотвращаем отправку формы с помощью preventDefault().
  • Функция showError() использует различные свойства объекта validity поля ввода, чтобы определить тип ошибки и отобразить соответсвущее сообщение.

Рабочий пример:

Constraint Validation API явяется мощным инструментом валидации форм, позволяющим получить контроль над пользовательским интерфейсом, существенно превосходящий возможности HTML и CSS.

Проверка форм без встроенного API

В некоторых случаях, например, при необходимости поддержки устаревших браузеров или кастомных элементов формы, вы не сможете или не захотите использовать Constraint Validation API. Вы по-прежнему сможете использовать JavaScript для валидации форм, но для этого всё нужно будет писать самостоятельно.

Для создания своего валидатора формы, задайте себе несколько вопросов:

Какую тип валидации я должен выполнить?

Вам нужно определить, как данные будут валидироваться: с помощью строковых операций, преобразования типов, регулярных выражений и так далее. Решать вам.

Что мне нужно делать, если форма не проходит валидацию?

Это явно вопрос пользовательского интерфейса. Вы должны решить, как в этом случае будет себя вести форма. Будет ли она в любом случае отправлять данные? Нужно ли выделять поля, содержащие ошибки? Нужно ли отображать сообщения об ошибках?

Как я могу помочь пользователю исправить не валидные данные?

Чтобы снизить степень разочарования пользователя, очень важно предоставить как можно больше полезной информации, чтобы помочь исправить данные, которые он ввёл неправильно. Нужно предложить правильные варианты, чтобы дать понять, какие данные вы ожидаете от него получить, а также сообщение, чётко описывающее ошибку. Если вы хотите подробнее ознакомиться с требованиями к пользовательскому интрефейсу при валидации форм, предлагаем прочитать следующие статьи:

  • SmashingMagazine: Form-Field Validation: The Errors-Only Approach
  • SmashingMagazine: Web Form Validation: Best Practices and Tutorials
  • WebFX: 10 Tips for Optimizing Web Form Submission Usability
  • A List Apart: Inline Validation in Web Forms

Пример без использования Constraint Validation API

Чтобы проиллюстрировать это дальше приводится упрощённая версия предыдущего примера, которая работает с устаревшими браузерами.

HTML почти тот такой же; мы только удалили функционал валидации HTML5.

<form>
  <p>
    <label for="mail">
        <span>Please enter an email address:</span>
        <input type="text" id="mail" name="mail">
        <span class="error" aria-live="polite"></span>
    </label>
  </p>
  <!-- Для некоторых устаревших браузеров элементу `button` нужно добавлять
       атрибут `type` с явно заданным значением `submit` -->
  <button type="submit">Submit</button>
</form>

CSS также не требует особых изменений; мы только заменили CSS-псевдокласс :invalid на реальный класс и не использовали селектор по атрибутам, так как он не работает в Internet Explorer 6.

body {
  font: 1em sans-serif;
  width: 200px;
  padding: 0;
  margin : 0 auto;
}

form {
  max-width: 200px;
}

p * {
  display: block;
}

input.mail {
  -webkit-appearance: none;

  width: 100%;
  border: 1px solid #333;
  margin: 0;

  font-family: inherit;
  font-size: 90%;

  box-sizing: border-box;
}

/* Стилизация не валидных полей */
input.invalid{
  border-color: #900;
  background-color: #FDD;
}

input:focus.invalid {
  outline: none;
}

/* Стилизация сообщений об ошибках */
.error {
  width  : 100%;
  padding: 0;

  font-size: 80%;
  color: white;
  background-color: #900;
  border-radius: 0 0 5px 5px;
  box-sizing: border-box;
}

.error.active {
  padding: 0.3em;
}

Существенно изменился только JavaScript-код, который теперь должен выполнять гораздо больше работы.

// Устаревшие браузеры поддерживают несколько способов получения DOM-узла
const form  = document.getElementsByTagName('form')[0];
const email = document.getElementById('mail');

// Ниже приведён способ получения узла следующего родственного DOM-элемента
// Он опасен, потому что можно создать бесконечный цикл.
// В современных браузерах лучше использовать `element.nextElementSibling`
let error = email;
while ((error = error.nextSibling).nodeType != 1);

// Согласно спецификации HTML5
const emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$/;

// Многие устаревшие браузеры не поддерживают метод `addEventListener`
// Есть простой способ заменить его; и далеко не единственный
function addEvent(element, event, callback) {
  let previousEventCallBack = element["on"+event];
  element["on"+event] = function (e) {
    let output = callback(e);

    // Колбэк, который возвращает `false`, останавливает цепочку колбэков
    // и прерывает выполнение колбэка события
    if (output === false) return false;

    if (typeof previousEventCallBack === 'function') {
      output = previousEventCallBack(e);
      if(output === false) return false;
    }
  };
}

// Теперь мы можем изменить наши критерии валидации
// Поскольку мы не полагаемся на CSS-псевдокласс, для поля email
// нужно явно задать валидный / не валидный класс
addEvent(window, "load", function () {
  // Проверка, является ли поле пустым (помните, оно не являтеся обязательным)
  // Если поле не пустое, проверяем содержимое на соответствует шаблону email
  const test = email.value.length === 0 || emailRegExp.test(email.value);

  email.className = test ? "valid" : "invalid";
});

// Здесь определяется поведение при вводе пользователем значения поля
addEvent(email, "input", function () {
  const test = email.value.length === 0 || emailRegExp.test(email.value);
  if (test) {
    email.className = "valid";
    error.textContent = "";
    error.className = "error";
  } else {
    email.className = "invalid";
  }
});

// Здесь определяется поведение при попытке отправить данные
addEvent(form, "submit", function () {
  const test = email.value.length === 0 || emailRegExp.test(email.value);

  if (!test) {
    email.className = "invalid";
    error.textContent = "I expect an e-mail, darling!";
    error.className = "error active";

    // Некоторые устаревшие браузеры не поддерживают метод event.preventDefault()
    return false;
  } else {
    email.className = "valid";
    error.textContent = "";
    error.className = "error";
  }
});

Результат выглядит следующим образом:

Как вы можете видеть, сделать собственную валидацию не так уж и сложно. Сложность состоит лишь в том, чтобы сделать его кроссплатформенным и работающим с любой формой, которую можно создать. Для проверки формы доступно множество библиотек, например Validate.js.

Проверьте свои навыки!

Вы дошли до конца этой статьи, но можете ли вы вспомнить самую важную информацию? Вы можете найти дополнительные тесты, чтобы убедиться, что вы сохранили эту информацию, прежде чем двигаться дальше — Test your skills: Form validation (en-US).

Заключение

Для проверки формы на стороне клиента иногда требуется JavaScript, если вы хотите настроить стилизацию и сообщения об ошибках, но это всегда требует от вас внимательного отношения к пользователю. Всегда помните о необходимости помогать пользователям исправлять данные, которые они вводят. Для этого обязательно нужно:

  • Отображать явные сообщения об ошибках.
  • Снисходительно относиться к формату ввода.
  • Указывать, где именно возникла ошибка. Особенно в больших формах.

После того, как вы убедились, что форма заполнена правильно, ее можно отправлять. Дальше мы рассмотрим отправку данных формы.

  • Назад (en-US)
  • Обзор: Forms
  • Далее

In this module

Продвинутые темы

Нативная валидация форм

От автора: в этой серии статей я буду излагать свои мысли после тщательного изучения современной валидации форм в CSS и JS. Я расскажу про нативные сообщения в HTML-валидации, CSS псевдоклассы :invalid и :valid, а также про Constraint Validation API, которое должно было упростить валидацию форм, но получилось слегка иначе.

В этой статье мы попробуем провести валидацию формы в стиле user-friendly с помощью нативных возможностей HTML, CSS и JS и написания пары небольших скриптов для вытягивания якобы простых строк в Constraint Validation API.

У нас ничего не получится. Мы поймем, что в дизайне были допущены серьезные ошибки, и что не просто так веб-разработчики не используют ни одну из этих техник. Современная валидация форм страдает от следующих проблем:

Между спецификациями HTML, CSS и JS нет четкой связи. Иногда они работают в совершенно разных целях.

Не существует декларативного способа вставки сообщений об ошибках в отдельные поля формы. (есть JS-способ, но он плохо спроектирован)

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Узнать подробнее

Сообщения HTML-валидации невозможно стилизовать, а их отвратительное и непостоянное поведение невозможно изменить. Можно только работать с командами show и hide, которые совсем не похожи не отображение и скрытие.

Псевдоклассы CSS – отличная штука, но когда вы начинаете их использовать, все становится не так гладко. Также все способы вставки сообщений об ошибках на псевдоклассах довольно сложные.

Эти проблемы кажутся еще более странными, когда узнаешь, что валидация форм буквально самый старый трюк в JS: когда JS был представлен в Netscape 2, он только и умел делать валидацию форм. У нас было 20 лет, чтобы все исправить, но все осталось как есть.

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

И прежде чем мы начнем еще кое-что: всегда помимо клиентской проверки делайте валидацию не сервере. Если скрипты поломаются, а фолбека под рукой не будет, может случиться что-то очень нехорошее.

И еще кое-что. Огромное спасибо Stéphanie Walter и Geoffrey Crofte за их крайне полезные комментарии к черновику этой статьи.

UI валидации полей формы

Прежде чем окунуться с головой в API и псевдоклассы, мы должны понять, чего хотим добиться. В теории все просто: мы хотим предложить пользователю хороший UX, т.е. понятные и короткие сообщения об ошибках в правильное время в правильном месте.

onsubmit, т.е. когда пользователь пытается отправить форму;

onblur, т.е. когда пользователь переходит на другое поле формы;

onkeypress, т.е. когда пользователь меняет значение поля формы (это может происходить по 10 или 12 раз, прежде чем пользователь перейдет к следующему полю).

Какой сценарий лучше? Christian Holst подробно рассматривает UI и customer experience валидации форм. Его главные советы заключается в том, что сообщения об ошибках необходимо показывать рядом с полями, в которых они возникают. Сообщения необходимо показывать сразу, как только пользователь заполнил поля. Другими словами, лучше всего по событию onblur.

Luke Wroblewski соглашается с такими утверждениями и добавляет замечание, что пользователям лучше постоянно показывать сообщения, а не так, чтобы они со временем пропадали. (Угадайте, как все браузеры показывают сообщения за исключением Firefox на Android?) Это же относится и к сообщениям о положительной проверке.

(Luke также протестировал четвертый вариант: focus + keypress. Сообщения показываются, когда пользователь вводит текст в поле формы. Его тесты убедительно показали, что это плохая идея)

Adrian Roselli также говорит: сообщения об ошибках следует показывать над полем формы, а не снизу, так как на маленьких экранах мобильных устройств сообщения под полем могут закрываться экранной клавиатурой или другими UI-элементами.

Есть и контраргумент – пользователи привыкли к тому, что сообщения об ошибках показываются рядом с полем или под ним. Ширины экрана мобильного устройства может не хватить для показа сообщения рядом с полем, поэтому такое расположение крайне нежелательно. Если разместить сообщение снизу, такой проблемы не возникнет.

Что лучше, решайте сами. Но я замечу, что почти все браузеры размещают сообщения об ошибках под полем формы, хотя некоторые мобильные браузеры нарушают это правило.

С размещением сообщения об ошибке не все так ясно, но появляться оно должно по событию onblur, т.е. когда пользователь дает понять, что он заполнил поле и переходит на следующее. Также должен быть легкий способ добавления своих сообщений об ошибке к отдельным полям формы.

CSS, API и браузеры не выполняют эти простые правила. Невозможно добавить сообщения об ошибках простым декларативным методом. Constraint Validation API основано на событии onsubmit, а CSS :invalid и :valid на событии onkeypress.

Валидация форм на чистом CSS

Валидация форм на чистом CSS работает на псевдоклассах :invalid и :valid. (Есть и другие псевдоклассы типа out-of-range, но мы опустим их, так как их принцип работы точно такой же, и это более частные случаи invalid)

Поиграться с псевдоклассами можете в первом примере на тестовой странице. Валидация перезапускается при каждом нажатии клавиш. Не самый красивый способ и, возможно, запутанный. Пользователю не нужно знать о состоянии введенного значения на каждом этапе: нужно одно четкое сообщение, когда поле будет заполнено целиком. (Пользователь пока не видит сообщения об ошибке. Чуть ниже мы к этому вернемся)

Вне фокуса

К счастью, перейти на onblur довольно легко. Потребуется задействовать немного сложный селектор (спасибо, Krijn, за этот трюк):

input:invalid:not(:focus)

Смотрите второй пример на тестовой странице. Теперь невалидные и валидные стили видны только, когда поле вне фокуса, т.е. когда пользователь не вводит в него значение. Уже лучше.

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Узнать подробнее

Сообщения об ошибках на чистом CSS

Такие сообщения решают проблему тайминга, но не решают проблему показа самих сообщений. Теоретически решение будет следующим:

input:invalid:not(:focus):before {

content: attr(dataerrormessage);

}

Показывайте контент невалидного атрибута data-error-message перед полем, если пользователь не печатает текст. Звучит хорошо, правда?

Увы, увы, но :before и :after нельзя использовать на замененных элементах типа input.

Это нужно исправить. :before и :after не заточены под замененные элементы, однако в Chrome и Safari они работают с диапазонами, чекбоксами и радиокнопками. В Chrome Safari/iOS, но не в Safari/Mac они также работают с полями типа date. (Почему именно эти типы? Я не знаю. Возможно, парочка разработчиков браузеров были пьяны)

Это не работает. Нужно передвинуть сообщение об ошибке за пределы поля. Что-то типа:

span.errorMessage {

display: none;

}

input:invalid:not(:focus) + span.errorMessage {

display: block;

}

Это работает, но сложность объявления сообщений сбивает с толку. Вы можете сказать, что сообщения не относятся к CSS, но, как мы позже увидим, их нет и в HTML и JS. Это фундаментальная проблема спецификация на данный момент.

Проблема с required

Нам может показаться, что мы прошли достойный путь, и валидация на чистом CSS у нас в руках, но все разваливается, когда необходимо учесть обязательные поля формы. Пустые обязательные поля считаются невалидными.

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

Можете использовать решение Krijn (добавить текст в плейсхолдер в виде одного пробела!), но тогда придется использовать псевдокласс :placeholder-shown.

:not(:focus):not(:placeholdershown):invalid

Вам еще не смешно? Мы же не просим какой-то скрытый функционал, который нужен только для пары полей. Нам лишь нужно подождать сигнала от пользователя, что он готов, прежде чем проверять поле на валидность.

Другими словами, валидация на чистом CSS вам не подойдет, если у вас есть обязательные поля. А так как почти каждая форма имеет минимум пару обязательных полей, CSS валидация – не вариант.

:user-invalid и :user-error

Эта проблема признана всеми, кто работает с CSS. Решение – сделать в форме псевдоклассы :user-invalid (W3C) или :user-error (WHATWG). Оба значат «поле невалидно после взаимодействия с пользователем». Эти псевдоклассы решили бы большую часть описанных выше проблем.

В настоящее время оба псевдокласса не поддерживаются, но в будущем они будут реализованы и продвинут валидацию в CSS еще дальше. Тем не менее, проблема нативной и простой системы сообщений об ошибках никуда не девается.

:valid и :invalid на других элементах

Мало кто знает, но :invalid и :valid работают не только на input. Эти псевдоклассы можно использовать на fieldset и form. :invalid срабатывает, если fieldset или form содержит минимум одно невалидное поле.

Еще круче, fieldset поддерживает :before и :after. Эта техника может пригодиться:

fieldset:invalid {

bordercolor: red;

}

fieldset:invalid:before {

content: attr(dataerrormessage);

}

К сожалению, она не поддерживается в Edge и парочке старых мобильных браузеров.

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

Так завершается часть 1. В следующей статье (скоро) мы поговорим о парочке опций HTML и JS API.

Автор: Peter-Paul Koch

Источник: //medium.com/

Редакция: Команда webformyself.

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Узнать подробнее

PSD to HTML

Практика верстки сайта на CSS Grid с нуля

Смотреть

Отображение сообщений об ошибках при заполнении полей формы

Если данные формы перед отправкой на сервер проверяются на правильность,
то непременно возникает необходимость показывать пользователю сообщения об ошибках.

Функция alert в этом случае неудобна, особенно если в форме допущены сразу
несколько ошибок (представьте себе, что пользователю будут показаны сразу несколько алертов подряд,
он может потом просто забыть, что ему нужно исправить).

Идеальным выходом в этой ситуации может послужить выведение сообщений об ошибках прямо в форме,
возле поля, вызвавшего ошибку.

Если установить относительное позиционирование для тегов label,
то в этом случае, установив для класса errorMsg абсолютное позиционирование,
можно помещать сообщение в любом месте относительно поля.

В функции showError сразу создается элемент span с ошибкой errorMessage,
которому присваивается имя класса errorMsg для установки стиля сообщений об ошибках.

Затем добавляется этот элемент внутрь тега label.
field — поле, возле которого нужно вывести сообщение об ошибке;
errorMessage — сообщение об ошибке.

Нажмите кнопку «Отправить», чтобы увидеть результат.

Исходный код этого примера:
<style>
    form p {
        margin-bottom: 20px;
    }
    form label {
        position: relative;
    }
    .errorMsg {
        position: absolute;
        left: 0;
        top: 40px;
        width: 200px;
        color: red;
        font-size: 12px;
        font-style: italic;
    }
</style>
<form id="frm" action="" onsubmit="return checkForm()">
    <p>
        <label for="firstName">Имя:</label><br>
        <input id="firstName" name="firstName" value="">
    </p>
    <p>
        <label for="lastName">Фамилия:</label><br>
        <input id="lastName" name="lastName" value="">
    </p>
    <p>
        <input type="submit" name="go" value="Отправить">
    </p>
</form>

<script>
//Функция проверки полей формы
function checkForm() {
  showError('firstName', 'Неверно заполнено поле!');
  return false;
}
// функция сообщения об ошибке
function showError(field, errorMessage) {
	var errorSpan = document.createElement("span");
	var errorMessage = document.createTextNode(errorMessage);

	errorSpan.appendChild(errorMessage);
	errorSpan.className = "errorMsg";

	var fieldLabel = document.getElementById(field).previousSibling;
	while (fieldLabel.nodeName.toLowerCase() != "label") {
		fieldLabel = fieldLabel.previousSibling;
	}
	fieldLabel.appendChild(errorSpan);
}
</script>

This tutorial will show you how to create and customize error messaging for various form elements. In this tutorial, we will customize everything from a basic error message to input field errors and tooltips. The best part? We will be using only CSS for customizations – that means no images or javascript required!

HTML

Below is the markup for the form elements we will be creating error messaging for. This is all of the HTML used throughout this tutorial. Copy and paste this code into your working file:

<!-- Basic Error Message -->
<div class="error-message">
  <span class="error-text">Checkout could not be completed. Please check your login information and try again.</span>
</div>
 
<!-- Input Field Error -->
<div class="input-group error">
  <label>Password *</label> 
  <input type="text">
  <div class="error-message">Password is a required field.</div>
</div>
 
<!-- Input Field Error with Tooltip -->
<div class="input-group error">
  <label>Quantity</label> 
  <input type="text">
  <div class="error-tip">Enter a quantity</div>
</div>

CSS

Now onto my personal favorite: the CSS. We will keep the basic functionality of the form elements but completely customize their appearance. In the end, they will stand on their own as custom design elements that thoughtfully guide the user through the form process, making it as straightforward and painless as possible.

Basic Error Message

Let’s start with a basic error message. We are going to customize the HTML above to look like this:

This is what we start out with, by default, after adding the HTML:

basic error message default

Customizing a basic error message is really simple. All we have to do is give our text a colored background and a couple font styles using CSS. To style the error message background, add the following styles to your CSS stylesheet:

.error-message {
  background-color: #fce4e4;
  border: 1px solid #fcc2c3;
  float: left;
  padding: 20px 30px;
}

Now let’s style the text itself by adding the following font styles:

.error-text {
  color: #cc0033;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: bold;
  line-height: 20px;
  text-shadow: 1px 1px rgba(250,250,250,.3);
}

That’s it! Keep reading to learn how to style input field and tooltip errors.

Input Field Error

Now that we have our basic error message styled, let’s work on input field errors. This is what the final product will look like:

error field input

And this is what we start out with by default:

error field input default

First, we want to override the browser’s default styles. Add the following CSS to give your input field a custom look:

/* Basic Input Styling */
.input-group {
  color: #333;
  float: left;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 13px;
  line-height: 20px;
  margin: 0 20px 10px;
  width: 200px;
}

label {
  display: block;
  margin-bottom: 2px;
}

input[type=text] {
  background: #fff;
  border: 1px solid #999;
  float: left;
  font-size: 13px;
  height: 33px;
  margin: 0;
  padding: 0 0 0 15px;
  width: 100%;
}

Next, we need to add the styling for the error message that displays when a user does not correctly fill out an input field (i.e. the “This is a required field” message):

.error-message {
  color: #cc0033;
  display: inline-block;
  font-size: 12px;
  line-height: 15px;
  margin: 5px 0 0;
}

Lastly, add the error-specific styling for the input field elements:

.error label {
  color: #cc0033;
}

.error input[type=text] {
  background-color: #fce4e4;
  border: 1px solid #cc0033;
  outline: none;
}

Input Field Error with Tooltip

The last element we’re tackling is the tooltip. It is slightly more complicated than the others but well worth the effort. We will also be utilizing Sass nesting to better organize our code, and because we are only using SCSS it is 100% editable and scalable.

Once we are done, the tooltip will look like this:

error field input tooltip

And by default, this is what we start with after adding the HTML:

error field input tooltip default

First, we override the browser’s default styles with our own custom styling:

/* Basic Input Styling */
.input-group {
  color: #333;
  float: left;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 13px;
  line-height: 20px;
  margin-bottom: 10px;
  width: 100%;
}

label {
  display: block;
  margin-bottom: 5px;
}

input[type=text] {
  background: #fff;
  border: 1px solid #ccc;
  color: #333;
  float: left;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 13px;
  height: 33px;
  line-height: 20px;
  margin: 0;
  padding: 0 0 0 15px;
  width: 45px;
}

Just like our previous example, we need to add the tooltip error message styling that displays when a form error occurs. Note: we are using Sass here to nest the tooltip’s left arrow properties. This comes in handy when trying to keep track of which values are assigned to the tooltip specifically:

/* Tooltip Styling */
.error-tip {
  background-color: #fce4e4;
  border: 1px solid #fcc2c3;
  border-radius: 7px;
  -moz-border-radius: 7px;
  -webkit-border-radius: 7px;
  display: inline;
  color: #cc0033;
  float: left;
  font-weight: bold;
  line-height: 24px;
  position: relative;
  padding: 7px 11px 4px;
  margin-left: 17px;
  // Left Arrow Styling Starts Here
  &:after, &:before {
    content: '';
    border: 7px solid transparent;
    position: absolute;
    top: 11px;
  }
  &:after {
    border-right: 7px solid #fce4e4;
    left: -14px;
  }
  &:before {
    border-right: 7px solid #fcc2c3;
    left: -15px;
  }
} // end .error-tip

Now all that’s left to do is define the input’s error-specific styling. Again, we will nest these styles under an “error” class selector to make classification and future changes easier:

/* Error Styling */
.error.input-group {
  label {
    color: #cc0033;
    font-weight: bold;
  }
  input {
    border: 2px solid #cc0033;
    line-height: 37px;
    outline: none;
  }
  .status {
    display: none;
  }
  .error-tip {
    display: inline;
  }
} // end .error

And that’s it! All the code you need to customize error messaging for default form elements. To experiment with the final results and copy and paste to your heart’s content (without fear of breaking anything), jump on over to Codepen by selecting any of the tutorial links below.

Codepen/Tutorial Links

All:  codepen.io/seskew/
Basic Error Message:  codepen.io/seskew/pen/akhLx
Input Field Error:  codepen.io/seskew/pen/XKJKNQ
Input Field Error with Tooltip:  codepen.io/seskew/pen/NrPNBp

crautcher Проблема с обработкой ошибочного заполнения формы. На данный момент имеется форма добавления объявления. Ситуация такая , если пользователь ошибся или не заполнил одну графу , а остальные правильно , открывается страница с сообщением о неверно заполненной графе и предлагается вернуться обратно и заполнить ее.

ОДНАКО , вот и наступает проблема. Все те поля ,которые были правильно заполнены оказываются пустыми. И приходится по новой заполнять их.
Помогите пожалуйста , кто нибудь((( за спасибо или за пиво)). Нужно применить сессии и чтобы при ошибке в той же форме рядом с «ошибочной» графой выводилось предупреждение об ошибке. Сам пробовал , не получается. Самоучка(((

Добавлено через 2 минуты
crautcher, Спасибо Вам огромное , буду пробовать. Просто никогда не применял сам сессии. Если что-то не получится я еще обращусь к Вам)) Но Надеюсь , что справлюсь. Еще раз , благодарю . Радости не будет предела.

Добавлено через 9 минут

Цитата
Сообщение от crautcher
Посмотреть сообщение

Затем выводи, где нужно $_SESSION[‘LastError’]

Это в форме я так понимаю ? Рядом с «ошибочным» полем ? Можете на одном примере показать ? К примеру графа «имя»

Отображение сообщений об ошибках при заполнении полей формы

Если данные формы перед отправкой на сервер проверяются на правильность,
то непременно возникает необходимость показывать пользователю сообщения об ошибках.

Функция alert в этом случае неудобна, особенно если в форме допущены сразу
несколько ошибок (представьте себе, что пользователю будут показаны сразу несколько алертов подряд,
он может потом просто забыть, что ему нужно исправить).

Идеальным выходом в этой ситуации может послужить выведение сообщений об ошибках прямо в форме,
возле поля, вызвавшего ошибку.

Если установить относительное позиционирование для тегов label,
то в этом случае, установив для класса errorMsg абсолютное позиционирование,
можно помещать сообщение в любом месте относительно поля.

В функции showError сразу создается элемент span с ошибкой errorMessage,
которому присваивается имя класса errorMsg для установки стиля сообщений об ошибках.

Затем добавляется этот элемент внутрь тега label.
field — поле, возле которого нужно вывести сообщение об ошибке;
errorMessage — сообщение об ошибке.

Нажмите кнопку «Отправить», чтобы увидеть результат.

Исходный код этого примера:
<style>
    form p {
        margin-bottom: 20px;
    }
    form label {
        position: relative;
    }
    .errorMsg {
        position: absolute;
        left: 0;
        top: 40px;
        width: 200px;
        color: red;
        font-size: 12px;
        font-style: italic;
    }
</style>
<form id="frm" action="" onsubmit="return checkForm()">
    <p>
        <label for="firstName">Имя:</label><br>
        <input id="firstName" name="firstName" value="">
    </p>
    <p>
        <label for="lastName">Фамилия:</label><br>
        <input id="lastName" name="lastName" value="">
    </p>
    <p>
        <input type="submit" name="go" value="Отправить">
    </p>
</form>

<script>
//Функция проверки полей формы
function checkForm() {
  showError('firstName', 'Неверно заполнено поле!');
  return false;
}
// функция сообщения об ошибке
function showError(field, errorMessage) {
	var errorSpan = document.createElement("span");
	var errorMessage = document.createTextNode(errorMessage);

	errorSpan.appendChild(errorMessage);
	errorSpan.className = "errorMsg";

	var fieldLabel = document.getElementById(field).previousSibling;
	while (fieldLabel.nodeName.toLowerCase() != "label") {
		fieldLabel = fieldLabel.previousSibling;
	}
	fieldLabel.appendChild(errorSpan);
}
</script>

Понравилась статья? Поделить с друзьями:

Не пропустите эти материалы по теме:

  • Яндекс еда ошибка привязки карты
  • Вывод ошибок формы django
  • Вывод ошибок вордпресс
  • Вывод ошибок валидации laravel
  • Вывод ошибок php лог

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии