Przejdź do głównej treści
INF.03-09-26.01-SGStyczeń 2026 · 47 kroków · ok. 87 min · 39 kryteriów z klucza

Rozwiązanie krok po kroku: Witryna salonu stylizacji paznokci (Nowoczesny kod (grid, JS))

To drugi sposób rozwiązania tego samego arkusza: salon stylizacji paznokci z bazą paznokcie, grafiką pięciu butelek lakieru i stroną paznokcie.html z trzema zakładkami przełączanymi po najechaniu kursorem oraz galerią dziesięciu wzorów. Obie wersje spełniają wszystkie 39 kryteriów klucza - różni je sposób pisania kodu, nie wynik.

Czym ta wersja różni się od podstawowej:

  • siatka CSS zamiast flex: grid-template-columns: 20% 80% na <body>, a kolory zakładek w zmiennych CSS,
  • stan zakładek w klasie active: o kolorach i widoczności decyduje arkusz stylów, a skrypt tylko przenosi klasę - nie wpisuje stylów w style="",
  • przycisk wskazuje swoją sekcję atrybutem aria-controls zamiast numeru doklejanego do identyfikatora,
  • oba skrypty w pliku skrypt.js z atrybutem defer, zdarzenia przez addEventListener (mouseenter i focus - działa też klawisz Tab),
  • wzory tworzone przez createElement z tekstem alternatywnym, pola formularza z opisem aria-label,
  • zapytanie 2 z przedziałem dat zamiast funkcji na kolumnie, zapytanie 3 z aliasami.

Kroki nadal idą zdanie po zdaniu za treścią arkusza. Każda wersja skryptu była uruchomiona w przeglądarce Chrome z symulowanym najechaniem kursorem i przejściem klawiszem Tab po każdym przycisku; w podglądzie najedź kursorem na „Kształt” albo „Wzór”. Baza i grafiki pochodzą z prawdziwego archiwum pliki15 (załącznik do arkusza, hasło w treści zadania).

