HTML I CSS · INF.03 · MODUŁ 05
Formularze
Formularz to rozmowa z użytkownikiem. Każde pole powinno mieć etykietę, typ i jasny cel.
Wprowadzenie
Formularz to część strony, w której użytkownik podaje dane: loguje się, wypełnia ankietę albo składa zamówienie. Całość zamykasz w elemencie <form>. Atrybut action wskazuje adres, który otrzyma dane, a method — sposób ich przesłania.
method="get" dopisuje dane do adresu strony, np. /szukaj?q=html. Nadaje się do wyszukiwania i filtrów, ale nie do haseł. method="post" wysyła dane w treści żądania, więc nie widać ich w pasku adresu. Logowanie, rejestracja i zamówienie powinny używać post.
Każde pole powinno mieć etykietę <label> połączoną z polem przez for i id. Dzięki temu kliknięcie w tekst etykiety ustawia kursor w polu, a czytnik ekranu odczytuje nazwę pola. Sam placeholder nie wystarcza, bo znika po wpisaniu tekstu.
Atrybut name jest nazwą pola w danych wysyłanych na serwer. Bez name pole nie trafi do formularza, nawet jeśli użytkownik coś w nim wpisze. Para name=value to najmniejsza jednostka danych formularza.
placeholder to tylko podpowiedź, a nie nazwa pola. Każde pole tekstowe, e-mail, hasło, listę i obszar tekstowy opisz przez <label for="...">.
Najważniejsza własność
Formularz wysyła na serwer pary name=value. Atrybut name mówi, pod jakim kluczem zapisać wartość, a value — co dokładnie zostanie wysłane. Pola bez name są pomijane. To najważniejsza zasada: najpierw nazwij pole, potem myśl o jego wyglądzie.
name="email" + value="ala@example.com" → email=ala%40example.com
method="post" ukrywa dane w adresie, a method="get" dopisuje je po znaku ?.
Rodzaj pola wybierasz atrybutem type. Przeglądarka dobiera do niego klawiaturę, sposób wyświetlania i podstawową walidację. To nie zastępuje sprawdzenia danych na serwerze, ale szybko informuje użytkownika o pomyłce.
| Typ pola | Do czego służy | Na co uważać |
|---|---|---|
text | krótki tekst, np. imię | nie sprawdza formatu |
email | adres e-mail | wymaga znaku @ i domeny |
password | hasło | zasłania znaki, ale nie szyfruje transmisji |
number | liczba, np. liczba sztuk | zakres ustawiasz przez min i max |
date | data | wartość ma format RRRR-MM-DD |
tel | numer telefonu | nie sprawdza formatu — dodaj pattern |
url | adres strony internetowej | oczekuje http:// lub https:// |
search | pole wyszukiwania | semantycznie sygnalizuje szukanie |
radio | jeden wybór z grupy | wszystkie opcje mają wspólne name |
checkbox | zero, jeden lub kilka wyborów | wartość jest wysyłana tylko po zaznaczeniu |
file | plik z komputera | formularz wymaga enctype="multipart/form-data" |
range | suwak z zakresem | zakres i krok ustawiasz przez min, max, step |
color | wybór koloru | wartość zapisuje się jako #rrggbb |
hidden | dane techniczne niewidoczne dla użytkownika | nie jest zabezpieczeniem — można je zmienić |
Poza polami <input> masz jeszcze cztery ważne elementy. <select> z <option> tworzy listę rozwijaną. <textarea> pozwala wpisać wiele linii — tekst początkowy umieszczasz między tagami, a nie w atrybucie value. <button type="submit"> wysyła formularz, a type="button" tylko wykonuje akcję. <fieldset> z <legend> grupuje powiązane pola i nadaje grupie nazwę.
Walidację po stronie przeglądarki ustawiasz atrybutami: required (pole musi być wypełnione), min i max (zakres liczby lub daty), minlength i maxlength (długość tekstu), pattern (wyrażenie regularne, np. [0-9]{9} oznacza dokładnie dziewięć cyfr) oraz autocomplete (podpowiedź dla przeglądarki, np. email albo current-password).
Atrybut required działa tylko w przeglądarce i można go obejść. Zawsze sprawdzaj dane ponownie na serwerze — zwłaszcza e-mail, liczbę sztuk i zgodę na regulamin.
Most: od teorii do kodu
Uzupełnij formularz logowania
Wybierz brakujące atrybuty. Formularz ma wysłać e-mail i hasło metodą POST, a oba pola mają być wymagane.
Brakujące atrybuty
uzupełnianie lukUzupełnij cztery luki.
<form action="/logowanie" method="">
<label ="email">E-mail</label>
<input type="email" id="email" ="email" required>
<label for="haslo">Hasło</label>
<input type="" id="haslo" name="haslo" required>
<button type="submit">Zaloguj</button>
</form>
Metoda post nie pokazuje danych w adresie. for w etykiecie musi wskazywać na id pola. name jest kluczem wysyłanym na serwer, a type="password" zasłania wpisywane znaki.
Znajdź błędy w formularzu
zaznaczanieZaznacz trzy linie, w których jest błąd.
-
Brakuje
name— pole nie zostanie wysłane na serwer. -
Etykieta wskazuje na pole
email, a powinna nahaslo. -
textareanie ma atrybutuvalue. Tekst początkowy wpisz między tagami.
Przykłady
Trzy formularze pokazują typowe sytuacje egzaminacyjne: logowanie, ankietę i zamówienie. W każdym zwróć uwagę na etykiety, atrybut name i sposób wysłania danych.
Zbuduj formularz logowania z etykietami, polami e-mail i hasło oraz przyciskiem. Oba pola mają być wymagane, a dane mają iść metodą POST.
<form class="logowanie" action="/logowanie" method="post">
<h2>Zaloguj się</h2>
<p>
<label for="email">Adres e-mail</label>
<input type="email" id="email" name="email"
autocomplete="email" placeholder="ala@example.com" required>
</p>
<p>
<label for="haslo">Hasło</label>
<input type="password" id="haslo" name="haslo"
minlength="8" autocomplete="current-password" required>
</p>
<p>
<button type="submit">Zaloguj</button>
</p>
</form>
.logowanie {
max-width: 380px;
margin: 0 auto;
padding: 24px;
border: 1px solid #e2e8f0;
border-radius: 14px;
background: #fff;
}
.logowanie h2 {
margin: 0 0 18px;
}
.logowanie p {
margin: 0 0 16px;
}
.logowanie label {
display: block;
margin-bottom: 6px;
font-weight: 600;
}
.logowanie input {
width: 100%;
padding: 10px 12px;
border: 1px solid #94a3b8;
border-radius: 8px;
font: inherit;
}
.logowanie input:focus {
outline: 3px solid #2563eb;
outline-offset: 2px;
border-color: #2563eb;
}
.logowanie button {
padding: 10px 18px;
border: 0;
border-radius: 8px;
background: #2563eb;
color: #fff;
font: inherit;
cursor: pointer;
}
action="/logowanie"wskazuje adres, amethod="post"ukrywa dane w adresie.label for="email"łączy się zinput id="email"— kliknięcie w etykietę ustawia kursor w polu.type="email"uruchamia podstawową walidację adresu, arequiredblokuje wysłanie pustego pola.minlength="8"wymaga co najmniej ośmiu znaków hasła.autocompletepomaga przeglądarce podpowiedzieć zapisane dane.
Wynik: formularz wysyła parę email=... i haslo=... metodą POST; przeglądarka pilnuje pustych pól i formatu e-maila.
Zbierz odpowiedzi przez radio, checkbox, listę rozwijaną i obszar tekstowy. Pogrupuj powiązane pola w fieldset z legend.
<form class="ankieta" action="/ankieta" method="post">
<fieldset>
<legend>Jak często uczysz się HTML?</legend>
<label><input type="radio" name="czestotliwosc"
value="codziennie" required> codziennie</label>
<label><input type="radio" name="czestotliwosc"
value="tydzien"> raz w tygodniu</label>
<label><input type="radio" name="czestotliwosc"
value="rzadko"> rzadko</label>
</fieldset>
<fieldset>
<legend>Które tematy chcesz powtórzyć?</legend>
<label><input type="checkbox" name="tematy"
value="formularze"> formularze</label>
<label><input type="checkbox" name="tematy"
value="tabele"> tabele</label>
<label><input type="checkbox" name="tematy"
value="grid"> grid</label>
</fieldset>
<p>
<label for="poziom">Poziom zaawansowania</label>
<select id="poziom" name="poziom">
<option value="">— wybierz —</option>
<option value="podstawowy">podstawowy</option>
<option value="sredni">średni</option>
<option value="zaawansowany">zaawansowany</option>
</select>
</p>
<p>
<label for="uwagi">Uwagi</label>
<textarea id="uwagi" name="uwagi" rows="3"></textarea>
</p>
<button type="submit">Wyślij ankietę</button>
</form>
.ankieta {
max-width: 640px;
margin: 0 auto;
}
.ankieta fieldset {
margin: 0 0 18px;
padding: 12px 16px 14px;
border: 1px solid #cbd5e1;
border-radius: 10px;
}
.ankieta legend {
padding: 0 6px;
font-weight: 700;
}
.ankieta label {
display: block;
margin: 6px 0;
}
.ankieta p {
margin: 0 0 16px;
}
.ankieta select,
.ankieta textarea {
width: 100%;
padding: 9px 10px;
border: 1px solid #94a3b8;
border-radius: 8px;
font: inherit;
}
.ankieta button {
padding: 10px 18px;
border: 0;
border-radius: 8px;
background: #2563eb;
color: #fff;
font: inherit;
cursor: pointer;
}
fieldset z legendami, lista rozwijana i pole wielolinijkowe.- Wszystkie opcje radio w jednej grupie mają to samo
name="czestotliwosc"— dlatego można wybrać tylko jedną. - Checkboxy mają wspólne
name="tematy", ale różnevalue— można zaznaczyć kilka i serwer dostanie kilka wartości. fieldsetilegendopisują całą grupę, więc czytnik ekranu odczyta kontekst przed każdą opcją.selectma pustą opcję zachęty, atextareanie ma atrybutuvalue— tekst wpisuje się między tagami.
Wynik: ankieta wysyła jedną wartość czestotliwosc, wybrane wartości tematy, poziom i treść uwag.
Ułóż formularz zamówienia w dwóch kolumnach. Użyj pól number, date, tel, range, color i file, a focus zaznacz wyraźną obwódką.
<form class="zamowienie" action="/zamowienie" method="post"
enctype="multipart/form-data">
<h2>Zamówienie</h2>
<p class="pole">
<label for="imie">Imię i nazwisko</label>
<input type="text" id="imie" name="imie"
autocomplete="name" autofocus required>
</p>
<p class="pole">
<label for="email">Adres e-mail</label>
<input type="email" id="email" name="email"
autocomplete="email" required>
</p>
<p class="pole">
<label for="telefon">Telefon</label>
<input type="tel" id="telefon" name="telefon"
pattern="[0-9]{9}" placeholder="123456789" required>
</p>
<p class="pole">
<label for="data">Data odbioru</label>
<input type="date" id="data" name="data" required>
</p>
<p class="pole">
<label for="ilosc">Liczba sztuk</label>
<input type="number" id="ilosc" name="ilosc"
min="1" max="10" value="1" required>
</p>
<p class="pole">
<label for="kolor">Kolor</label>
<input type="color" id="kolor" name="kolor" value="#2563eb">
</p>
<p class="pole">
<label for="zakres">Zakres</label>
<input type="range" id="zakres" name="zakres"
min="0" max="100" value="50">
</p>
<p class="pole">
<label for="plik">Projekt do wydruku</label>
<input type="file" id="plik" name="plik"
accept="image/png,image/jpeg">
</p>
<p class="pole pelna">
<label for="uwagi">Uwagi</label>
<textarea id="uwagi" name="uwagi" rows="3"></textarea>
</p>
<input type="hidden" name="zrodlo" value="kurs">
<p class="pelna">
<button type="submit">Złóż zamówienie</button>
</p>
</form>
.zamowienie {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px 20px;
max-width: 720px;
margin: 0 auto;
}
.zamowienie h2,
.zamowienie .pelna {
grid-column: 1 / -1;
}
.zamowienie h2 {
margin: 0;
}
.zamowienie .pole {
display: grid;
gap: 6px;
margin: 0;
}
.zamowienie label {
font-weight: 600;
}
.zamowienie input,
.zamowienie select,
.zamowienie textarea {
padding: 10px 12px;
border: 1px solid #94a3b8;
border-radius: 8px;
font: inherit;
}
.zamowienie input:focus,
.zamowienie select:focus,
.zamowienie textarea:focus {
outline: 3px solid #2563eb;
outline-offset: 2px;
border-color: #2563eb;
}
.zamowienie input[type="color"] {
height: 44px;
padding: 4px;
}
.zamowienie button {
padding: 10px 18px;
border: 0;
border-radius: 8px;
background: #2563eb;
color: #fff;
font: inherit;
cursor: pointer;
}
display: gridigrid-template-columns: 1fr 1frtworzą dwie równe kolumny.- Elementy z klasą
.pelnaoraz nagłówek rozciągają się przez obie kolumny dziękigrid-column: 1 / -1. type="number"zmin="1" max="10"ogranicza liczbę sztuk, apattern="[0-9]{9}"wymaga dziewięciu cyfr telefonu.enctype="multipart/form-data"jest potrzebne, gdy formularz wysyła plik.autofocusustawia focus w pierwszym polu, dlatego widać obwódkę.
Wynik: formularz układa pola w siatce, pokazuje focus i wysyła dane oraz plik metodą POST.
Most: od teorii do kodu
Oceń formularz ankiety
Przeczytaj każdą linię i wybierz kategorię. Nie każda linia jest błędna.
Code review formularza
code reviewOceń każdą linię.
-
Poprawne wysłanie danych metodą POST.
-
Etykieta jest połączona z polem przez
foriid. -
Pole nie ma etykiety.
placeholdernie zastępujelabel. -
Radio z różnymi
namenie tworzą jednej grupy — można zaznaczyć oba naraz. -
textareanie ma atrybutuvalue; tekst początkowy powinien być między tagami. -
type="button"nie wysyła formularza. Do wysłania służytype="submit". -
requiredna checkboxie wymaga zaznaczenia zgody przed wysłaniem.
Spróbuj samodzielnie
Zanim napiszesz własny formularz, sprawdź, co przeglądarka wysyła po kliknięciu przycisku. Potem wykonaj zadania — od najprostszego do egzaminacyjnego.
Most: od teorii do kodu
Co trafi do adresu?
Formularz używa metody GET. Sprawdź, jak będą wyglądać dane po wysłaniu.
Adres po wysłaniu formularza
przewidywanieKtóry adres otworzy przeglądarka po wysłaniu formularza?
<form action="/szukaj" method="get">
<input type="search" name="q" value="html css">
<input type="hidden" name="dzial" value="kursy">
<button type="submit">Szukaj</button>
</form>
Metoda GET dopisuje pary name=value po znaku ?. Spacja w wartości zmienia się na +, a pole hidden też jest wysyłane.
-
Zadanie 1 — newsletter. Napisz formularz zapisu do newslettera: pole e-mail z etykietą, przycisk „Zapisz się”, wymagane pole i wysyłka metodą POST do
/newsletter.Pokaż rozwiązanie
Najpierw łączymy etykietę z polem przez
foriid. Potem dodajemyname,type="email"irequired. Całość wysyłamy metodą POST.<form action="/newsletter" method="post"> <label for="email">Adres e-mail</label> <input type="email" id="email" name="email" autocomplete="email" required> <button type="submit">Zapisz się</button> </form>Etykieta jest powiązana z polem, więc kliknięcie w tekst ustawia kursor.
requiredblokuje wysłanie pustego pola, ale serwer i tak musi sprawdzić adres ponownie. -
Zadanie 2 — ankieta. Zbuduj ankietę z trzema opcjami radio („tak”, „nie”, „nie wiem”) w grupie „Czy znasz formularze?”, dwoma checkboxami tematów oraz listą rozwijaną poziomu. Użyj
fieldsetilegend.Pokaż rozwiązanie
Wszystkie radio muszą mieć to samo
name, np.znasz. Checkboxy mogą mieć wspólnename="tematy"i różnevalue. Grupy zamykamy wfieldsetzlegend.<form action="/ankieta" method="post"> <fieldset> <legend>Czy znasz formularze?</legend> <label><input type="radio" name="znasz" value="tak" required> tak</label> <label><input type="radio" name="znasz" value="nie"> nie</label> <label><input type="radio" name="znasz" value="nie-wiem"> nie wiem</label> </fieldset> <fieldset> <legend>Tematy do powtórki</legend> <label><input type="checkbox" name="tematy" value="formularze"> formularze</label> <label><input type="checkbox" name="tematy" value="grid"> grid</label> </fieldset> <p> <label for="poziom">Poziom</label> <select id="poziom" name="poziom"> <option value="">— wybierz —</option> <option value="podstawowy">podstawowy</option> <option value="sredni">średni</option> </select> </p> <button type="submit">Wyślij</button> </form> -
Zadanie 3 — znajdź błędy. Uczeń napisał formularz poniżej. Wskaż trzy błędy i popraw je: brakujące
name, złą etykietę i tekst wtextarea.<form action="/zapis" method="post"> <label for="email">Telefon</label> <input type="text" id="telefon"> <textarea name="uwagi" value="Brak uwag"></textarea> <button type="submit">Wyślij</button> </form>Pokaż rozwiązanie
Poprawki: etykieta musi wskazywać
for="telefon", pole musi miećname="telefon", a tekst początkowy wtextareawpisujemy między tagami.<form action="/zapis" method="post"> <label for="telefon">Telefon</label> <input type="text" id="telefon" name="telefon"> <textarea name="uwagi">Brak uwag</textarea> <button type="submit">Wyślij</button> </form>Metoda rozwiązania: najpierw sprawdź, czy każda etykieta ma
forrówneidpola. Potem sprawdź, czy każde pole maname. Na końcu zajrzyj do elementów, które mają własną treść —textareaibutton. -
Zadanie 4 — zamówienie. Zaprojektuj formularz zamówienia: imię, e-mail, telefon z
patternna 9 cyfr, liczbę sztuk od 1 do 5, datę odbioru i zgodę na regulamin. Ułóż pola w dwóch kolumnach przez CSS Grid i wyjaśnij, dlaczego używasz POST.Pokaż rozwiązanie
Formularz ma dwa pola w każdym rzędzie. Pola imienia i e-maila mogą być w pierwszym rzędzie, telefon i data w drugim, liczba sztuk i zgoda w trzecim. Przycisk zajmuje całą szerokość.
<form class="zamowienie" action="/zamowienie" method="post"> <p class="pole"> <label for="imie">Imię</label> <input type="text" id="imie" name="imie" required> </p> <p class="pole"> <label for="email">E-mail</label> <input type="email" id="email" name="email" required> </p> <p class="pole"> <label for="telefon">Telefon</label> <input type="tel" id="telefon" name="telefon" pattern="[0-9]{9}" required> </p> <p class="pole"> <label for="data">Data odbioru</label> <input type="date" id="data" name="data" required> </p> <p class="pole"> <label for="ilosc">Liczba sztuk</label> <input type="number" id="ilosc" name="ilosc" min="1" max="5" value="1" required> </p> <p class="pole"> <label><input type="checkbox" name="regulamin" value="tak" required> Akceptuję regulamin</label> </p> <p class="pelna"> <button type="submit">Zamów</button> </p> </form>.zamowienie { display: grid; grid-template-columns: 1fr 1fr; gap: 16px 20px; } .zamowienie .pelna { grid-column: 1 / -1; } .zamowienie .pole { display: grid; gap: 6px; margin: 0; }POST jest lepszy, bo zamówienie zawiera dane kontaktowe i nie powinno trafiać do adresu strony ani historii przeglądarki.
requiredpilnuje pustych pól w przeglądarce, amin,maxipatternzawężają wartości — ale serwer nadal musi je sprawdzić.
Podsumowanie. Formularz wysyła pary name=value na adres z action, metodą get lub post. Każde pole nazwij przez name, połącz z etykietą przez for i id, a grupę pól zamknij w fieldset z legend. Walidacja w przeglądarce (required, min, max, pattern) pomaga użytkownikowi, ale nie zastępuje sprawdzenia na serwerze.