Potwierdzone sprawdzone punkt po punkcie · 2026-11-05
Pomiń nawigację
Informatyka · INF.03 · egzamin

HTML I CSS · INF.03 · ZESTAW EGZAMINACYJNY

Zestaw egzaminacyjny — 3 projekty

Trzy zadania w stylu egzaminu zawodowego. Każde ma wymagania, zrzut gotowej strony i pełne rozwiązanie w HTML oraz CSS.

Zadanie 1 — Wizytówka firmy „Zielony Liść”

Fikcyjne studio ogrodów „Zielony Liść” potrzebuje jednostronicowej wizytówki. To typowe zadanie egzaminacyjne: nagłówek z logo i nawigacją, sekcja powitalna z obrazem, trzy karty usług, formularz kontaktowy oraz stopka. Całość wykonasz w czystym HTML5 i CSS3, bez JavaScriptu.

Wizytówka Zielony Liść: nagłówek z logo i menu, duży nagłówek nad obrazem lasu, trzy karty usług oraz zielona sekcja kontaktu z formularzem i stopką
Gotowa strona: dwukolumnowe hero i kontakt, trzy karty usług w gridzie oraz formularz z etykietami i widocznym przyciskiem.

Wymagania do wizytówki

  1. Dokument HTML5: <!doctype html>, lang="pl", kodowanie UTF-8, meta viewport i tytuł strony.
  2. Podział semantyczny: header, nav, main, trzy sekcje section i footer. Na stronie jest dokładnie jeden h1.
  3. Nagłówek: logo złożone ze znaku SVG, nazwy i podtytułu oraz nawigacja z linkami „Usługi”, „Kontakt” i wyróżnionym przyciskiem „Zamów konsultację”.
  4. Hero: etykieta nad tytułem, h1, akapit opisu, dwa odnośniki (jeden prowadzi do #kontakt) oraz lista trzech liczb.
  5. Obraz w hero: plik las.svg, sensowny alt, podpis w figcaption, proporcje 4:3, object-fit: cover i zaokrąglone rogi.
  6. Sekcja usług: dokładnie trzy karty article w CSS Grid (repeat(3, 1fr)), każda z numerem, nagłówkiem h3, opisem i linkiem.
  7. Kolory: ciemna zieleń #14532d, akcent #84cc16 i tło #f7f8f2. Zapisz je jako zmienne CSS w :root i używaj w regułach.
  8. Typografia: nagłówki krojem szeryfowym (Georgia), tekst bezszeryfowy (Segoe UI lub systemowy), bazowo 16 px i interlinia 1.65.
  9. Formularz: pola imię i nazwisko, e-mail, temat (select), wiadomość (textarea), checkbox zgody oraz przycisk type="submit".
  10. Dostępność formularza: każde pole ma label powiązany przez for i id, e-mail ma type="email", pola wymagane mają required, a kontrolki — autocomplete.
  11. Układ: strona ma maksymalnie 960 px szerokości i jest wyśrodkowana. Hero oraz kontakt to dwie kolumny, a odstępy w sekcjach wynoszą 36–48 px.
  12. Responsywność: poniżej 760 px hero, karty i kontakt przechodzą na jedną kolumnę, nawigacja się zawija, a padding boczny maleje do 22 px.
  13. Stany interakcji: karty usług delikatnie się unoszą po najechaniu, a linki i przyciski mają czytelny stan :hover oraz :focus-visible.
  14. Stopka: nazwa firmy, rok i link „Wróć na górę”. Tekst na ciemnym tle musi mieć dobry kontrast.
  15. Klasy mają nazwy opisujące rolę elementu (np. naglowek, hero, karta, formularz). Nie używaj stylów inline ani przypadkowych nazw typu box1.

Wskazówki do wizytówki

Wskazówka 1 — zacznij od szkieletu

Najpierw wstaw header, nav, main i footer, a dopiero potem dodawaj klasy i style. Jeśli od razu ozdobisz stronę, łatwiej zgubić semantykę i zamknąć element nie w tym miejscu.

Wskazówka 2 — dwa gridy, jeden wzorzec

Hero ustaw jako grid-template-columns: 1.05fr .95fr, a kontakt jako .9fr 1.1fr. W media query oba zamień na 1fr — nie potrzebujesz do tego osobnych klas.

Wskazówka 3 — sprawdź formularz Tabem

Klikając Tab, przejdź przez wszystkie pola. Jeśli fokus znika albo nie widać, które pole jest aktywne, popraw :focus-visible. Etykiety muszą być widoczne także po wpisaniu tekstu.

Rozwiązanie — wizytówka

Pokaż pełne rozwiązanie

Kluczowe decyzje

  • Wspólny kontener: body.strona ustawia tło, kolor tekstu i typografię w jednym miejscu, więc sekcje nie powtarzają tych samych reguł.
  • Dwie kolumny: hero i kontakt korzystają z CSS Grid. Media query zmienia tylko liczbę kolumn, bez przebudowy HTML.
  • Karty jako article: każda usługa jest samodzielną treścią z własnym nagłówkiem h3 i linkiem, a nie zwykłym divem.
  • Formularz: label for, required, type="email" i autocomplete dają działanie myszką, klawiaturą i czytnikiem ekranu.
  • Obraz: aspect-ratio: 4 / 3 i object-fit: cover utrzymują stałe proporcje, więc obraz nie rozciąga się i nie przesuwa układu.

Zapisz kod jako index.html i style.css w jednym folderze, a obraz umieść w assets/las.svg. W podglądzie kursu ten sam plik leży w ../assets/las.svg.

HTML
<!doctype html>
<html lang="pl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Zielony Liść — studio ogrodów</title>
  <link rel="stylesheet" href="style.css">
</head>
<body class="strona">
    <header class="naglowek">
        <a class="logo" href="#start">
            <svg class="logo-znak" viewBox="0 0 48 48" aria-hidden="true" focusable="false">
                <circle cx="24" cy="24" r="24" fill="#14532d"/>
                <path d="M33 13c-9 1-15 6-16 14 0 0 6 1 10-2 4-3 6-8 6-12Z" fill="#a3e635"/>
                <path d="M15 34c3-7 7-11 13-14" fill="none" stroke="#ecfccb" stroke-width="2" stroke-linecap="round"/>
            </svg>
            <span class="logo-tekst">Zielony Liść<small>studio ogrodów</small></span>
        </a>
        <nav aria-label="Nawigacja główna">
            <ul class="menu">
                <li><a href="#uslugi">Usługi</a></li>
                <li><a href="#kontakt">Kontakt</a></li>
                <li><a class="menu-cta" href="#kontakt">Zamów konsultację</a></li>
            </ul>
        </nav>
    </header>

    <main id="start">
        <section class="hero">
            <div class="hero-tekst">
                <p class="etykieta">Projektowanie · pielęgnacja · doradztwo</p>
                <h1>Ogród, w którym chce się zostać</h1>
                <p class="hero-lead">Projektujemy zielone przestrzenie, które żyją razem z Tobą. Od pierwszego szkicu po ostatnią posadzoną bylinę — z uważnością na światło, glebę i codzienne nawyki.</p>
                <div class="hero-akcje">
                    <a class="przycisk" href="#kontakt">Zamów konsultację</a>
                    <a class="link-strzalka" href="#uslugi">Zobacz usługi →</a>
                </div>
                <ul class="hero-liczby">
                    <li><strong>15</strong> lat doświadczenia</li>
                    <li><strong>240</strong> gotowych ogrodów</li>
                    <li><strong>100%</strong> roślin z polskich szkółek</li>
                </ul>
            </div>
            <figure class="hero-obraz">
                <img src="assets/las.svg" alt="Słoneczny las z wysokimi drzewami i zielonym poszyciem">
                <figcaption>Ogród leśny — realizacja z 2025 roku</figcaption>
            </figure>
        </section>

        <section class="uslugi" id="uslugi" aria-labelledby="uslugi-tytul">
            <div class="sekcja-naglowek">
                <p class="etykieta">Co robimy</p>
                <h2 id="uslugi-tytul">Trzy kroki do zielonego ogrodu</h2>
                <p>Zaczynamy od rozmowy, kończymy na gotowej przestrzeni. Ty decydujesz o tempie i budżecie.</p>
            </div>
            <div class="karty">
                <article class="karta">
                    <span class="karta-nr">01</span>
                    <h3>Projekt ogrodu</h3>
                    <p>Inwentaryzacja działki, koncepcja i rysunek techniczny z doborem roślin dopasowanym do stanowiska.</p>
                    <a href="#kontakt">Zapytaj o projekt →</a>
                </article>
                <article class="karta">
                    <span class="karta-nr">02</span>
                    <h3>Pielęgnacja</h3>
                    <p>Regularne cięcia, nawożenie i ochrona roślin. Opiekujemy się ogrodem przez cały sezon.</p>
                    <a href="#kontakt">Zamów wizytę →</a>
                </article>
                <article class="karta">
                    <span class="karta-nr">03</span>
                    <h3>Doradztwo</h3>
                    <p>Godzinna konsultacja na miejscu lub online. Podpowiemy, co zmienić, żeby ogród odetchnął.</p>
                    <a href="#kontakt">Umów rozmowę →</a>
                </article>
            </div>
        </section>

        <section class="kontakt" id="kontakt" aria-labelledby="kontakt-tytul">
            <div class="kontakt-info">
                <p class="etykieta">Kontakt</p>
                <h2 id="kontakt-tytul">Porozmawiajmy o Twoim ogrodzie</h2>
                <p>Napisz kilka słów o miejscu i pomysłach. Odpowiemy w ciągu dwóch dni roboczych i zaproponujemy termin bezpłatnej rozmowy.</p>
                <dl class="dane">
                    <div><dt>Adres</dt><dd>ul. Lipowa 12, 20-001 Lublin</dd></div>
                    <div><dt>Telefon</dt><dd>81 555 20 40</dd></div>
                    <div><dt>E-mail</dt><dd>kontakt@zielonylisc.pl</dd></div>
                    <div><dt>Godziny</dt><dd>pon.–pt. 8:00–16:00</dd></div>
                </dl>
            </div>
            <form class="formularz" action="#" method="post">
                <h3>Formularz kontaktowy</h3>
                <div class="pola-dwa">
                    <div class="pole">
                        <label for="imie">Imię i nazwisko</label>
                        <input id="imie" name="imie" type="text" autocomplete="name" required>
                    </div>
                    <div class="pole">
                        <label for="email">Adres e-mail</label>
                        <input id="email" name="email" type="email" autocomplete="email" required>
                    </div>
                </div>
                <div class="pole">
                    <label for="temat">Czego dotyczy zapytanie?</label>
                    <select id="temat" name="temat">
                        <option>Projekt ogrodu</option>
                        <option>Pielęgnacja</option>
                        <option>Doradztwo</option>
                    </select>
                </div>
                <div class="pole">
                    <label for="wiadomosc">Wiadomość</label>
                    <textarea id="wiadomosc" name="wiadomosc" rows="3" required></textarea>
                </div>
                <label class="zgoda">
                    <input type="checkbox" name="zgoda" required>
                    <span>Zgadzam się na kontakt w sprawie zapytania i przetwarzanie danych zgodnie z polityką prywatności.</span>
                </label>
                <button class="przycisk" type="submit">Wyślij zapytanie</button>
                <p class="formularz-nota">Odpowiadamy w ciągu dwóch dni roboczych.</p>
            </form>
        </section>
    </main>

    <footer class="stopka">
        <p><strong>Zielony Liść</strong> — studio ogrodów z Lublina</p>
        <p>© 2026 Zielony Liść</p>
        <p><a href="#start">Wróć na górę ↑</a></p>
    </footer>
</body>
</html>
CSS
* { box-sizing: border-box; }

body { margin: 0; }

:root {
    --zielen: #14532d;
    --zielen-ciemna: #0f2e1c;
    --akcent: #84cc16;
    --tlo: #f7f8f2;
    --tekst: #1e293b;
}

.strona {
    background: var(--tlo);
    color: var(--tekst);
    font: 16px/1.65 "Segoe UI", system-ui, -apple-system, sans-serif;
}

.strona h1,
.strona h2,
.strona h3 {
    margin: 0;
    color: var(--zielen);
    font-family: Georgia, "Times New Roman", serif;
    line-height: 1.15;
}

.strona p { margin: 0; }
.strona img { display: block; max-width: 100%; }
.strona a { color: inherit; }

.strona a:focus-visible,
.strona button:focus-visible,
.strona input:focus-visible,
.strona select:focus-visible,
.strona textarea:focus-visible {
    outline: 3px solid #f59e0b;
    outline-offset: 2px;
}

.naglowek {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 14px 48px;
    border-bottom: 1px solid #dce7cf;
    background: #fbfdf7;
}

.logo {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
}

.logo-znak { width: 44px; height: 44px; flex: 0 0 auto; }

.logo-tekst {
    display: flex;
    flex-direction: column;
    color: var(--zielen);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 21px;
    font-weight: 700;
    line-height: 1.05;
}

.logo-tekst small {
    margin-top: 4px;
    color: #65805a;
    font-family: "Segoe UI", system-ui, sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
}

.menu {
    display: flex;
    align-items: center;
    gap: 28px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.menu a {
    display: inline-block;
    padding: 6px 2px;
    border-bottom: 2px solid transparent;
    color: #334155;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
}

.menu a:hover { color: var(--zielen); border-bottom-color: var(--akcent); }

.menu .menu-cta {
    padding: 10px 18px;
    border: 0;
    border-radius: 999px;
    background: var(--zielen);
    color: #fff;
}

.menu .menu-cta:hover { background: #166534; color: #fff; }

.hero {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    gap: 44px;
    align-items: center;
    padding: 42px 48px 32px;
    background: linear-gradient(135deg, #f1f8e8 0%, #fbfdf7 70%);
}

.etykieta {
    margin: 0 0 12px;
    color: #4d7c0f;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.hero h1 { max-width: 13ch; font-size: 45px; letter-spacing: -.02em; }

.hero-lead {
    max-width: 46ch;
    margin-top: 14px;
    color: #475569;
    font-size: 15.5px;
}

.hero-akcje {
    display: flex;
    align-items: center;
    gap: 22px;
    margin-top: 20px;
    flex-wrap: wrap;
}

.przycisk {
    display: inline-block;
    padding: 13px 24px;
    border: 0;
    border-radius: 999px;
    background: var(--zielen);
    color: #fff;
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
}

.strona .przycisk { color: #fff; }
.przycisk:hover { background: #166534; }

.link-strzalka {
    padding-bottom: 2px;
    border-bottom: 1px solid var(--akcent);
    color: var(--zielen);
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
}

.hero-liczby {
    display: flex;
    gap: 26px;
    margin: 22px 0 0;
    padding: 13px 0 0;
    border-top: 1px solid #d9e6c8;
    list-style: none;
    flex-wrap: wrap;
}

.hero-liczby li { color: #64748b; font-size: 11.5px; line-height: 1.35; }

.hero-liczby strong {
    display: block;
    color: var(--zielen);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 23px;
}

.hero-obraz { margin: 0; }

.hero-obraz img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 20px;
    box-shadow: 0 20px 40px rgba(20, 83, 45, .18);
}

.hero-obraz figcaption {
    margin-top: 9px;
    color: #64748b;
    font-size: 11.5px;
    text-align: right;
}

.uslugi { padding: 38px 48px 40px; }

.sekcja-naglowek {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: 8px 40px;
    margin-bottom: 22px;
}

.sekcja-naglowek .etykieta { grid-column: 1 / -1; margin-bottom: 0; }
.sekcja-naglowek h2 { font-size: 32px; }

.sekcja-naglowek > p:last-child {
    max-width: 34ch;
    margin-bottom: 4px;
    color: #64748b;
    font-size: 13.5px;
}

.karty {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
}

.karta {
    padding: 20px 20px 18px;
    border: 1px solid #dce7cf;
    border-radius: 16px;
    background: #fff;
    transition: transform .18s ease, box-shadow .18s ease;
}

.karta:hover {
    transform: translateY(-4px);
    box-shadow: 0 16px 30px rgba(20, 83, 45, .10);
}

.karta-nr {
    display: inline-grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: #ecfccb;
    color: #3f6212;
    font-size: 13px;
    font-weight: 700;
}

.karta h3 { margin: 12px 0 6px; font-size: 20px; }
.karta p { margin-bottom: 12px; color: #64748b; font-size: 13.5px; }

.karta a {
    color: #3f6212;
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
}

.karta a:hover { text-decoration: underline; }

.kontakt {
    display: grid;
    grid-template-columns: .9fr 1.1fr;
    gap: 36px;
    padding: 36px 48px;
    background: var(--zielen);
    color: #e8f3dc;
}

.kontakt .etykieta { color: #bef264; }
.kontakt h2 { max-width: 14ch; color: #fff; font-size: 32px; }

.kontakt-info > p:not(.etykieta) {
    max-width: 40ch;
    margin-top: 14px;
    color: #c7dbb6;
    font-size: 14.5px;
}

.dane { display: grid; gap: 13px; margin: 22px 0 0; }

.dane div {
    display: grid;
    grid-template-columns: 84px 1fr;
    gap: 10px;
}

.dane dt {
    padding-top: 2px;
    color: #9fbe8a;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.dane dd { margin: 0; color: #f1f7ea; font-size: 13.5px; }

.formularz {
    padding: 22px;
    border-radius: 18px;
    background: #fff;
    color: #1e293b;
    box-shadow: 0 18px 40px rgba(0, 0, 0, .18);
}

.formularz h3 { margin-bottom: 12px; color: var(--zielen); font-size: 19px; }
.pole { margin-bottom: 10px; }

.pola-dwa { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.pole label {
    display: block;
    margin-bottom: 5px;
    color: #334155;
    font-size: 12px;
    font-weight: 700;
}

.pole input,
.pole select,
.pole textarea {
    width: 100%;
    padding: 8px 11px;
    border: 1px solid #cbd5c0;
    border-radius: 8px;
    background: #fbfdf8;
    color: #1e293b;
    font: inherit;
    font-size: 13.5px;
}

.pole input:focus,
.pole select:focus,
.pole textarea:focus {
    border-color: #65a30d;
    outline: 2px solid #84cc16;
    outline-offset: 1px;
}

.pole textarea { min-height: 62px; resize: vertical; }

.zgoda {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    margin: 2px 0 10px;
    color: #475569;
    font-size: 11.5px;
    line-height: 1.5;
}

.zgoda input { margin-top: 3px; accent-color: #15803d; }

.formularz .przycisk { width: 100%; padding: 12px 20px; font-size: 14px; }

.formularz-nota {
    margin-top: 9px !important;
    color: #64748b;
    font-size: 11px;
    text-align: center;
}

.stopka {
    display: flex;
    justify-content: space-between;
    gap: 20px;
    padding: 16px 48px;
    background: var(--zielen-ciemna);
    color: #b8cbb0;
    font-size: 12.5px;
}

.stopka p { margin: 0; }
.stopka strong { color: #fff; }
.stopka a { color: #d9f99d; text-decoration: none; }
.stopka a:hover { text-decoration: underline; }

@media (max-width: 760px) {
    .naglowek { flex-wrap: wrap; padding: 16px 22px; }
    .menu { gap: 16px; flex-wrap: wrap; }
    .hero { grid-template-columns: 1fr; gap: 28px; padding: 34px 22px; }
    .hero h1 { font-size: 36px; }
    .hero-liczby { gap: 18px; }
    .uslugi { padding: 36px 22px; }
    .sekcja-naglowek { grid-template-columns: 1fr; }
    .karty { grid-template-columns: 1fr; }
    .kontakt { grid-template-columns: 1fr; gap: 28px; padding: 36px 22px; }
    .kontakt h2 { max-width: none; }
    .stopka { flex-direction: column; padding: 20px 22px; }
}
Przed oddaniem sprawdź
  • Czy jest jeden h1 i czy każda sekcja ma własny nagłówek h2?
  • Czy każde pole formularza ma label powiązany przez for i id?
  • Czy po zwężeniu okna do 360 px nic nie wystaje w poziomie?
  • Czy obraz ma sensowny alt, a linki widoczny focus?
  • Czy kolory i odstępy są spójne — najlepiej przez zmienne CSS?

Zadanie 2 — Galeria podróży „Kadr w drogę”

Kolejne zadanie sprawdza pracę z powtarzalnymi kartami. Twoim celem jest galeria sześciu zdjęć z podpisami, zbudowana w CSS Grid, z delikatnym efektem hover i układem, który na telefonie nadal wygląda dobrze. Nie używaj JavaScriptu ani gotowych bibliotek.

Galeria podróży: ciemny nagłówek z logo, duży tytuł, opis, trzy liczby oraz sześć zdjęć w trzech kolumnach z podpisami
Galeria sześciu kadrów w trzech kolumnach. Podpisy są zawsze widoczne, a hover tylko powiększa zdjęcie i unosi kartę.

Wymagania do galerii

  1. Dokument HTML5 z lang="pl", kodowaniem UTF-8, meta viewport i tytułem strony.
  2. Semantyka: header, main, section, sześć par figure i figcaption oraz footer. Na stronie jest jeden h1 i jeden h2 galerii.
  3. Nagłówek: znak graficzny SVG, nazwa „Kadr w drogę” i podtytuł. Po prawej stronie znajduje się informacja „6 kadrów · 4 kraje · 2 lata”.
  4. Wstęp: etykieta, h1, akapit opisowy oraz lista trzech liczb: 6 zdjęć, 4 kraje i 4 200 km.
  5. Galeria: dokładnie sześć elementów figure w CSS Grid, trzy kolumny i odstęp 20 px.
  6. Każdy kadr zawiera obraz z atrybutem alt, tag kategorii (Góry, Morze, Las, Miasto) oraz podpis z tytułem i miejscem lub rokiem.
  7. Wykorzystaj wszystkie obrazki: gory.svg, morze.svg, las.svg i miasto.svg — każdy co najmniej raz.
  8. Obrazy mają stałe proporcje 4:3 (aspect-ratio), wypełniają kadr przez object-fit: cover i są przycięte przez overflow: hidden.
  9. Efekt hover: karta unosi się o 5 px (translateY), obraz skaluje się do 1.08, a przejścia są płynne (0.2–0.35 s). Podpisy pozostają czytelne.
  10. Kolory: tło #f8f4ec, ciemny nagłówek #1c1917 i akcent #c2410c. Zapisz je jako zmienne CSS.
  11. Typografia: nagłówki szeryfowe (Georgia), tekst bezszeryfowy. h1 ma około 52 px, tytuł kadru 17 px, a podpis z miejscem 11.5 px.
  12. Responsywność: przy 900 px galeria ma dwie kolumny, a poniżej 760 px jedną. Nagłówek zawija się, a padding boczny maleje do 22 px.
  13. Dostępność: alt opisuje treść zdjęcia, kontrast tekstu jest wystarczający, linki mają :focus-visible, a podpisy są widoczne bez najeżdżania myszką.
  14. Klasy opisują rolę elementu (kadr, kadr-obraz, kadr-tag), a wszystkie style znajdują się w osobnym pliku CSS — bez atrybutu style w HTML.

Wskazówki do galerii

Wskazówka 1 — równe kafle bez tabeli

Ustaw aspect-ratio: 4 / 3 na kontenerze obrazu, a sam obraz rozciągnij przez width: 100%; height: 100%; object-fit: cover. Dzięki temu każde zdjęcie ma taki sam kadr, nawet jeśli pliki mają różne proporcje.

Wskazówka 2 — hover tylko na dwóch elementach

Unoszenie ustaw na figure, a powiększenie na img. Kontener obrazu musi mieć overflow: hidden, inaczej powiększony obraz wyjedzie poza zaokrąglone rogi karty.

Wskazówka 3 — dwa progi, nie jeden

Przy 900 px zostaw dwie kolumny, a dopiero przy 760 px przejdź na jedną. Jeden próg 760 px dałby na tablecie zbyt wąskie kafle i niepotrzebnie długą stronę.

Rozwiązanie — galeria

Pokaż pełne rozwiązanie

Kluczowe decyzje

  • Grid 3 → 2 → 1: trzy reguły grid-template-columns obsługują desktop, tablet i telefon. Karty są automatycznie tej samej szerokości.
  • Figure i figcaption: para elementów opisuje zdjęcie w sposób zrozumiały dla czytnika ekranu; podpis nie jest ukrywany za hoverem.
  • Stałe proporcje: aspect-ratio rezerwuje miejsce na obraz jeszcze przed jego wczytaniem, więc galeria nie „skacze”.
  • Tag kategorii: element span jest pozycjonowany absolutnie względem kontenera obrazu. Kontener ma position: relative.
  • Wydajność: animowane są tylko transform i box-shadow, a nie szerokość czy marginesy, więc hover nie powoduje przeliczania całego układu.

Zapisz kod jako index.html i style.css, a cztery obrazki umieść w folderze assets. W podglądzie kursu leżą one w ../assets/.

HTML
<!doctype html>
<html lang="pl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Kadr w drogę — galeria podróży</title>
  <link rel="stylesheet" href="style.css">
</head>
<body class="strona">
    <header class="naglowek">
        <a class="logo" href="#start">
            <svg class="logo-znak" viewBox="0 0 40 40" aria-hidden="true" focusable="false">
                <circle cx="20" cy="20" r="19" fill="#c2410c"/>
                <path d="M7 27l8-10 5 6 4-4 7 8Z" fill="#fff7ed"/>
                <circle cx="27" cy="13" r="3" fill="#fdba74"/>
            </svg>
            <span>Kadr w drogę<small>notatnik z podróży</small></span>
        </a>
        <p class="naglowek-nota">6 kadrów · 4 kraje · 2 lata</p>
    </header>

    <main id="start">
        <section class="wstep" aria-labelledby="wstep-tytul">
            <p class="etykieta">Fotografie z podróży · 2024–2026</p>
            <h1 id="wstep-tytul">Świat widziany w kadrze</h1>
            <div class="wstep-dol">
                <p class="wstep-lead">Nie kolekcjonuję pocztówek. Zatrzymuję miejsca, w których zwolniłem na chwilę dłużej: poranną mgłę nad wodą, cień drzew i światło na ścianach starych miast.</p>
                <ul class="liczby">
                    <li><strong>6</strong> zdjęć</li>
                    <li><strong>4</strong> kraje</li>
                    <li><strong>4 200</strong> km</li>
                </ul>
            </div>
        </section>

        <section class="galeria-sekcja" id="galeria" aria-labelledby="galeria-tytul">
            <div class="galeria-naglowek">
                <h2 id="galeria-tytul">Wybrane kadry</h2>
                <p>Najedź na zdjęcie — kadr delikatnie się powiększy.</p>
            </div>
            <div class="galeria">
                <figure class="kadr">
                    <div class="kadr-obraz">
                        <img src="assets/gory.svg" alt="Ostre szczyty górskie oświetlone porannym słońcem">
                        <span class="kadr-tag">Góry</span>
                    </div>
                    <figcaption>
                        <strong>Tatry o świcie</strong>
                        <span>Polska · wrzesień 2025</span>
                    </figcaption>
                </figure>
                <figure class="kadr">
                    <div class="kadr-obraz">
                        <img src="assets/morze.svg" alt="Spokojne morze i jasne niebo z niskim słońcem">
                        <span class="kadr-tag">Morze</span>
                    </div>
                    <figcaption>
                        <strong>Bałtyk po burzy</strong>
                        <span>Polska · sierpień 2025</span>
                    </figcaption>
                </figure>
                <figure class="kadr">
                    <div class="kadr-obraz">
                        <img src="assets/las.svg" alt="Słoneczna polana w gęstym lesie iglastym">
                        <span class="kadr-tag">Las</span>
                    </div>
                    <figcaption>
                        <strong>Ścieżka w Bieszczadach</strong>
                        <span>Polska · maj 2025</span>
                    </figcaption>
                </figure>
                <figure class="kadr">
                    <div class="kadr-obraz">
                        <img src="assets/miasto.svg" alt="Sylwetka miasta z podświetlonymi oknami wieżowców">
                        <span class="kadr-tag">Miasto</span>
                    </div>
                    <figcaption>
                        <strong>Lizbona z góry</strong>
                        <span>Portugalia · marzec 2026</span>
                    </figcaption>
                </figure>
                <figure class="kadr">
                    <div class="kadr-obraz">
                        <img src="assets/gory.svg" alt="Szeroka panorama gór z zieloną doliną">
                        <span class="kadr-tag">Góry</span>
                    </div>
                    <figcaption>
                        <strong>Dolomity bez chmur</strong>
                        <span>Włochy · czerwiec 2024</span>
                    </figcaption>
                </figure>
                <figure class="kadr">
                    <div class="kadr-obraz">
                        <img src="assets/morze.svg" alt="Błękitna woda i jasny horyzont nad zatoką">
                        <span class="kadr-tag">Morze</span>
                    </div>
                    <figcaption>
                        <strong>Zatoka w Chorwacji</strong>
                        <span>Chorwacja · lipiec 2024</span>
                    </figcaption>
                </figure>
            </div>
        </section>
    </main>

    <footer class="stopka" id="stopka">
        <p><strong>Kadr w drogę</strong> — prywatny notatnik z podróży</p>
        <p>Zdjęcia: archiwum autora · 2026</p>
        <p><a href="#start">Wróć na górę ↑</a></p>
    </footer>
</body>
</html>
CSS
* { box-sizing: border-box; }

body { margin: 0; }

:root {
    --tlo: #f8f4ec;
    --ciemny: #1c1917;
    --akcent: #c2410c;
    --tekst: #292524;
}

.strona {
    background: var(--tlo);
    color: var(--tekst);
    font: 16px/1.6 "Segoe UI", system-ui, -apple-system, sans-serif;
}

.strona h1,
.strona h2,
.strona h3 {
    margin: 0;
    color: var(--ciemny);
    font-family: Georgia, "Times New Roman", serif;
    line-height: 1.12;
}

.strona p { margin: 0; }
.strona img { display: block; max-width: 100%; }
.strona a { color: inherit; }

.strona a:focus-visible,
.strona button:focus-visible {
    outline: 3px solid #f59e0b;
    outline-offset: 3px;
}

.naglowek {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 18px 56px;
    background: var(--ciemny);
    color: #faf7f2;
}

.logo {
    display: flex;
    align-items: center;
    gap: 12px;
    color: #faf7f2;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 22px;
    font-weight: 700;
    text-decoration: none;
}

.logo-znak { width: 38px; height: 38px; flex: 0 0 auto; }

.logo small {
    display: block;
    margin-top: 2px;
    color: #c7bfb4;
    font-family: "Segoe UI", system-ui, sans-serif;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
}

.naglowek-nota {
    padding: 7px 14px;
    border: 1px solid #44403c;
    border-radius: 999px;
    color: #d6d3d1;
    font-size: 12px;
    letter-spacing: .02em;
}

.wstep { padding: 52px 56px 34px; }

.etykieta {
    margin: 0 0 10px;
    color: var(--akcent);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.wstep h1 { max-width: 16ch; font-size: 52px; letter-spacing: -.02em; }

.wstep-dol {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 24px 48px;
    align-items: end;
    margin-top: 18px;
}

.wstep-lead {
    max-width: 58ch;
    color: #57534e;
    font-size: 16px;
}

.liczby {
    display: flex;
    gap: 26px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.liczby li {
    padding-left: 12px;
    border-left: 2px solid #d6bfa4;
    color: #78716c;
    font-size: 11px;
    line-height: 1.35;
}

.liczby strong {
    display: block;
    color: var(--ciemny);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 22px;
}

.galeria-sekcja { padding: 0 56px 48px; }

.galeria-naglowek {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 20px;
    margin-bottom: 20px;
    padding-top: 24px;
    border-top: 1px solid #e4d9c8;
}

.galeria-naglowek h2 { font-size: 28px; }

.galeria-naglowek p {
    color: #78716c;
    font-size: 12.5px;
}

.galeria {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
}

.kadr {
    margin: 0;
    overflow: hidden;
    border: 1px solid #e4d9c8;
    border-radius: 15px;
    background: #fffdf9;
    transition: transform .2s ease, box-shadow .2s ease;
}

.kadr:hover {
    transform: translateY(-5px);
    box-shadow: 0 18px 34px rgba(41, 37, 36, .14);
}

.kadr-obraz {
    position: relative;
    overflow: hidden;
    aspect-ratio: 4 / 3;
    background: #e7e5e4;
}

.kadr-obraz img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .35s ease;
}

.kadr:hover .kadr-obraz img { transform: scale(1.08); }

.kadr-tag {
    position: absolute;
    top: 11px;
    left: 11px;
    padding: 5px 10px;
    border-radius: 999px;
    background: rgba(28, 25, 23, .78);
    color: #fff7ed;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.kadr figcaption { padding: 12px 15px 14px; }

.kadr figcaption strong {
    display: block;
    color: var(--ciemny);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 17px;
    line-height: 1.25;
}

.kadr figcaption span {
    display: block;
    margin-top: 2px;
    color: #78716c;
    font-size: 11.5px;
}

.stopka {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 18px 56px;
    background: var(--ciemny);
    color: #c7bfb4;
    font-size: 12px;
}

.stopka strong { color: #faf7f2; }
.stopka a { color: #fdba74; text-decoration: none; }
.stopka a:hover { text-decoration: underline; }

@media (max-width: 900px) {
    .galeria { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 760px) {
    .naglowek { flex-wrap: wrap; padding: 16px 22px; }
    .naglowek-nota { display: none; }
    .wstep { padding: 34px 22px 26px; }
    .wstep h1 { font-size: 36px; }
    .wstep-dol { grid-template-columns: 1fr; }
    .liczby { flex-wrap: wrap; gap: 16px; }
    .galeria-sekcja { padding: 0 22px 34px; }
    .galeria-naglowek { align-items: flex-start; flex-direction: column; gap: 4px; }
    .galeria { grid-template-columns: 1fr; }
    .stopka { flex-direction: column; align-items: flex-start; padding: 18px 22px; }
}
Przed oddaniem sprawdź
  • Czy galeria ma dokładnie sześć kadrów i wszystkie cztery rodzaje obrazków?
  • Czy każdy obraz ma alt opisujący zdjęcie, a nie nazwę pliku?
  • Czy podpisy są widoczne bez hovera i czy hover nie zasłania treści?
  • Czy przy 900 px są dwie kolumny, a przy 360 px jedna?
  • Czy powiększony obraz nie wychodzi poza zaokrągloną kartę?

Zadanie 3 — Formularz zamówienia „Pod Lipą”

Herbaciarnia „Pod Lipą” przyjmuje zamówienia przez stronę internetową. Zadanie sprawdza formularz z różnymi typami pól, tabelę podsumowania oraz układ dwukolumnowy, który na telefonie zamienia się w jedną kolumnę. Zwróć uwagę na powiązanie etykiet z polami i spójność kwot.

Formularz zamówienia Pod Lipą: dane klienta, wybór herbaty, ilość, trzy opcje dostawy, checkbox regulaminu oraz ciemna tabela podsumowania po prawej
Formularz i podsumowanie w dwóch kolumnach. Tabela pokazuje produkt, cenę, ilość, dostawę i kwotę razem.

Wymagania do formularza zamówienia

  1. Dokument HTML5 z lang="pl", kodowaniem UTF-8, meta viewport i tytułem strony.
  2. Semantyka: header, main, section z formularzem, aside z podsumowaniem i footer. Strona ma jeden h1, a podsumowanie własny h2.
  3. Nagłówek: logo ze znakiem SVG, nazwą i podtytułem oraz informacja „Wysyłka w 24 godziny”.
  4. Układ: dwie kolumny — formularz i podsumowanie — z odstępem 32 px i wyrównaniem do góry. Strona ma maksymalnie 960 px szerokości, a klasy (zamowienie, podsumowanie, pole) opisują role elementów.
  5. Formularz podzielony na grupy fieldset z legend: „Dane klienta” oraz „Produkt i dostawa”.
  6. Dane klienta: imię i nazwisko, e-mail, telefon (opcjonalny) i miasto. Użyj typów text, email i tel oraz atrybutów autocomplete.
  7. Produkt: lista select z trzema herbatami oraz pole number z zakresem od 1 do 20 i wartością początkową 1.
  8. Dostawa: trzy pola radio w jednej grupie name="dostawa", z czego jedno jest zaznaczone domyślnie. Każde radio ma własną etykietę.
  9. Checkbox akceptacji regulaminu z atrybutem required oraz przycisk type="submit".
  10. Tabela podsumowania: caption, nagłówki wierszy th z scope="row" oraz wiersze: produkt, cena, ilość, dostawa i razem.
  11. Kwoty są spójne: herbata 32,00 zł, kurier 14,99 zł, razem 46,99 zł. Wartość „razem” jest wyróżniona kolorem i większym rozmiarem.
  12. Kolory: ciemna zieleń #1f3d2b, tło #f6f1e7 i akcent #b45309. Zapisz je jako zmienne CSS.
  13. Typografia: nagłówki Georgia, treść Segoe UI lub systemowa. Etykiety pól mają około 11.5 px, a kwota razem 16 px.
  14. Responsywność: poniżej 760 px układ przechodzi na jedną kolumnę, podsumowanie trafia pod formularz, a position: sticky jest wyłączone.
  15. Dostępność: każde pole ma label for, grupy mają legend, kontrolki mają widoczny :focus-visible, a tekst na ciemnym tle zachowuje kontrast.

Wskazówki do formularza zamówienia

Wskazówka 1 — grupuj pola, nie wszystko naraz

Podziel formularz na dwa zestawy fieldset: dane klienta oraz produkt z dostawą. Legenda każdej grupy jest jednocześnie krótkim opisem dla czytnika ekranu.

Wskazówka 2 — tabela to nie lista divów

Użyj table, tbody, th scope="row" i td. Kwoty wyrównaj do prawej, a wiersz „Razem” oddziel górną linią i zmień jego kolor.

Wskazówka 3 — sticky tylko na desktopie

Na szerokim ekranie podsumowanie może zostać przy górze dzięki position: sticky; top: 24px. W media query ustaw position: static, inaczej na telefonie karta będzie się dziwnie zachowywać podczas przewijania.

Rozwiązanie — formularz zamówienia

Pokaż pełne rozwiązanie

Kluczowe decyzje

  • Fieldset i legend: grupowanie pól nie jest tylko ozdobą — czytnik ekranu odczyta nazwę grupy przed każdym polem.
  • Grid 1.25fr .75fr: formularz dostaje więcej miejsca, a podsumowanie pozostaje wąską kartą. Na telefonie obie kolumny zamieniają się w jedną.
  • Tabela semantyczna: th scope="row" wiąże nazwę pozycji z kwotą, a caption opisuje całą tabelę. To ważne, gdy tabela jest czytana poza kontekstem strony.
  • Spójne dane: cena produktu i dostawy w formularzu odpowiadają wartościom w podsumowaniu. W prawdziwym sklepie te liczby liczyłby skrypt, tutaj są przykładem statycznym.
  • Radio i checkbox: każde pole ma własną etykietę, a wspólna nazwa name="dostawa" sprawia, że można wybrać tylko jedną opcję.

Zapisz kod jako index.html i style.css w jednym folderze. Formularz nie wysyła danych — atrybut action="#" jest celowym placeholderem.

HTML
<!doctype html>
<html lang="pl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Pod Lipą — formularz zamówienia</title>
  <link rel="stylesheet" href="style.css">
</head>
<body class="strona">
    <header class="naglowek">
        <a class="logo" href="#start">
            <svg class="logo-znak" viewBox="0 0 44 44" aria-hidden="true" focusable="false">
                <circle cx="22" cy="22" r="21" fill="#1f3d2b"/>
                <path d="M12 18h17v6a8.5 8.5 0 0 1-17 0Z" fill="#fde68a"/>
                <path d="M29 20h3a4 4 0 0 1 0 8h-3" fill="none" stroke="#fde68a" stroke-width="2"/>
                <path d="M17 13c0-2 2-2 2-4M22 13c0-2 2-2 2-4" fill="none" stroke="#d9f99d" stroke-width="1.8" stroke-linecap="round"/>
            </svg>
            <span>Pod Lipą<small>herbaciarnia</small></span>
        </a>
        <p class="naglowek-info">Wysyłka w 24 godziny</p>
    </header>

    <main class="uklad" id="start">
        <section class="zamowienie" aria-labelledby="zamowienie-tytul">
            <p class="etykieta">Zamówienie · krok 1 z 2</p>
            <h1 id="zamowienie-tytul">Złóż zamówienie</h1>
            <p class="zamowienie-lead">Wybierz herbatę i sposób dostawy. Dane potrzebne do wysyłki wpiszemy na kolejnym ekranie — tutaj przygotujemy tylko podsumowanie.</p>

            <form action="#" method="post">
                <fieldset>
                    <legend>Dane klienta</legend>
                    <div class="pola-dwa">
                        <div class="pole">
                            <label for="imie">Imię i nazwisko</label>
                            <input id="imie" name="imie" type="text" autocomplete="name" required>
                        </div>
                        <div class="pole">
                            <label for="email">Adres e-mail</label>
                            <input id="email" name="email" type="email" autocomplete="email" required>
                        </div>
                    </div>
                    <div class="pola-dwa">
                        <div class="pole">
                            <label for="telefon">Telefon (opcjonalnie)</label>
                            <input id="telefon" name="telefon" type="tel" autocomplete="tel">
                        </div>
                        <div class="pole">
                            <label for="miasto">Miasto dostawy</label>
                            <input id="miasto" name="miasto" type="text" autocomplete="address-level2" required>
                        </div>
                    </div>
                </fieldset>

                <fieldset>
                    <legend>Produkt i dostawa</legend>
                    <div class="pola-dwa">
                        <div class="pole">
                            <label for="produkt">Rodzaj herbaty</label>
                            <select id="produkt" name="produkt">
                                <option>Zielona „Łąka” — 32,00 zł</option>
                                <option>Czarna „Poranek” — 28,00 zł</option>
                                <option>Owocowa „Lato” — 26,00 zł</option>
                            </select>
                        </div>
                        <div class="pole">
                            <label for="ilosc">Ilość (opakowania)</label>
                            <input id="ilosc" name="ilosc" type="number" min="1" max="20" value="1" required>
                        </div>
                    </div>
                    <fieldset class="dostawa">
                        <legend>Dostawa</legend>
                        <label class="wybor"><input type="radio" name="dostawa" value="kurier" checked> Kurier — 14,99 zł</label>
                        <label class="wybor"><input type="radio" name="dostawa" value="paczkomat"> Paczkomat — 9,99 zł</label>
                        <label class="wybor"><input type="radio" name="dostawa" value="odbior"> Odbiór w sklepie — 0 zł</label>
                    </fieldset>
                </fieldset>

                <label class="zgoda">
                    <input type="checkbox" name="regulamin" required>
                    <span>Akceptuję regulamin sklepu i politykę prywatności.</span>
                </label>
                <button class="przycisk" type="submit">Zamawiam i płacę</button>
                <p class="zamowienie-nota">Płatność online lub przy odbiorze. Nie wysyłamy spamu.</p>
            </form>
        </section>

        <aside class="podsumowanie" aria-labelledby="podsumowanie-tytul">
            <h2 id="podsumowanie-tytul">Podsumowanie</h2>
            <table class="tabela">
                <caption>Podsumowanie zamówienia</caption>
                <tbody>
                    <tr>
                        <th scope="row">Produkt</th>
                        <td>Zielona „Łąka”</td>
                    </tr>
                    <tr>
                        <th scope="row">Cena za opakowanie</th>
                        <td>32,00 zł</td>
                    </tr>
                    <tr>
                        <th scope="row">Ilość</th>
                        <td>1 szt.</td>
                    </tr>
                    <tr>
                        <th scope="row">Dostawa</th>
                        <td>Kurier · 14,99 zł</td>
                    </tr>
                    <tr class="razem">
                        <th scope="row">Razem</th>
                        <td>46,99 zł</td>
                    </tr>
                </tbody>
            </table>
            <p class="podsumowanie-nota">Cena zawiera VAT. Próbkę herbaty dodajemy do każdego zamówienia bez dodatkowych kosztów.</p>
            <ul class="korzysci">
                <li>Świeżo pakowane w małych partiach</li>
                <li>14 dni na zwrot bez podania przyczyny</li>
                <li>Bezpłatna dostawa od 120 zł</li>
            </ul>
        </aside>
    </main>

    <footer class="stopka">
        <p><strong>Pod Lipą</strong> — herbaciarnia z Lublina</p>
        <p>© 2026 Pod Lipą</p>
        <p><a href="#start">Wróć na górę ↑</a></p>
    </footer>
</body>
</html>
CSS
* { box-sizing: border-box; }

body { margin: 0; }

:root {
    --zielen: #1f3d2b;
    --tlo: #f6f1e7;
    --akcent: #b45309;
    --tekst: #292524;
}

.strona {
    background: var(--tlo);
    color: var(--tekst);
    font: 16px/1.6 "Segoe UI", system-ui, -apple-system, sans-serif;
}

.strona h1,
.strona h2 {
    margin: 0;
    color: var(--zielen);
    font-family: Georgia, "Times New Roman", serif;
    line-height: 1.15;
}

.strona p { margin: 0; }
.strona a { color: inherit; }

.strona a:focus-visible,
.strona button:focus-visible,
.strona input:focus-visible,
.strona select:focus-visible {
    outline: 3px solid #f59e0b;
    outline-offset: 2px;
}

.naglowek {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 15px 56px;
    border-bottom: 1px solid #e4d9c6;
    background: #fffdf8;
}

.logo {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--zielen);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 23px;
    font-weight: 700;
    text-decoration: none;
}

.logo-znak { width: 42px; height: 42px; flex: 0 0 auto; }

.logo small {
    display: block;
    margin-top: 1px;
    color: #8a7a63;
    font-family: "Segoe UI", system-ui, sans-serif;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .2em;
    text-transform: uppercase;
}

.naglowek-info {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 13px;
    border-radius: 999px;
    background: #eef5e9;
    color: #3f6212;
    font-size: 11.5px;
    font-weight: 700;
}

.naglowek-info::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #65a30d;
}

.uklad {
    display: grid;
    grid-template-columns: 1.25fr .75fr;
    gap: 32px;
    align-items: start;
    padding: 36px 56px 44px;
}

.etykieta {
    margin: 0 0 8px;
    color: var(--akcent);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.zamowienie h1 { font-size: 38px; letter-spacing: -.02em; }

.zamowienie-lead {
    max-width: 52ch;
    margin: 10px 0 22px;
    color: #57534e;
    font-size: 14px;
}

fieldset { margin: 0 0 18px; padding: 0; border: 0; }

legend {
    width: 100%;
    margin-bottom: 9px;
    padding: 0 0 6px;
    border-bottom: 1px solid #e7ddcb;
    color: var(--zielen);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 17px;
    font-weight: 700;
}

.pola-dwa { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.pole { margin-bottom: 9px; }

.pole label {
    display: block;
    margin-bottom: 4px;
    color: #44403c;
    font-size: 11.5px;
    font-weight: 700;
}

.pole input,
.pole select {
    width: 100%;
    padding: 8px 11px;
    border: 1px solid #d8cbb5;
    border-radius: 8px;
    background: #fffdf8;
    color: #292524;
    font: inherit;
    font-size: 13px;
}

.pole input:focus,
.pole select:focus {
    border-color: #4d7c0f;
    outline: 2px solid #a3e635;
    outline-offset: 1px;
}

.dostawa {
    margin: 2px 0 0;
    padding: 8px 13px 6px;
    border: 1px solid #e3d8c4;
    border-radius: 10px;
    background: #fffdf9;
}

.dostawa legend {
    width: auto;
    margin: 0;
    padding: 0 4px;
    border: 0;
    color: #57534e;
    font-family: "Segoe UI", system-ui, sans-serif;
    font-size: 11.5px;
}

.wybor {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    color: #44403c;
    font-size: 12.5px;
    cursor: pointer;
}

.wybor input { accent-color: #1f3d2b; }

.zgoda {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 4px 0 12px;
    color: #57534e;
    font-size: 11px;
    line-height: 1.5;
}

.zgoda input { margin-top: 2px; accent-color: #1f3d2b; }

.przycisk {
    display: block;
    width: 100%;
    padding: 11px 20px;
    border: 0;
    border-radius: 999px;
    background: var(--zielen);
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}

.przycisk:hover { background: #2d5a3d; }

.zamowienie-nota {
    margin-top: 8px !important;
    color: #8a7a63;
    font-size: 10.5px;
    text-align: center;
}

.podsumowanie {
    position: sticky;
    top: 24px;
    padding: 22px;
    border-radius: 18px;
    background: var(--zielen);
    color: #e7efe2;
    box-shadow: 0 18px 34px rgba(31, 61, 43, .18);
}

.podsumowanie h2 { margin-bottom: 12px; color: #fff; font-size: 22px; }

.tabela { width: 100%; border-collapse: collapse; }

.tabela caption {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.tabela th,
.tabela td {
    padding: 8px 0;
    border-bottom: 1px solid rgba(255, 255, 255, .14);
    font-size: 12.5px;
    vertical-align: top;
}

.tabela th { color: #b9cdae; font-weight: 500; text-align: left; }
.tabela td { color: #fff; font-weight: 600; text-align: right; }

.tabela .razem th,
.tabela .razem td {
    padding-top: 13px;
    border-bottom: 0;
    color: #fde68a;
    font-size: 16px;
}

.tabela .razem th { font-family: Georgia, "Times New Roman", serif; font-weight: 700; }

.podsumowanie-nota {
    margin-top: 10px !important;
    color: #b9cdae;
    font-size: 10.5px;
    line-height: 1.5;
}

.korzysci {
    display: grid;
    gap: 6px;
    margin: 14px 0 0;
    padding: 12px 0 0;
    border-top: 1px solid rgba(255, 255, 255, .14);
    list-style: none;
}

.korzysci li {
    position: relative;
    padding-left: 18px;
    color: #d7e4cf;
    font-size: 11px;
    line-height: 1.45;
}

.korzysci li::before {
    content: "✓";
    position: absolute;
    left: 0;
    color: #a3e635;
    font-weight: 700;
}

.stopka {
    display: flex;
    justify-content: space-between;
    gap: 20px;
    padding: 15px 56px;
    border-top: 1px solid #e4d9c6;
    background: #fffdf8;
    color: #8a7a63;
    font-size: 11.5px;
}

.stopka strong { color: var(--zielen); }
.stopka a { color: var(--zielen); text-decoration: none; }
.stopka a:hover { text-decoration: underline; }

@media (max-width: 760px) {
    .naglowek { flex-wrap: wrap; padding: 14px 22px; }
    .naglowek-info { display: none; }
    .uklad { grid-template-columns: 1fr; padding: 28px 22px 34px; }
    .pola-dwa { grid-template-columns: 1fr; gap: 0; }
    .podsumowanie { position: static; }
    .stopka { flex-direction: column; padding: 15px 22px; }
}
Przed oddaniem sprawdź
  • Czy każde pole ma label powiązany przez for i id oraz czy grupy mają legendę?
  • Czy radio mają wspólną nazwę i czy tylko jedno jest zaznaczone na start?
  • Czy kwoty w formularzu zgadzają się z tabelą podsumowania?
  • Czy przy 360 px podsumowanie jest pod formularzem i nie jest przyklejone do ekranu?
  • Czy checkbox regulaminu jest wymagany, a przycisk ma type="submit"?