Skip to content

Wszystko o WordPressie, tworzeniu stron — i nie tylko

📱 Maska telefonu dla input w JavaScript: 4 sposoby z kodem

📱 Maska telefonu dla input w JavaScript: 4 sposoby z kodem

Użytkownik wpisuje telefon jakkolwiek: ktoś od ósemki, ktoś od +7, ktoś razem, ktoś ze spacjami po każdej parze cyfr. Do bazy trafia mieszanina. Menedżer traci czas na obdzwonkę, a połowa numerów jest błędna. Znajomy obrazek dla każdego, kto umieszczał formularz kontaktowy na stronie.

Maska wprowadzania zamyka problem całkowicie: użytkownik fizycznie nie może wprowadzić numeru w nieprawidłowym formacie. Wpisuje cyfry, one same podstawiają się w odpowiednie miejsca, nawiasy i myślniki pojawiają się automatycznie. Żadnych błędów, żadnej irytacji.

Poniżej cztery sposoby dodania maski telefonu do inputa: od natywnego HTML5 bez ani jednej linii JavaScriptu po gotową bibliotekę z flagami wszystkich krajów. Z kodem, który można skopiować i wkleić do swojego projektu.

💡 Szybki przegląd:

  • Najprostsza maska przez atrybut pattern i type="tel", zero linii JavaScriptu, działa w każdej przeglądarce
  • Potrzebne flagi krajów i format międzynarodowy, proszę użyć intl-tel-input, najpopularniejsze rozwiązanie na GitHubie
  • Potrzebna jedna biblioteka do telefonów, dat, kart i wszelkich innych masek, proszę wziąć IMask.js
  • Chcą Państwo napisać maskę ręcznie i nie ciągnąć zależności, czysty JavaScript poradzi sobie w 30 linijkach

Czym jest maska wprowadzania i dlaczego jest ważniejsza niż walidacja

Maska wprowadzania, czyli input mask, to ciąg-szablon, który kontroluje to, co widzi i może wpisać użytkownik w polu formularza. W przeciwieństwie do walidacji, która sprawdza dane po wysłaniu i pokazuje błąd, maska działa bezpośrednio podczas wprowadzania: nie pozwala wpisać litery tam, gdzie ma być cyfra, i sama rozmieszcza nawiasy, myślniki i spacje.

Różnica jest zasadnicza. Walidacja mówi „popełnił Pan błąd", użytkownik jest już zirytowany i może odejść. Maska prowadzi za rękę: błąd jest po prostu niemożliwy. Dla telefonu jest to krytyczne, ponieważ formatów zapisu są dziesiątki. Tylko rosyjski numer można zapisać jako +7 999 123-45-67, jako 8(999)1234567 lub jako +7(999)123-45-67, a to tylko trzy warianty z niezliczonej liczby. Bez maski każdy użytkownik wymyśla swój format i baza zamienia się w śmietnik.

Sposób 1: HTML5, type="tel" i pattern

Najłatwiejsza droga: obyć się całkowicie bez JavaScriptu. Współczesne przeglądarki obsługują type="tel" oraz atrybut pattern, który sprawdza wprowadzenie za pomocą wyrażenia regularnego podczas wysyłania formularza.

Proszę dodać pole do znaczników. Kod wstawia się do dowolnego szablonu HTML: Contact Form 7, natywnego formularza WordPress lub niestandardowego układu.

1<input
2 type="tel"
3 id="phone"
4 name="phone"
5 pattern="\+7\s?[\(]?\d{3}[\)]?\s?\d{3}[\-]?\d{2}[\-]?\d{2}"
6 placeholder="+7 (999) 123-45-67"
7 title="Введите номер в формате +7 (999) 123-45-67"
8 required
9>

Rozłóżmy na części, co tu się dzieje. type="tel" na urządzeniach mobilnych pokazuje klawiaturę numeryczną zamiast zwykłej, wprowadzanie telefonu od razu jest wygodniejsze. pattern definiuje wyrażenie regularne, które dopuszcza kilka wariantów: ze spacjami i bez, z nawiasami wokół kodu operatora i bez nich. title pokazuje podpowiedź przy najechaniu, a required nie pozwoli wysłać formularza z pustym polem.

Plus podejścia: zero zależności, działa w każdej przeglądarce. Dla prostego landing page’a to wystarczy.

Ale to nie jest prawdziwa maska. Nawiasy i myślniki nie pojawiają się automatycznie, użytkownik musi wpisać je sam. pattern zadziała tylko podczas wysyłania formularza. Jeśli potrzebne jest formatowanie bezpośrednio podczas wprowadzania, proszę przejść do kolejnych sposobów.

Sposób 2: intl-tel-input, format międzynarodowy z flagami krajów

intl-tel-input, najpopularniejsza biblioteka JavaScript do wprowadzania telefonów. Daje pole z rozwijaną listą flag krajów, autoformatowaniem pod narodowy szablon i walidacją numeru. Według stanu na czerwiec 2026 biblioteka ma ponad 7800 gwiazdek na GitHubie, aktualna wersja to 29.