Jak liczą się punkty. Klucz ma 39 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 30 punktów. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 39 kryteriów (pkt)

    Krok 1: Baza danych paznokcie

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie paznokcie, z zestawem polskich znaków (np. utf8_polish_ci)

    Archiwum pliki15.7z ma hasło P@znoKcie? (małpa zamiast „a”, pytajnik na końcu); w środku paznokcie.sql, manicure.jpg, kolory.png, ksztalt.png i wzory 1.jpg - 10.jpg. W phpMyAdmin: Nowa, nazwa paznokcie, porównywanie utf8_polish_ci, albo w zakładce SQL:

    CREATE DATABASE paznokcie CHARACTER SET utf8 COLLATE utf8_polish_ci;
    
  2. Krok 2: Import tabel z pliku paznokcie.sql

    ok. 2 min
    Polecenie z arkusza

    Z rozpakowanego archiwum zaimportuj tabele z pliku paznokcie.sql do utworzonej bazy

    Zaznacz bazę paznokcie, potem Import → paznokcie.sql → Wykonaj. Powstają trzy tabele z ilustracji 1: klienci (klucze obce ksztalty_id i wzory_id, pole topKlient - 1 dla ważnego klienta, termin z datą i godziną), ksztalty i wzory.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabel do bazy danych paznokcie - obraz import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel

    Print Screen (cały ekran z paskiem zadań), wklej do edytora grafiki i zapisz jako import.png. Wszystkie zrzuty w tym arkuszu są w formacie PNG.

    Typowe błędy

    Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).

  4. Krok 4: Zapytanie 1: ważni klienci

    Kryteria: ,

    R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonane zapytanie 1 wybierające jedynie imię, kolor i cenę tylko dla ważnych klientów. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT imie, kolor, cena FROM klienci WHERE topKlient = 1; oraz na zrzucie widocznych jest dokładnie 6 wierszy z imionami: Anna, Monika, Ewelina, Joanna, Małgorzata i Jagna

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie imię, kolor i cenę tylko dla ważnych klientów

    • SELECT imie, kolor, cena - trzy pola,
    • FROM klienci,
    • WHERE topKlient = 1 - ważny klient to wartość 1 (opis pod ilustracją 1).

    Wynik: sześć wierszy - Anna, Monika, Ewelina, Joanna, Małgorzata, Jagna. Każda klauzula w osobnej linii - SQL nie zwraca uwagi na znaki nowej linii. Zapisz w kwerendy.txt, zrzut jako kw1.png.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT imie, kolor, cena
    FROM klienci
    WHERE topKlient = 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: klienci umówieni na 23 maja

    Kryteria:

    R.1.4 Wykonane zapytanie 2 wybierające jedynie imię i cenę dla klientów umówionych na dzień 2024-05-23. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT imie, cena FROM klienci WHERE termin LIKE "2024-05-23%"; (termin = "2024-05-23" jest błędem ) oraz na zrzucie widocznych jest dokładnie 6 wierszy z imionami: Marta, Agnieszka, Zuza, Roma, Małgorzata, Jagna

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 2: wybierające jedynie imię i cenę dla klientów umówionych na dzień 2024-05-23

    Pole termin przechowuje datę z godziną (2024-05-23 12:00:00). Cały dzień 23 maja to przedział: od północy 23 maja włącznie (>= '2024-05-23') do północy 24 maja wyłącznie (< '2024-05-24').

    Wersja podstawowa pisze DATE(termin) = '2024-05-23', a klucz podaje termin LIKE '2024-05-23%' - wszystkie trzy dają ten sam wynik: Marta, Agnieszka, Zuza, Roma, Małgorzata, Jagna. Przedział ma jedną przewagę: porównuje samą kolumnę, bez funkcji na niej, więc baza może użyć indeksu na termin. Przy dziesiątkach wierszy to bez znaczenia, przy milionach rezerwacji - duże. Zrzut: kw2.png.

    Typowe błędy

    WHERE termin = '2024-05-23' porównuje z północą tego dnia i zwraca 0 wierszy - klucz wprost nazywa ten zapis błędem. <= '2024-05-24' zamiast < dołączyłby wizytę o północy 24 maja.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT imie, kolor, cena
    FROM klienci
    WHERE topKlient = 1;
    
    -- Zapytanie 2
    SELECT imie, cena
    FROM klienci
    WHERE termin >= '2024-05-23' AND termin < '2024-05-24';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: klienci z kształtem „migdał”

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające jedynie imię i kolor z tabeli klienci oraz odpowiadającą im nazwę kształtu z tabeli ksztalty dla kształtu „migdał”. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT imie, kolor, ksztalt FROM klienci JOIN ksztalty ON ksztalty_id = ksztalty.id WHERE ksztalt = "migdał"; (lub porównanie kluczy po WHERE ) oraz na zrzucie widocznych jest dokładnie 5 wierszy z imionami: Urszula, Anna, Ewa, Monika, Sylwia

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie imię i kolor z tabeli klienci oraz odpowiadającą im nazwę kształtu z tabeli ksztalty dla kształtu „migdał”. Należy posłużyć się relacją

    • FROM klienci AS k JOIN ksztalty AS s - aliasy tabel (s od „shape”, bo k zajęli klienci),
    • ON s.id = k.ksztalty_id - relacja: kształt wybrany przez klienta,
    • WHERE s.ksztalt = 'migdał' - warunek na nazwie kształtu, jak w poleceniu,
    • SELECT k.imie, k.kolor, s.ksztalt - każde pole z prefiksem swojej tabeli.

    Wynik: pięć wierszy - Urszula, Anna, Ewa, Monika, Sylwia. Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT imie, kolor, cena
    FROM klienci
    WHERE topKlient = 1;
    
    -- Zapytanie 2
    SELECT imie, cena
    FROM klienci
    WHERE termin >= '2024-05-23' AND termin < '2024-05-24';
    
    -- Zapytanie 3
    SELECT k.imie, k.kolor, s.ksztalt
    FROM klienci AS k
    JOIN ksztalty AS s ON s.id = k.ksztalty_id
    WHERE s.ksztalt = 'migdał';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: nowa kolumna doplata

    Kryteria:

    R.1.6 Wykonane zapytanie 4 modyfikujące strukturę tabeli wzory , poprzez dodanie kolumny o nazwie doplata, dowolnego typu całkowitego. W pliku z kwerendami lub na zrzucie istnieje zapis np. ALTER TABLE wzory ADD COLUMN doplata INT; (dowolny typ całkowity, COLUMN opcjonalne ) oraz na zrzucie widoczny jest komunikat o poprawnie wykonanym zapytaniu lub zmieniona struktura tabeli

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: modyfikujące strukturę tabeli wzory, poprzez dodanie kolumny o nazwie doplata, dowolnego typu całkowitego

    Strukturę tabeli zmienia ALTER TABLE (a nie UPDATE, który zmienia dane): ADD COLUMN doplata INT dopisuje kolumnę typu całkowitego (R.1.6). Dopisek NOT NULL DEFAULT 0 ustala od razu wartość dla istniejących wzorów: dopłata 0 zamiast NULL. Dopłata to kwota - cena + doplata z NULL daje NULL, a z zerem zwykłą cenę.

    Zapytanie niczego nie wyświetla - na zrzucie kw4.png komunikat o wykonaniu albo zakładka Struktura z nową kolumną.

    kwerendy.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT imie, kolor, cena
    FROM klienci
    WHERE topKlient = 1;
    
    -- Zapytanie 2
    SELECT imie, cena
    FROM klienci
    WHERE termin >= '2024-05-23' AND termin < '2024-05-24';
    
    -- Zapytanie 3
    SELECT k.imie, k.kolor, s.ksztalt
    FROM klienci AS k
    JOIN ksztalty AS s ON s.id = k.ksztalty_id
    WHERE s.ksztalt = 'migdał';
    
    -- Zapytanie 4
    ALTER TABLE wzory
    ADD COLUMN doplata INT NOT NULL DEFAULT 0;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-28 · po tym etapie masz 19 z 39 kryteriów (pkt)

    Krok 8: Grafika kolory.png: kadr do butelek

    ok. 3 min
    Polecenie z arkusza

    Cechy grafiki kolory.png (ilustracja 3): Grafikę należy skadrować tak, aby były widoczne jedynie butelki lakierów do paznokci. Grafikę należy przyciąć dokładnie do kształtów butelek.

    Grafika jest taka sama w obu wersjach. kolory.png ma przezroczyste tło i trzy rzędy kosmetyków - butelki lakieru są w dolnym. W GIMP-ie zaznacz dolny rząd prostokątem z zapasem, Obraz → Przytnij do zaznaczenia, potem Obraz → Przytnij do zawartości - krawędzie dosuną się do butelek. Kadr: 566 × 182 px.

  9. Krok 9: Grafika kolory.png: wysokość 70 px

    Kryteria:

    R.2.1 Grafika kolory.png przedstawia jedynie 5 butelek z lakierami. Jest przycięta do wszystkich krawędzi (sprawdzić bez powiększania obrazu ). Jej wysokość to 70 px

    ok. 2 min
    Polecenie z arkusza

    Grafikę należy przeskalować z zachowaniem proporcji do wysokości 70 px

    Obraz → Skaluj obraz, łańcuch zamknięty, wysokość 70 px - szerokość wychodzi sama: 218 px. Eksport do PNG, żeby zostało przezroczyste tło (R.2.1).

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Plik paznokcie.html w HTML5

    ok. 2 min
    Polecenie z arkusza

    Nazwa pliku paznokcie w formacie HTML lub PHP w zależności od implementacji skryptów. Zapisana w języku HTML5

    Oba skrypty będą w JavaScripcie, więc plik ma rozszerzenie .html i działa bez serwera. Na początek <!DOCTYPE html> i szkielet.

    paznokcie.html HTML nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  11. Krok 11: Język strony

    Kryteria:

    R.2.2 W pliku paznokcie znajduje się deklaracja HTML5 <!DOCTYPE HTML> i deklaracja języka zawartości witryny: polski np. <html lang="pl">

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny

    Atrybut lang="pl" - razem z deklaracją HTML5 to jedno kryterium.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  12. Krok 12: Kodowanie polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head>.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  13. Krok 13: Tytuł strony

    Kryteria:

    R.2.3 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków i tytuł strony "Stylizacja paznokci"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Stylizacja paznokci"

    <title> w <head>. Kodowanie i tytuł to razem jedno kryterium.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  14. Krok 14: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony

    Plik styl.css. Całe formatowanie pochodzi z tego pliku - także zmiany po najechaniu kursorem: skrypt nie będzie wpisywał stylów do HTML-u.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  15. Krok 15: Bloki: boczny i główny z nagłówkiem, menu, trzema sekcjami i stopką

    Kryteria:

    R.2.4 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: aside, main->header+nav+section+section+section, footer (dopuszcza się zastosowanie bloków pomocniczych, poprawne również gdy stopka znajduje się w bloku main )

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 4

    Po lewej <aside>, po prawej <main> z nagłówkiem, menu, trzema sekcjami i stopką - klucz uznaje stopkę w bloku głównym (R.2.4). Sekcje dostają identyfikatory mówiące, co zawierają: color, shape, pattern (zamiast section1 - section3).

    Pierwsza sekcja ma od razu klasę active - to stan „ta zakładka jest otwarta”. W CSS klasa zdecyduje o widoczności, a skrypt będzie ją tylko przenosił między sekcjami.

    paznokcie.html HTML zmienione: 16 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
        </aside>
        <main>
            <header>
            </header>
            <nav>
            </nav>
            <section id="color" class="active">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  16. Krok 16: Blok boczny: zdjęcie

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku bocznego: Obraz manicure.jpg z tekstem alternatywnym „Stylizacja paznokci”

    <img> z atrybutem alt, bez ukośnika na końcu (HTML5).

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
            </header>
            <nav>
            </nav>
            <section id="color" class="active">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  17. Krok 17: Nagłówek strony

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku głównego: blok nagłówkowy, blok nawigacyjny, bloki: sekcja 1, sekcja 2, sekcja 3 (w jednym momencie tylko jedna sekcja jest widoczna). Zawartość bloku nagłówkowego: Nagłówek pierwszego stopnia o treści „Twoje wymarzone paznokcie”

    <h1> w bloku nagłówkowym.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
            </nav>
            <section id="color" class="active">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  18. Krok 18: Przycisk „Kolor”

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku nawigacyjnego: Przycisk o treści „Kolor”

    <button> z trzema atrybutami:

    • type="button" - zwykły przycisk; bez tego przycisk w formularzu wysyła formularz (domyślny typ to submit),
    • aria-controls="color" - identyfikator sekcji, którą przycisk pokazuje. Czytnik ekranu wie, czym przycisk steruje, a skrypt odczyta z tego atrybutu, którą sekcję otworzyć - bez numerów doklejanych do identyfikatorów,
    • class="active" - tak jak pierwsza sekcja: ta zakładka jest otwarta na starcie.
    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
            </nav>
            <section id="color" class="active">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  19. Krok 19: Przycisk „Kształt”

    ok. 1 min
    Polecenie z arkusza

    Przycisk o treści „Kształt”

    Drugi przycisk wskazuje sekcję shape, bez klasy active.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
            </nav>
            <section id="color" class="active">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  20. Krok 20: Przycisk „Wzór”

    Kryteria:

    R.2.7 W bloku nawigacyjnym znajdują się trzy przyciski: "Kolor", "Kształt" i "Wzór"

    ok. 1 min
    Polecenie z arkusza

    Przycisk o treści „Wzór”

    Trzeci przycisk, sekcja pattern. Komplet trzech przycisków w bloku nawigacyjnym (R.2.7).

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  21. Krok 21: Sekcja 1: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcja 1: Nagłówek drugiego stopnia o treści „Kolor”

    <h2> w sekcji color.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  22. Krok 22: Sekcja 1: butelki lakierów

    Kryteria:

    R.2.6 W bloku bocznym znajduje się obraz manicure.jpg z tekstem alternatywnym "Stylizacja paznokci", oraz w blokach sekcji przynajmniej jeden obraz z kolorami, alt = "Kolory paznokci" lub ksztalt.png , alt = "Kształty paznokci"

    ok. 1 min
    Polecenie z arkusza

    Obraz kolory.png z tekstem alternatywnym „Kolory paznokci”

    Grafika przygotowana na początku. Są już oba obrazy z kryterium R.2.6.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  23. Krok 23: Sekcja 1: pole wyboru koloru

    Kryteria: ,

    R.2.8 W blokach sekcji znajduje się przynajmniej jedno pole edycyjne

    R.3.4 W bloku sekcji 1 pole input jest typu color oraz zastosowany atrybut value="#FF0000"

    ok. 2 min
    Polecenie z arkusza

    Poniżej pole edycyjne pozwalające wybrać kolor, wartość początkowa pola: #FF0000 (ilustracja 5)

    Pole type="color" z wartością początkową value="#FF0000" (czerwony; R.2.8, R.3.4). „Poniżej” obrazu: pole stoi w <div> - element blokowy zawsze zaczyna nowy wiersz, więc nie potrzeba <br>, który tylko łamie linię i nic nie znaczy.

    Pole nie ma widocznej etykiety (arkusz jej nie przewiduje), więc dostaje aria-label="Kolor lakieru" - czytnik ekranu przeczyta ten opis zamiast samego „pole koloru”.

    paznokcie.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  24. Krok 24: Sekcja 2: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcja 2: Nagłówek drugiego stopnia o treści „Kształt”

    <h2> w sekcji shape.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
                <h2>Kształt</h2>
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  25. Krok 25: Sekcja 2: kształty paznokci

    ok. 1 min
    Polecenie z arkusza

    Obraz ksztalt.png z tekstem alternatywnym „Kształty paznokci”

    Grafika z archiwum bez zmian - ma 70 px wysokości jak butelki.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
                <h2>Kształt</h2>
                <img src="ksztalt.png" alt="Kształty paznokci">
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  26. Krok 26: Sekcja 2: lista kształtów

    Kryteria:

    R.2.9 Zdefiniowana jest jedna lista rozwijana z 5 opcjami, użyte znaczniki <select> i <option>

    ok. 2 min
    Polecenie z arkusza

    Poniżej pole listy rozwijanej z opcjami: „migdał”, „zaokrąglony”, „kwadratowy”, „balerina”, „zaokrąglony kwadrat”

    <select> z pięcioma <option> w kolejności z arkusza (R.2.9), w <div> pod obrazem i z opisem aria-label. Opcje bez atrybutu value wysłałyby swój tekst - na tej stronie nic ich nie wysyła. Lista jest wpisana w HTML-u: w tabeli ksztalty nie ma „zaokrąglonego kwadratu”.

    paznokcie.html HTML zmienione: 9 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
                <h2>Kształt</h2>
                <img src="ksztalt.png" alt="Kształty paznokci">
                <div>
                    <select aria-label="Kształt paznokci">
                        <option>migdał</option>
                        <option>zaokrąglony</option>
                        <option>kwadratowy</option>
                        <option>balerina</option>
                        <option>zaokrąglony kwadrat</option>
                    </select>
                </div>
            </section>
            <section id="pattern">
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  27. Krok 27: Sekcja 3: nagłówek, miejsce na wzory i pole liczbowe

    Kryteria:

    R.3.5 W bloku sekcji 3 pole input jest typu number oraz zastosowane atrybuty min=1 i max=10

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku sekcja 3: Nagłówek drugiego stopnia o treści „Wzór”. Efekt działania skryptu 1. Poniżej pole edycyjne przeznaczone do wpisywania wartości całkowitych jedynie od 1 do 10

    Pod nagłówkiem pusty <div id="patterns"> - tam skrypt 1 wstawi dziesięć wzorów. Pod nim pole type="number" z min="1" i max="10" (R.3.5); krok domyślny to 1, więc pole przyjmuje liczby całkowite. Opis aria-label="Numer wzoru" mówi, co wpisać.

    paznokcie.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
                <h2>Kształt</h2>
                <img src="ksztalt.png" alt="Kształty paznokci">
                <div>
                    <select aria-label="Kształt paznokci">
                        <option>migdał</option>
                        <option>zaokrąglony</option>
                        <option>kwadratowy</option>
                        <option>balerina</option>
                        <option>zaokrąglony kwadrat</option>
                    </select>
                </div>
            </section>
            <section id="pattern">
                <h2>Wzór</h2>
                <div id="patterns"></div>
                <div>
                    <input type="number" min="1" max="10" aria-label="Numer wzoru">
                </div>
            </section>
            <footer>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  28. Krok 28: Stopka z wyróżnionym autorem

    Kryteria: ,

    R.2.5 W bloku nagłówkowym znajduje się <h1> "Twoje wymarzone paznokcie", w blokach sekcji przynajmniej jeden <h2>: "Kolor", "Kształt" lub "Wzór", w stopce <p> z numerem zdającego

    R.2.10 Numer zdającego formatowany jest znacznikiem <em>

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku stopki: Paragraf o treści „Autor strony: ”, dalej wstawiony numer zdającego. Numer zdającego jest zapisany za pomocą znacznika semantycznego oznaczającego tekst uwypuklony, formatowany domyślnie jako pochylony

    Tekst uwypuklony to <em> - przeglądarka pisze go kursywą (R.2.10); <i> też pochyla, ale nie niesie znaczenia. Na egzaminie w <em> wpisujesz swój numer zdającego (PESEL) - tu stoi imię i nazwisko autora rozwiązania. Komplet nagłówków i akapitów z klucza (R.2.5).

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
                <h2>Kształt</h2>
                <img src="ksztalt.png" alt="Kształty paznokci">
                <div>
                    <select aria-label="Kształt paznokci">
                        <option>migdał</option>
                        <option>zaokrąglony</option>
                        <option>kwadratowy</option>
                        <option>balerina</option>
                        <option>zaokrąglony kwadrat</option>
                    </select>
                </div>
            </section>
            <section id="pattern">
                <h2>Wzór</h2>
                <div id="patterns"></div>
                <div>
                    <input type="number" min="1" max="10" aria-label="Numer wzoru">
                </div>
            </section>
            <footer>
                <p>Autor strony: <em>Bartosz Bryniarski</em></p>
            </footer>
        </main>
    </body>
    </html>
    Podgląd strony po tym kroku (paznokcie.html)
  29. Etap 3: Styl CSS

    Kroki 29-38 · po tym etapie masz 30 z 39 kryteriów (pkt)

    Krok 29: Plik styl.css: kolory zakładek i krój czcionki

    Kryteria:

    R.4.1 domyślne formatowanie selektorów (*): krój czcionki "Trebuchet MS", sans-serif (dozwolona tylko taka kolejność )

    ok. 2 min
    Polecenie z arkusza

    Domyślnie, dla wszystkich selektorów: krój czcionki Trebuchet MS, w przypadku braku sans-serif

    Kolory arkusza dostają zmienne CSS nazwane według roli: --active-tab (Salmon) - otwarta zakładka i jej sekcja, --inactive-tab (Crimson) - pozostałe przyciski. Z nazwy widać, dlaczego przycisk i sekcja mają ten sam kolor: otwarty przycisk „zlewa się” ze swoją sekcją.

    Reguła *: krój ze spacją w cudzysłowie i rodzina zapasowa sans-serif na końcu (R.4.1).

    styl.css CSS nowy plik
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  30. Krok 30: Ciało strony: tło i wyrównanie

    ok. 1 min
    Polecenie z arkusza

    Dla ciała strony: kolor tła BlanchedAlmond, wyrównanie tekstu do środka

    Nazwy kolorów CSS można pisać dowolną wielkością liter.

    styl.css CSS zmienione: 5 linii
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  31. Krok 31: Blok boczny i główny: kolumny 20% i 80%

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 4 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position, bloki sekcji nie są uwzględniane, stopka może być w bloku main lub poza nim)

    ok. 2 min
    Polecenie z arkusza

    Dla bloku bocznego: szerokość 20%. Dla bloku głównego: szerokość 80%

    <body> staje się siatką o kolumnach 20% 80%: <aside> trafia do pierwszej, <main> do drugiej - stoją obok siebie, a szerokości wynikają z kolumn (klucz dopuszcza grid-template-columns). Nagłówek, menu, sekcje i stopka i tak leżą jedna pod drugą wewnątrz <main> - układ z ilustracji 4 (R.3.1).

    styl.css CSS zmienione: 2 linie
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  32. Krok 32: Zdjęcie na całą szerokość bloku bocznego

    Kryteria:

    R.4.8 styl jedynie dla obrazu w bloku bocznym: szerokość 100%

    ok. 1 min
    Polecenie z arkusza

    Jedynie dla obrazu w bloku bocznym: szerokość 100%

    „Jedynie w bloku bocznym” to selektor potomka aside img - obrazy w sekcjach zostają w swoim rozmiarze (R.4.8).

    styl.css CSS zmienione: 4 linie
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  33. Krok 33: Blok nawigacyjny

    Kryteria:

    R.4.5 wyrównanie tekstu: dla ciała strony do środka, blok nawigacyjny do lewej strony

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nawigacyjnego: wyrównanie tekstu do lewej strony, jedynie margines zewnętrzny lewy 10%

    text-align: left nadpisuje środkowanie z body; „jedynie lewy” to margin-left (R.4.5).

    styl.css CSS zmienione: 5 linii
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    
    nav {
        text-align: left;
        margin-left: 10%;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  34. Krok 34: Trzy sekcje: tło, marginesy i wysokość

    Kryteria:

    R.4.6 marginesy wewnętrzne (padding ): bloki sekcji - 10px margines zewnętrzny lewy (margin-left ): blok nawigacyjny, bloki sekcji - 10%

    ok. 2 min
    Polecenie z arkusza

    Dla trzech bloków sekcji: kolor tła Salmon, jedynie margines zewnętrzny lewy 10%, marginesy wewnętrzne 10 px, wysokość 250 px

    Tło ze zmiennej --active-tab. Ten sam lewy margines co w menu - przyciski i sekcja zaczynają się w jednej linii (R.4.6).

    styl.css CSS zmienione: 7 linii
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    
    nav {
        text-align: left;
        margin-left: 10%;
    }
    
    section {
        background-color: var(--active-tab);
        margin-left: 10%;
        padding: 10px;
        height: 250px;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  35. Krok 35: Widoczna tylko sekcja z klasą active

    Kryteria:

    R.4.9 sposób wyświetlania: pierwszy blok sekcji display: block; pozostałe display: none; (visibility jest błędem )

    ok. 2 min
    Polecenie z arkusza

    Dodatkowo blok sekcji 1 jest wyświetlany w sposób blokowy, natomiast bloki sekcji 2 i 3 są usunięte z układu

    Domyślnie każda sekcja jest usunięta z układu (display: none w regule section), a sekcja z klasą active - wyświetlana blokowo (display: block). Selektor section.active jest bardziej szczegółowy niż samo section, więc wygrywa. Na starcie klasę ma tylko pierwsza sekcja: w inspektorze sekcja 1 ma block, sekcje 2 i 3 - none (R.4.9).

    Reguły nie wiedzą nic o numerach sekcji - otwarcie innej zakładki to tylko przeniesienie klasy.

    Typowe błędy

    visibility: hidden tylko ukrywa element i zostawia po nim puste miejsce - klucz wprost uznaje to za błąd.

    styl.css CSS zmienione: 5 linii
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    
    nav {
        text-align: left;
        margin-left: 10%;
    }
    
    section {
        background-color: var(--active-tab);
        margin-left: 10%;
        padding: 10px;
        height: 250px;
        display: none;
    }
    
    section.active {
        display: block;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  36. Krok 36: Przyciski: szerokość, czcionka, tło, bez obramowania

    Kryteria: , ,

    R.4.3 kolor czcionki: przyciski - biały

    R.4.4 wysokość: bloki sekcji - 250px szerokość: blok boczny 20%, blok główny 80% (width lub grid-template-columns lub flex ), przycisk 26%

    R.4.7 styl przycisków: brak obramowania, np. border: none, rozmiar czcionki 200%

    ok. 2 min
    Polecenie z arkusza

    Dla przycisków: szerokość 26%, biały kolor czcionki, brak obramowania, rozmiar czcionki 200%

    border: none usuwa ramkę przycisku z przeglądarki. Od razu też tło --inactive-tab - biały tekst na domyślnym szarym tle byłby słabo widoczny (R.4.3, R.4.4, R.4.7).

    styl.css CSS zmienione: 8 linii
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    
    nav {
        text-align: left;
        margin-left: 10%;
    }
    
    section {
        background-color: var(--active-tab);
        margin-left: 10%;
        padding: 10px;
        height: 250px;
        display: none;
    }
    
    section.active {
        display: block;
    }
    
    button {
        width: 26%;
        color: white;
        border: none;
        font-size: 200%;
        background-color: var(--inactive-tab);
    }
    Podgląd strony po tym kroku (paznokcie.html)
  37. Krok 37: Kolor otwartej zakładki

    Kryteria:

    R.4.2 kolor tła: dla ciała strony BlanchedAlmond, bloki sekcji, pierwszy przycisk - Salmon, drugi i trzeci przycisk - Crimson

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla pierwszego przycisku kolor tła Salmon, dla pozostałych – Crimson

    Wszystkie przyciski mają Crimson z poprzedniej reguły, a przycisk z klasą active - Salmon. Na starcie klasę ma „Kolor”, więc pierwszy przycisk jest Salmon, pozostałe Crimson (R.4.2).

    styl.css CSS zmienione: 4 linie
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    
    nav {
        text-align: left;
        margin-left: 10%;
    }
    
    section {
        background-color: var(--active-tab);
        margin-left: 10%;
        padding: 10px;
        height: 250px;
        display: none;
    }
    
    section.active {
        display: block;
    }
    
    button {
        width: 26%;
        color: white;
        border: none;
        font-size: 200%;
        background-color: var(--inactive-tab);
    }
    
    button.active {
        background-color: var(--active-tab);
    }
    Podgląd strony po tym kroku (paznokcie.html)
  38. Krok 38: Klasa wzory: okrągłe miniatury

    Kryteria:

    R.4.10 styl klasy .wzory : szerokość 70px, marginesy zewnętrzne (margin ) 5px, zaokrąglenie rogów 100%

    ok. 1 min
    Polecenie z arkusza

    Dla klasy wzory: szerokość 70 px, marginesy zewnętrzne 5 px, zaokrąglenie rogów 100%

    Kwadratowe wzory po border-radius: 100% (wystarczy też 50%) stają się kołami, jak na ilustracji 6. Klasę nada im skrypt 1 (R.4.10).

    styl.css CSS zmienione: 6 linii
    :root {
        --active-tab: Salmon;
        --inactive-tab: Crimson;
    }
    
    * {
        font-family: "Trebuchet MS", sans-serif;
    }
    
    body {
        background-color: BlanchedAlmond;
        text-align: center;
        display: grid;
        grid-template-columns: 20% 80%;
    }
    
    aside img {
        width: 100%;
    }
    
    nav {
        text-align: left;
        margin-left: 10%;
    }
    
    section {
        background-color: var(--active-tab);
        margin-left: 10%;
        padding: 10px;
        height: 250px;
        display: none;
    }
    
    section.active {
        display: block;
    }
    
    button {
        width: 26%;
        color: white;
        border: none;
        font-size: 200%;
        background-color: var(--inactive-tab);
    }
    
    button.active {
        background-color: var(--active-tab);
    }
    
    .wzory {
        width: 70px;
        margin: 5px;
        border-radius: 100%;
    }
    Podgląd strony po tym kroku (paznokcie.html)
  39. Etap 4: JavaScript

    Kroki 39-44 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 39: Skrypt 2: plik skrypt.js i zdarzenie mouseenter

    Kryteria:

    R.3.3 Zdefiniowane dla przynajmniej jednego przycisku zdarzenie onmouseover, które uruchamia funkcję skryptu (obsługa zdarzenia zdefiniowana w HTML np. onmouseover=... lub w skrypcie np. addEventListener element.mouseover = … lub element.addEventListener("mouseover", (event) => {});) (lub zdarzenia focus, focusin, mouseenter )

    ok. 3 min
    Polecenie z arkusza

    Zdarzenie najechania kursorem myszy na dowolny przycisk uruchamia skrypt 2. Skrypt 2: Wykonywany po stronie klienta, po najechaniu kursorem na przycisk

    Oba skrypty trafią do pliku skrypt.js, dołączonego w <head> z atrybutem defer: przeglądarka pobiera plik równolegle, ale uruchamia go dopiero po wczytaniu całego HTML-u - przyciski i sekcje już istnieją, gdy skrypt ich szuka.

    querySelectorAll('nav button') zbiera trzy przyciski, a pętla for...of przypina każdemu obsługę zdarzenia mouseenter przez addEventListener (R.3.3). Funkcja strzałkowa () => showSection(button) przekazuje do funkcji przycisk, który zdarzenie wywołał. mouseenter to najechanie kursorem jak onmouseover z tabeli 1, ale wywołuje się raz przy wejściu na element, a nie przy każdym ruchu nad jego fragmentami. Funkcja showSection jest na razie pusta.

    paznokcie.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Stylizacja paznokci</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <aside>
            <img src="manicure.jpg" alt="Stylizacja paznokci">
        </aside>
        <main>
            <header>
                <h1>Twoje wymarzone paznokcie</h1>
            </header>
            <nav>
                <button type="button" class="active" aria-controls="color">Kolor</button>
                <button type="button" aria-controls="shape">Kształt</button>
                <button type="button" aria-controls="pattern">Wzór</button>
            </nav>
            <section id="color" class="active">
                <h2>Kolor</h2>
                <img src="kolory.png" alt="Kolory paznokci">
                <div>
                    <input type="color" value="#FF0000" aria-label="Kolor lakieru">
                </div>
            </section>
            <section id="shape">
                <h2>Kształt</h2>
                <img src="ksztalt.png" alt="Kształty paznokci">
                <div>
                    <select aria-label="Kształt paznokci">
                        <option>migdał</option>
                        <option>zaokrąglony</option>
                        <option>kwadratowy</option>
                        <option>balerina</option>
                        <option>zaokrąglony kwadrat</option>
                    </select>
                </div>
            </section>
            <section id="pattern">
                <h2>Wzór</h2>
                <div id="patterns"></div>
                <div>
                    <input type="number" min="1" max="10" aria-label="Numer wzoru">
                </div>
            </section>
            <footer>
                <p>Autor strony: <em>Bartosz Bryniarski</em></p>
            </footer>
        </main>
    </body>
    </html>
    skrypt.js JavaScript nowy plik
    // Skrypt 2: zakładki przełączane po najechaniu kursorem
    const tabButtons = document.querySelectorAll('nav button');
    
    function showSection(selectedButton) {
    }
    
    for (const button of tabButtons) {
        button.addEventListener('mouseenter', () => showSection(button));
    }
    Podgląd strony po tym kroku (paznokcie.html)
  40. Krok 40: Skrypt 2: wybrana sekcja widoczna, pozostałe usunięte

    Kryteria:

    R.5.4 Skrypt 2 stosuje przynajmniej jedną metodę DOM aby zmienić cechy bloku sekcji lub przycisku

    ok. 3 min
    Polecenie z arkusza

    Działanie w przypadku zdarzenia, gdy kursor najedzie na przycisk „Kolor” (ilustracja 2): Pierwszy blok sekcji jest wyświetlany w postaci blokowej. Pozostałe bloki są usunięte

    Funkcja przechodzi po wszystkich przyciskach. Dla każdego getAttribute('aria-controls') odczytuje identyfikator jego sekcji, a getElementById ją znajduje. classList.toggle('active', warunek) dodaje klasę, gdy warunek jest prawdziwy, i zdejmuje, gdy fałszywy: sekcja przycisku pod kursorem dostaje active, pozostałe ją tracą (R.5.4). Resztę robi CSS - section.active ma display: block, pozostałe display: none.

    Skrypt nie zna liczby zakładek ani ich nazw: czwarta zakładka to czwarty przycisk z aria-controls, bez zmian w kodzie. Najedź w podglądzie na „Kształt”: widać drugą sekcję, ale przycisk „Kolor” jest nadal jasny.

    skrypt.js JavaScript zmienione: 4 linie
    // Skrypt 2: zakładki przełączane po najechaniu kursorem
    const tabButtons = document.querySelectorAll('nav button');
    
    function showSection(selectedButton) {
        for (const button of tabButtons) {
            const section = document.getElementById(button.getAttribute('aria-controls'));
            section.classList.toggle('active', button === selectedButton);
        }
    }
    
    for (const button of tabButtons) {
        button.addEventListener('mouseenter', () => showSection(button));
    }
    Podgląd strony po tym kroku (paznokcie.html)
  41. Krok 41: Skrypt 2: kolory przycisków

    Kryteria: , ,

    R.5.5 Podczas aktywowania zakładki "Kolor": kolor pierwszego przycisku zmienia się na Salmon, pozostałe - Crimson, tylko pierwszy blok sekcji jest widoczny

    R.5.6 Podczas aktywowania zakładki "Kształt": kolor drugiego przycisku zmienia się na Salmon, pozostałe - Crimson, tylko drugi blok sekcji jest widoczny

    R.5.7 Podczas aktywowania zakładki "Wzór": kolor trzeciego przycisku zmienia się na Salmon, pozostałe - Crimson, tylko trzeci blok sekcji jest widoczny

    ok. 3 min
    Polecenie z arkusza

    Pierwszy przycisk ma kolor tła Salmon. Pozostałe przyciski mają kolor tła Crimson. Działanie w przypadku zdarzenia, gdy kursor najedzie na przycisk „Kształt” (ilustracja 7): Drugi blok sekcji jest wyświetlany w postaci blokowej. Pozostałe bloki są usunięte. Drugi przycisk ma kolor tła Salmon. Pozostałe przyciski mają kolor tła Crimson. Działanie w przypadku zdarzenia, gdy kursor najedzie na przycisk „Wzór” (ilustracja 6): Trzeci blok sekcji jest wyświetlany w postaci blokowej. Pozostałe bloki są usunięte. Trzeci przycisk ma kolor tła Salmon. Pozostałe przyciski mają kolor tła Crimson

    Ten sam przełącznik dla przycisku: wynik porównania trafia do stałej isSelected i klasa active przenosi się razem z sekcją. Kolory Salmon i Crimson ustawia CSS (button i button.active) - skrypt nie zawiera ani jednego koloru, więc zmiana wyglądu zakładek to zmiana tylko w styl.css.

    Sprawdzone w Chrome dla każdego przycisku: „Kolor” - sekcja 1 i jasny pierwszy przycisk, „Kształt” - sekcja 2, „Wzór” - sekcja 3, pozostałe przyciski ciemne (R.5.5 - R.5.7).

    skrypt.js JavaScript zmienione: 3 linie
    // Skrypt 2: zakładki przełączane po najechaniu kursorem
    const tabButtons = document.querySelectorAll('nav button');
    
    function showSection(selectedButton) {
        for (const button of tabButtons) {
            const section = document.getElementById(button.getAttribute('aria-controls'));
            const isSelected = button === selectedButton;
            button.classList.toggle('active', isSelected);
            section.classList.toggle('active', isSelected);
        }
    }
    
    for (const button of tabButtons) {
        button.addEventListener('mouseenter', () => showSection(button));
    }
    Podgląd strony po tym kroku (paznokcie.html)
  42. Krok 42: Skrypt 2: zakładki także z klawiatury

    ok. 2 min
    Polecenie z arkusza

    Zdarzenie najechania kursorem myszy na dowolny przycisk uruchamia skrypt 2

    Najechanie kursorem nie istnieje dla osoby bez myszy. Drugie zdarzenie, focus, wywołuje tę samą funkcję, gdy przycisk dostaje fokus - klawiszem Tab albo dotknięciem na telefonie. Sprawdzone w Chrome: przejście Tabem po przyciskach przełącza sekcje tak samo jak kursor. Klucz wymienia focus wśród zdarzeń, które uznaje.

    skrypt.js JavaScript zmienione: 1 linia
    // Skrypt 2: zakładki przełączane po najechaniu kursorem
    const tabButtons = document.querySelectorAll('nav button');
    
    function showSection(selectedButton) {
        for (const button of tabButtons) {
            const section = document.getElementById(button.getAttribute('aria-controls'));
            const isSelected = button === selectedButton;
            button.classList.toggle('active', isSelected);
            section.classList.toggle('active', isSelected);
        }
    }
    
    for (const button of tabButtons) {
        button.addEventListener('mouseenter', () => showSection(button));
        button.addEventListener('focus', () => showSection(button));
    }
    Podgląd strony po tym kroku (paznokcie.html)
  43. Krok 43: Skrypt 1: dziesięć obrazów z pętli

    Kryteria: ,

    R.5.1 Skrypt 1 napisany w języku JavaScript lub PHP oraz skrypt 2 w języku JavaScript. Przynajmniej jeden skrypt zawiera przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania

    R.5.2 Na stronie jest wyświetlanych za pomocą pętli 10 obrazów o nazwach 1.jpg ÷ 10.jpg

    ok. 3 min
    Polecenie z arkusza

    Skrypt 1: Zapisany w języku JavaScript lub PHP (w przypadku PHP plik musi nazywać się paznokcie.php). Wyświetla za pomocą pętli 10 obrazów o nazwach, kolejno: 1.jpg, 2.jpg, 3.jpg ... 10.jpg

    Skrypt 1 w tym samym pliku, pod skryptem 2. Pętla for liczy od 1 do 10; w każdym obrocie createElement('img') tworzy obraz, a szablon tekstowy `${number}.jpg` (odwrotne apostrofy, wartość w ${}) skleja nazwę pliku. append dokłada obraz na koniec bloku #patterns (R.5.1, R.5.2).

    document.write z wersji podstawowej działa tylko podczas wczytywania strony i musi stać w miejscu, gdzie mają się pojawić obrazy. Tu skrypt jest w osobnym pliku i uruchamia się po wczytaniu HTML-u, więc wstawia obrazy do wskazanego bloku. Najedź na „Wzór”: dziesięć dużych kwadratów, jeszcze bez stylu klasy.

    skrypt.js JavaScript zmienione: 9 linii
    // Skrypt 2: zakładki przełączane po najechaniu kursorem
    const tabButtons = document.querySelectorAll('nav button');
    
    function showSection(selectedButton) {
        for (const button of tabButtons) {
            const section = document.getElementById(button.getAttribute('aria-controls'));
            const isSelected = button === selectedButton;
            button.classList.toggle('active', isSelected);
            section.classList.toggle('active', isSelected);
        }
    }
    
    for (const button of tabButtons) {
        button.addEventListener('mouseenter', () => showSection(button));
        button.addEventListener('focus', () => showSection(button));
    }
    
    // Skrypt 1: dziesięć wzorów generowanych pętlą
    const patterns = document.getElementById('patterns');
    
    for (let number = 1; number <= 10; number++) {
        const image = document.createElement('img');
        image.src = `${number}.jpg`;
        patterns.append(image);
    }
    Podgląd strony po tym kroku (paznokcie.html)
  44. Krok 44: Skrypt 1: klasa wzory, dymek z numerem i tekst alternatywny

    Kryteria: ,

    R.5.3 Każdy generowany skryptem obraz ma przypisaną klasę wzory oraz atrybut title z nazwą (numerem) pliku

    R.5.8 W skryptach zastosowana przynajmniej jedna zmienna lub funkcja oraz nazwy wszystkich funkcji i zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania

    ok. 2 min
    Polecenie z arkusza

    Każdy obraz ma przypisaną klasę wzory. Po najechaniu kursorem na obraz jest wyświetlany dymek z nazwą (numerem) obrazu (na ilustracji 6 wskazano obraz3.jpg, więc dymek zawiera liczbę 3)

    Trzy właściwości obrazu:

    • classList.add('wzory') - klasa z arkusza; reguła .wzory robi z kwadratów koła,
    • title - dymek po najechaniu kursorem; String(number) zamienia liczbę na tekst „3” (R.5.3),
    • alt - „Wzór 3”: obraz bez tekstu alternatywnego jest dla czytnika ekranu samą nazwą pliku.

    Nazwy w skrypcie mówią, do czego służą (R.5.8): tabButtons, showSection, selectedButton, button, section, isSelected, patterns, number, image.

    skrypt.js JavaScript zmienione: 3 linie
    // Skrypt 2: zakładki przełączane po najechaniu kursorem
    const tabButtons = document.querySelectorAll('nav button');
    
    function showSection(selectedButton) {
        for (const button of tabButtons) {
            const section = document.getElementById(button.getAttribute('aria-controls'));
            const isSelected = button === selectedButton;
            button.classList.toggle('active', isSelected);
            section.classList.toggle('active', isSelected);
        }
    }
    
    for (const button of tabButtons) {
        button.addEventListener('mouseenter', () => showSection(button));
        button.addEventListener('focus', () => showSection(button));
    }
    
    // Skrypt 1: dziesięć wzorów generowanych pętlą
    const patterns = document.getElementById('patterns');
    
    for (let number = 1; number <= 10; number++) {
        const image = document.createElement('img');
        image.src = `${number}.jpg`;
        image.alt = `Wzór ${number}`;
        image.title = String(number);
        image.classList.add('wzory');
        patterns.append(image);
    }
    Podgląd strony po tym kroku (paznokcie.html)
  45. Etap 5: Porównanie z wersją podstawową

    Kroki 45-46 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 45: Co jest inaczej i dlaczego

    ok. 3 min
    Polecenie z arkusza

    Ocenie podlegać będzie 5 rezultatów: operacje na bazie danych, zawartość witryny internetowej, działanie witryny internetowej, styl CSS witryny internetowej, skrypt.

    Obie wersje dają te same punkty. Różnice:

    wersja podstawowata wersja
    układdisplay: flex na <body>, width blokówsiatka 20% 80%
    widoczność i koloryskrypt wpisuje style.display i style.backgroundColorskrypt przenosi klasę active, wygląd z CSS
    przycisk ↔ sekcja"section" + numberatrybut aria-controls
    zdarzenieatrybut onmouseover w HTMLaddEventListener('mouseenter') i focus
    skrypty<script> w HTML, document.writeskrypt.js z defer, createElement + append
    obrazy wzorówbez altalt, title, klasa
    pola formularzapo <br>w <div>, z aria-label
    zapytanie 2DATE(termin) = …przedział >= / <

    Arkusz pozwala napisać skrypt 1 także w PHP (plik paznokcie.php): pętla for z echo "<img src=\"$i.jpg\" class=\"wzory\" title=\"$i\">"; wysłałaby gotowe obrazy w HTML-u, bez JavaScriptu. Skrypt 2 i tak musi zostać w JavaScripcie - reaguje na kursor po stronie przeglądarki.

    Podgląd strony bez zmian - taki jak po kroku 44.

  46. Krok 46: Którą wersję wybrać na egzaminie

    ok. 2 min
    Polecenie z arkusza

    Czas przeznaczony na wykonanie zadania wynosi 150 minut.

    • Wersja podstawowa, gdy liczy się czas: metody z tabeli 1 arkusza (getElementById, style, onmouseover) wystarczą do pełnych punktów, a każdą linię łatwo sprawdzić w przeglądarce.
    • Ta wersja, gdy addEventListener i classList są pisane z pamięci. Jedna pułapka: skrypt w <head> bez defer uruchomiłby się przed przyciskami i querySelectorAll zwróciłby pustą listę - zakładki by nie działały, a w konsoli nie byłoby żadnego błędu.

    Mieszanie też daje pełne punkty, np. klasy active z tej wersji i onmouseover z podstawowej.

    Podgląd strony bez zmian - taki jak po kroku 44.

  47. Etap 6: Oddanie pracy

    Krok 47 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 47: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    UWAGA: po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt nazwa przeglądarki, w której strona była sprawdzana.

    W folderze z numerem zdającego: 1.jpg - 10.jpg, import.png, kolory.png, ksztalt.png, kw1.png - kw4.png, kwerendy.txt, manicure.jpg, paznokcie.html, przeglądarka.txt, skrypt.js, styl.css. Po nagraniu sprawdź odczyt płyty.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 44.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.