<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[validity.state вместо if-ов: браузер валидирует формы на лету без костылей]]></title><description><![CDATA[<p dir="auto">Устал от кучи if-else в обработчиках форм? Браузер уже всё проверит сам через <strong>validity.state</strong>. Это объект с флагами ошибок, который обновляется на лету без твоего JS.</p>
<p dir="auto">Забудь ручные проверки на пустоту, длину или паттерны. Атрибуты HTML типа required, minlength, pattern сами генерируют состояния :valid и :invalid. Получаешь чистый код, меньше багов и ноль зависимостей. Разберём, как это работает под капотом и почему мидлы всё равно пишут костыли.</p>
<h2>Как validity.state ловит ошибки без твоего кода</h2>
<p dir="auto">Браузерный движок следит за каждым вводом и обновляет <strong>validity</strong> - объект с булевыми флагами. Там valueMissing для required, tooShort для minlength, patternMismatch для regex. Всё это живое: ввёл букву - флаг переключился.</p>
<p dir="auto">Не нужно oninput с if (value.length &lt; 5). Браузер сам решает, валидно или нет, и вешает :invalid. Плюс checkValidity() вернёт true/false для всей формы. А setCustomValidity() позволит подправить сообщение, если надо кастом.</p>
<p dir="auto">Это решает типичные грабли: утечки в ивент-лупе от лишних слушателей, несинхронные проверки при submit. Вместо 50 строк JS - пара атрибутов в HTML.</p>
<ul>
<li><strong>valueMissing</strong>: true, если required-поле пустое. Браузер блочит submit.</li>
<li><strong>typeMismatch</strong>: для email/number - ввёл буквы в цифры? Флаг взлетел.</li>
<li><strong>tooLong/tooShort</strong>: min/maxlength сами считают символы, без твоих счётчиков.</li>
<li><strong>patternMismatch</strong>: regex в pattern атрибуте - браузер парсит нативно.</li>
<li><strong>valid</strong>: итоговый флаг. true только если все остальные false.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Состояние</th>
<th>Псевдокласс</th>
<th>Пример атрибута</th>
<th>Что блочит</th>
</tr>
</thead>
<tbody>
<tr>
<td>Пустое required</td>
<td>:invalid</td>
<td>required</td>
<td>submit</td>
</tr>
<tr>
<td>Короткий текст</td>
<td>:invalid</td>
<td>minlength=“5”</td>
<td>флаг tooShort</td>
</tr>
<tr>
<td>Не email</td>
<td>:invalid</td>
<td>type=“email”</td>
<td>typeMismatch</td>
</tr>
<tr>
<td>Соответствует</td>
<td>:valid</td>
<td>pattern=“[a-z]+”</td>
<td>submit OK</td>
</tr>
</tbody>
</table>
<h2>Подключаем CSS для состояний: стили без JS</h2>
<p dir="auto">Псевдоклассы :valid и :invalid - это готовый API для стилей. input:invalid { border: 2px solid red; } - и поле краснеет на лету. Добавь :required для фокуса на обязательных.</p>
<p dir="auto">form:invalid блокирует кнопку: button[type=submit] { opacity: 0.5; pointer-events: none; } form:valid button { opacity: 1; pointer-events: auto; }. Никаких MutationObserver или ResizeObserver - чистый CSS.</p>
<p dir="auto">Новички пишут onblur с классами error/success, но это бандл разрастается. Браузер уже знает состояние, зачем дублировать? Минус один слушатель на поле.</p>
<ul>
<li><strong>input:invalid</strong>: красная обводка + shake-анимация для фидбека.</li>
<li><strong>input:valid + input:focus:valid</strong>: зелёный чекмарк через ::after.</li>
<li><strong>form:invalid ~ button</strong>: disable до полной валидности формы.</li>
<li><strong>:out-of-range</strong>: для number min/max - стилизуй отдельно.</li>
</ul>
<pre><code class="language-css">input:invalid {
  border-color: #e74c3c;
  animation: shake 0.5s;
}

input:valid {
  border-color: #27ae60;
}

form:invalid button {
  background: #bdc3c7;
  cursor: not-allowed;
}
</code></pre>
<h2>JS только для тонкой настройки: checkValidity и кастом</h2>
<p dir="auto">Хочешь свои сообщения? validity.validationMessage - стоковое от браузера. Перезапиши через setCustomValidity(‘Минимум 8 символов, бро’). Вызывай в oninput или после debounce.</p>
<p dir="auto">reportValidity() покажет все ошибки диалогом - браузер сам. Для a11y: aria-invalid=“true” на invalid полях, aria-errormessage ссылается на спан с текстом.</p>
<p dir="auto">Без JS форма валидна по дефолту, но мидлы добавляют preventDefault и циклы по полям. validity.state избавляет от этого: if (!form.checkValidity()) return; - и всё.</p>
<ul>
<li>reportValidity(): браузерный popup со всеми ошибками.</li>
<li>setCustomValidity(‘’): сбрасывает кастом, возвращает к нативному.</li>
<li>aria-invalid связывается с validity.valid автоматически в новых браузерах.</li>
<li>CustomError: validity.customError для твоих флагов.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Метод</th>
<th>Что делает</th>
<th>Когда юзать</th>
</tr>
</thead>
<tbody>
<tr>
<td>checkValidity()</td>
<td>true/false для поля/формы</td>
<td>перед submit</td>
</tr>
<tr>
<td>reportValidity()</td>
<td>Показывает ошибки UI</td>
<td>onsubmit fallback</td>
</tr>
<tr>
<td>setCustomValidity()</td>
<td>Кастом текст ошибки</td>
<td>после async чека</td>
</tr>
</tbody>
</table>
<h2>Грабли с validity, которые бьют мидлов</h2>
<p dir="auto">Не все флаги работают везде: customError игнорирует :invalid, пока не вызовешь checkValidity. pattern на type=search может глючить в старых Safari.</p>
<p dir="auto">willValidate false для disabled/readonly - браузер пропускает. rangeUnderflow/Overflow для number - забудь про ручной парсинг Int.</p>
<p dir="auto">Мидлы пишут глобальные валидаторы с Lodash, но validity.state - 0kb, нативно. Тестируй: console.log(input.validity) - увидишь все флаги живьём.</p>
<ul>
<li><strong>rangeOverflow</strong>: &gt; max в number - браузер ловит.</li>
<li><em>stepMismatch</em>: не кратно step в range.</li>
<li><strong>validLength</strong>: false при mismatch min/maxlength.</li>
</ul>
<h2>Нативка рулит, но кастом всё равно нужен</h2>
<p dir="auto">validity.state - идеал для 80% форм: регистрация, поиск, фильтры. JS только для серверного чека или сложных правил типа уникальности email.</p>
<p dir="auto">Осталось async: подожди API, потом setCustomValidity на основе ответа. Или polyfill для IE, но кто его юзает в 2026? Думай о производительности: меньше JS - быстрее ивент-луп.</p>
]]></description><link>https://forum.exlends.com/topic/2029/validity.state-vmesto-if-ov-brauzer-validiruet-formy-na-letu-bez-kostylej</link><generator>RSS for Node</generator><lastBuildDate>Wed, 08 Apr 2026 21:51:17 GMT</lastBuildDate><atom:link href="https://forum.exlends.com/topic/2029.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 08 Apr 2026 09:06:09 GMT</pubDate><ttl>60</ttl></channel></rss>