Proszę podłączyć bibliotekę przez npm (npm i intl-tel-input) lub CDN. Kod poniżej jest dla vanilla JavaScript; są też gotowe komponenty dla React, Vue, Angular i Svelte.

1<!-- В <head> страницы -->
2<link
3 rel="stylesheet"
4 href="https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/css/intlTelInput.css"
5>
6<script src="https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/js/intlTelInput.min.js"></script>

Sam input i inicjalizacja, w tym miejscu szablonu, gdzie potrzebne jest pole. Dla motywu WordPress proszę dodać skrypt przez wp_enqueue_script w functions.php, a znaczniki do odpowiedniego szablonu.

1<input type="tel" id="phone">
2
3<script>
4 const input = document.querySelector("#phone");
5 const iti = intlTelInput(input, {
6 initialCountry: "ru",
7 separateDialCode: true,
8 utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/js/utils.js"
9 });
10</script>

initialCountry: "ru" ustawia domyślnie rosyjską flagę. separateDialCode: true wynosi kod kraju poza pole wprowadzania: użytkownik zmienia flagę, kod podstawia się sam. utilsScript doładowuje narzędzia formatowania, bez nich biblioteka działa, ale numery nie są formatowane pod maskę wybranego kraju.

Obiekt, który zwraca intlTelInput(), daje kilka przydatnych metod. iti.getNumber() oddaje numer w międzynarodowym formacie E.164, iti.isValidNumber() sprawdza poprawność, iti.setNumber("9991234567") programowo ustawia wartość. Dla Contact Form 7 potrzebny będzie niestandardowy skrypt: znajdują Państwo pole .wpcf7-tel i wieszają na nim intlTelInput.

Plus: pełnoprawne międzynarodowe rozwiązanie, autoformat, flagi, walidacja, integracje z frameworkami. Minus: biblioteka waży około 40 KB (gzip) i dla prostego landing page’a z jednym polem to za dużo.

Sposób 3: IMask.js, uniwersalna maska bez jQuery

IMask.js, dojrzała biblioteka masek na czystym JavaScripcie: ani jQuery, ani innych zależności. Obsługuje maski dla telefonów, dat, liczb, walut i dynamiczne szablony. Wygodna, gdy na jednej stronie potrzebne są różne typy masek: telefon w formularzu kontaktowym, data w kalendarzu i kwota w kalkulatorze. Aktualna wersja to 7.1.

Proszę zainstalować przez npm (npm i imask) lub podłączyć CDN:

1<script src="https://unpkg.com/imask"></script>

Maska telefonu w trzech linijkach. Kod można umieścić w <script> w stopce lub w osobnym pliku JS motywu.

1const phoneInput = document.getElementById('phone');
2const maskOptions = {
3 mask: '+{7} (000) 000-00-00'
4};
5IMask(phoneInput, maskOptions);

Składnia maski: +{7}, stały prefiks, nieedytowalny przez użytkownika. 0, dowolna cyfra od 0 do 9. Można skomplikować: uczynić kod operatora opcjonalnym lub dynamicznie zmieniać maskę przy zmianie kraju przez parametr dispatch.

IMask zwraca obiekt z dostępem do surowej wartości: maskRef.unmaskedValue odda czyste cyfry 79991234567, dokładnie to, co trzeba zapisać w bazie. Metoda maskRef.value zwróci sformatowany ciąg do wyświetlenia. Klasyczny problem rozwiązany: na backend lecą cyfry, a użytkownik widzi ładny numer.

Plus: jedna biblioteka na wszystkie przypadki, czyste wartości od razu, brak zależności. Minus: dla jednego pola telefonu prościej wziąć intl-tel-input z flagami, IMask rozwija skrzydła na formularzach z trzema do pięciu różnymi typami pól.

Sposób 4: czysty JavaScript, maska własnymi rękami

Jeśli nie chcą Państwo ciągnąć biblioteki dla jednego pola, proszę napisać maskę na czystym JavaScripcie. Kod poniżej obsługuje każde naciśnięcie i automatycznie wstawia nawiasy oraz myślniki w miarę wprowadzania cyfr.

Skrypt umieszcza się w tym samym szablonie, gdzie znajduje się pole wprowadzania, lub podłącza osobnym plikiem. Dla WordPress przez wp_enqueue_script z flagą true (w stopce).

1document.getElementById('phone').addEventListener('input', function (e) {
2 let value = e.target.value.replace(/\D/g, '');
3
4 if (value.length > 11) {
5 value = value.slice(0, 11);
6 }
7
8 let formatted = '+7 (';
9 if (value.length > 1) formatted += value.slice(1, 4);
10 if (value.length > 4) formatted += ') ' + value.slice(4, 7);
11 if (value.length > 7) formatted += '-' + value.slice(7, 9);
12 if (value.length > 9) formatted += '-' + value.slice(9, 11);
13
14 e.target.value = formatted;
15});

