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.