Prawidłowa odpowiedź to „pattern”, bo właśnie ten atrybut w HTML5 służy do walidacji zawartości pola tekstowego za pomocą wyrażeń regularnych po stronie przeglądarki. Atrybut pattern przyjmuje jako wartość wyrażenie regularne w składni zbliżonej do tej znanej z JavaScript (ECMAScript). Przeglądarka sprawdza, czy wpisany tekst pasuje do wzorca i jeśli nie, to nie pozwoli wysłać formularza, o ile pole ma ustawiony atrybut required lub użytkownik wywoła standardową walidację formularza.
Przykład praktyczny: jeśli chcemy wymusić, żeby użytkownik wpisał dokładnie 3 cyfry, możemy napisać:
<input type="text" name="kod" pattern="\d{3}" required>
Wtedy poprawne będą wartości typu „123”, a „12a” czy „1234” zostaną odrzucone. Dla adresu e‑mail (prostej wersji) można użyć np.:
<input type="text" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}">
W praktyce i tak często łączy się walidację HTML5 (pattern) z walidacją po stronie serwera, bo walidacja w przeglądarce jest tylko pierwszą linią obrony i użytkownik może ją wyłączyć.
Z mojego doświadczenia warto pamiętać, że pattern działa tylko na tekst (input type="text", „search”, „tel”, „email”, „url” itd.) i jest walidowany dopiero w momencie wysyłki formularza lub wywołania metody checkValidity() w JavaScript. Dobrą praktyką jest też dodanie atrybutu title z opisem formatu danych, np. title="Wpisz 3 cyfry", żeby użytkownik zrozumiał, czemu formularz go nie przepuszcza. W projektach komercyjnych pattern bardzo pomaga szybko ogarnąć proste reguły, jak kody pocztowe, numery indeksów, proste loginy itp., bez konieczności pisania dodatkowego skryptu JS.
W tym pytaniu chodzi o konkretny mechanizm walidacji wbudowany w HTML5, a nie o ogólne właściwości pól formularza. Walidacja za pomocą wyrażeń regularnych jest w standardzie przypisana do jednego, ściśle określonego atrybutu – właśnie pattern. Inne atrybuty z listy pełnią zupełnie inne role i ich mylenie to dość typowy błąd przy nauce formularzy.
Atrybut step jest używany do określania „kroku” dla wartości liczbowych lub dat, np. w input type="number" czy type="date". Pozwala zdefiniować, o ile ma się zwiększać lub zmniejszać wartość przy użyciu strzałek lub walidować, czy liczba jest wielokrotnością danego kroku. Przykład: step="0.5" przy liczbie zmiennoprzecinkowej. Nie ma on żadnego związku z wyrażeniami regularnymi ani ze zwykłym tekstem w type="text".
value z kolei to po prostu wartość pola – początkowa (domyślna) lub aktualna, odczytywana i modyfikowana przez JavaScript lub wysyłana w formularzu. Ustawienie value nie waliduje danych, tylko je definiuje. Można wprawdzie ręcznie sprawdzać value w JS i dopasowywać je do regexa, ale to już logika skryptu, a nie działanie samego atrybutu w HTML. To pewnie częsty skrót myślowy: „wartość pola” vs. „sprawdzenie wartości pola”, ale przeglądarka sama z siebie nie waliduje na podstawie samego value.
readonly natomiast blokuje możliwość edycji pola przez użytkownika, ale nadal wysyła jego wartość z formularzem. To przydatne, gdy chcemy coś pokazać, ale nie pozwolić na zmianę, np. wygenerowany identyfikator. Nie ma tu żadnej analizy treści, żadnego dopasowywania do wzorca – po prostu pole jest nieedytowalne. Czasem ktoś myśli: „skoro nie można tego zmienić, to jakby jest bezpieczne i zwalidowane”, ale to już bardziej kwestia logiki aplikacji, a nie mechanizmu walidacji.
Mechanizm HTML5 do regexów jest jeden: pattern. Warto go łączyć z innymi atrybutami walidacyjnymi, jak required, minlength, maxlength, type, ale to właśnie pattern odpowiada za dopasowanie tekstu do określonego wzorca. Wszystko inne z tej listy pełni pomocnicze lub zupełnie inne funkcje i nie zastępuje typowej walidacji opartej o wyrażenia regularne.