Zdarzenie input uruchamia się przy każdej zmianie pola: wklejenie ze schowka, autokorekta, usunięcie. Pierwsza linijka replace(/\D/g, '') wycina wszystko oprócz cyfr: litery i znaki specjalne znikają natychmiast. Następnie skrypt odcina zbędne cyfry (numer rosyjski, 11 znaków z kodem kraju) i składa sformatowany ciąg: kod kraju +7, trzy cyfry kodu operatora w nawiasach, trzy cyfry numeru, dwie, dwie, przez myślniki.

Przed użyciem na rzeczywistej stronie proszę dodać dwa ulepszenia. Pierwsze: podczas usuwania cyfr wewnątrz numeru kursor może przeskakiwać na koniec pola, proszę zapisywać pozycję karetki przez selectionStart i przywracać po formatowaniu. Drugie: dla numerów innych krajów (Białoruś, 12 cyfr, Kazachstan, 11 cyfr z innym kodem) logika się komplikuje i wtedy intl-tel-input jest w pełni uzasadniony.

Plus: 30 linijek, pełna kontrola, ani jednego kilobajta zależności. Minus: maska jest dostosowana do jednego formatu, dla projektów wielokrajowych kod spuchnie.

⁉️🤔 Często zadawane pytania

Czym maska jest lepsza od prostej walidacji?

Walidacja uruchamia się po wysłaniu formularza: użytkownik widzi błąd i wraca poprawiać. Maska działa podczas wprowadzania, nieprawidłowy format jest fizycznie niemożliwy. Mniej irytacji, mniej rezygnacji z wysłania. Dla telefonu jest to krytyczne: błędy w numerze to jedna z najczęstszych przyczyn, dla których użytkownicy porzucają formularz.

Jak zapisywać do bazy czyste cyfry bez nawiasów i myślników?

Wszystkie biblioteki z artykułu oddają surową wartość: w intl-tel-input metoda getNumber() zwraca +79991234567, w IMask.js właściwość unmaskedValue zwraca 79991234567. Przed wysłaniem na serwer proszę brać czystą wartość i ją zapisywać. Sformatowany ciąg proszę pokazywać tylko w interfejsie. W formularzach WordPress proszę dodać ukryte pole <input type="hidden" name="phone_raw"> i wypełniać je przez JavaScript przed wysłaniem.

Czy maska działa na urządzeniach mobilnych?

Tak, wszystkie cztery sposoby działają poprawnie na iOS i Androidzie. type="tel" wywołuje klawiaturę numeryczną, to wygodne. Na starych Androidach (wersje poniżej 6) zdarzenie input może zachowywać się inaczej podczas autokorekty, proszę przetestować na rzeczywistych urządzeniach. intl-tel-input oraz IMask.js są testowane przez deweloperów na przeglądarkach mobilnych i nie stwarzają problemów.

Czy można użyć maski w Contact Form 7?

CF7 generuje pola z klasami .wpcf7-tel. Proszę napisać skrypt, który znajduje to pole po selektorze i wiesza na nim intl-tel-input lub IMask. Podczas wysyłania formularza CF7 bierze wartość bezpośrednio z pola, biblioteka musi zdążyć sformatować ją przed tym. Jeśli używają Państwo czystych wartości, proszę przechwycić zdarzenie wpcf7submit i podmienić dane w ukrytym polu.

Co robić z numerami różnych krajów na jednej stronie?

Proszę wziąć intl-tel-input: użytkownik wybiera flagę, maska automatycznie przełącza się na format wybranego kraju. Do geotargetingu można ustawić initialCountry: "auto", biblioteka określi kraj po IP przez zewnętrzny serwis. Jeśli krajów jest dwa-trzy i budżet na zależności minimalny, proszę napisać dwie maski na czystym JavaScripcie i przełączać je przyciskiem radiowym „Rosja / Kazachstan" nad polem.

Który sposób wybrać do swojego zadania

Wybór sprowadza się do trzech pytań: ile pól na stronie, czy potrzebne są flagi krajów i jak krytyczny jest rozmiar paczki.

Jeden prosty formularz na landing page’u, proszę zacząć od HTML5 pattern. Szybko, bez JavaScriptu, na urządzeniach mobilnych klawiatura przełącza się na numeryczną. Strona przyjmuje numery międzynarodowe, intl-tel-input zamknie kwestię całkowicie: flagi, autoformat, walidacja. Dla sklepu internetowego lub SaaS to standard.

Kilka różnych masek na stronie (telefon, data, kwota, karta), IMask.js da jedno API pod wszystkie pola i nie ciągnie jQuery. Robią Państwo projekt hobbystyczny i chcą pełną kontrolę, 30 linijek na czystym JavaScripcie rozwiąże zadanie dla rosyjskich numerów bez żadnej zależności.

Proszę sprawdzić działanie maski na żywej stronie: proszę wpisać numer z literami, wkleić ze schowka, spróbować usunąć parę cyfr w środku. Pole powinno zachowywać się przewidywalnie w każdym scenariuszu. Który sposób wybrali Państwo dla swojego projektu, proszę napisać w komentarzach.