Przejdź do głównej treści
INF.03-03-26.01-SGStyczeń 2026 · 51 kroków · ok. 92 min · 38 kryteriów z klucza

Rozwiązanie krok po kroku: Witryna matematyczna pola figur (Nowoczesny kod (grid))

To drugi sposób rozwiązania tego samego arkusza: animacja GIF z pięciu kwadratów, strona index.html z dużą figurą, dwiema klikanymi miniaturami i kalkulatorem pola oraz podstrona kolo.html ze wzorem na pole koła. Obie wersje spełniają wszystkie 38 kryteriów klucza - różni je sposób pisania kodu, nie wynik.

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

  • siatka CSS (display: grid) w bloku głównym: trzy kolumny 35% / 30% / 35% w jednej linii grid-template-columns, kolory z arkusza w zmiennych CSS,
  • HTML bez <br>: miniatury mają własny blok, a etykiety nad polami ustawia CSS,
  • skrypt w osobnym pliku skrypt.js dołączonym z defer - w HTML nie ma ani jednego onclick,
  • dane zamiast drabinki if: obiekt FIGURES opisuje każdą figurę (plik obrazu, nazwę, wzór na pole), a skrypt pamięta wybraną figurę w zmiennej, zamiast porównywać atrybut src,
  • miniatury obsługiwane także klawiaturą (Tab, Enter, spacja), wynik przez textContent i ogłaszany czytnikom ekranu (aria-live).

Kroki nadal idą zdanie po zdaniu za treścią arkusza. Oba skrypty są sprawdzone w prawdziwej przeglądarce na oryginalnych plikach BMP z archiwum pliki2 - kliknięciami, klawiaturą i złymi danymi.

Jak liczą się punkty. Klucz ma 38 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 29 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: Animacja

    Kroki 1-3 · po tym etapie masz 4 z 38 kryteriów (pkt)

    Krok 1: Pięć klatek 200 × 200 px wyciętych z klatki.jpg

    Kryteria: ,

    R.1.1 Animacja kolo.gif ma wymiary 200 px na 200 px

    R.1.2 W animacji zastosowany przynajmniej jeden kwadrat z grafiki klatki.jpg

    ok. 5 min
    Polecenie z arkusza

    Każdą klatką animacji jest jeden kwadrat z grafiki klatki.jpg, razem to pięć klatek animacji. Wymiary każdej klatki: 200 px na 200 px

    Archiwum pliki2.7z ma hasło *M@tem@tyk@6 (gwiazdka na początku, trzy małpy zamiast „a”). Obraz klatki.jpg ma 1122 × 220 px, a każdy z pięciu kwadratów - około 205 × 204 px, czyli trochę więcej niż klatka.

    W GIMP-ie nowy obraz 200 × 200 px, a potem dla każdego kwadratu: zaznaczanie prostokątne z opcją Stały: Rozmiar 200 × 200, zaznaczenie w środku kwadratu, Kopiuj, w nowym obrazie Wklej jako → Nowa warstwa. Stały rozmiar zaznaczenia gwarantuje identyczne klatki - bez skalowania, które rozmyłoby napis. Kolejność warstw: ostatnia na liście to pierwsza klatka, więc kwadraty wkleja się od lewej do prawej.

    Typowe błędy

    Klatka większa niż 200 × 200 px (cały kwadrat z ramką albo przeskalowany cały obraz) daje animację o złych wymiarach - klucz sprawdza dokładnie 200 × 200.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 1
  2. Krok 2: Pętla i opóźnienie 1 s: zrzut parametry.jpg

    Kryteria:

    R.1.4 Ustawiono opóźnienie między klatkami na 1 sekundę, co jest udokumentowane zrzutem ekranu - plik parametry.jpg , na którym widoczny jest cały obszar ekranu z paskiem zadań

    ok. 3 min
    Polecenie z arkusza

    Animacja jest powtarzana w nieskończoność, opóźnienie między klatkami 1 sekunda. Udokumentuj ustawienie parametrów animacji za pomocą zrzutu ekranu o nazwie parametry.jpg. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań.

    Plik → Wyeksportuj jako, nazwa kolo.gif. W oknie eksportu GIF:

    • Jako animację - bez tego GIMP spłaszczy warstwy do jednego obrazu,
    • Pętla - powtarzanie w nieskończoność,
    • opóźnienie 1000 ms - jednostką są milisekundy, więc 1 s to 1000,
    • Jedna klatka na warstwę (zastąp) i Użyj opóźnienia wprowadzonego powyżej dla wszystkich klatek - GIMP czyta też opóźnienie z nazw warstw (np. „Warstwa (100ms)”), a to pole każe zignorować nazwy.

    Zanim klikniesz Eksportuj, zrób zrzut całego ekranu z tym oknem i zapisz go jako parametry.jpg (JPEG, nie PNG). Obraz w podglądzie kroku to odtworzenie tego okna z ustawieniami z arkusza.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 2
  3. Krok 3: Animacja kolo.gif

    Kryteria:

    R.1.3 Animacja składa się z pięciu klatek wyświetlanych jedna po drugiej, po ostatniej klatce jest wyświetlana pierwsza

    ok. 1 min
    Polecenie z arkusza

    Animację zapisz jako kolo.gif

    Eksportuj - powstaje kolo.gif: 5 klatek 200 × 200 px, każda po 1000 ms, po ostatniej znów pierwsza (R.1.3). Litery napisu „KOŁO” po kolei robią się czerwone, a koło miga na żółto i czerwono. Najprostszy test: przeciągnij plik do okna przeglądarki - animacja musi się zapętlać.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 3
  4. Etap 2: Strona HTML

    Kroki 4-22 · po tym etapie masz 17 z 38 kryteriów (pkt)

    Krok 4: Plik index.html w HTML5

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony głównej index.html oraz podstrony kolo.html. Cechy wspólne dla obu stron: zapisane w języku HTML5

    <!DOCTYPE html> i szkielet strony głównej. Podstrona kolo.html powstanie później jako kopia gotowej strony - obie mają ten sam nagłówek, menu i stopkę, więc nie ma sensu pisać ich dwa razy.

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

    Kryteria:

    R.2.1 W plikach index.html lub kolo.html 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

    lang="pl" w <html>: czytnik ekranu czyta stronę polską wymową, a przeglądarka wie, że nie musi proponować tłumaczenia. Z <!DOCTYPE html> to jedno kryterium (R.2.1).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  6. Krok 6: 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> - przeglądarka musi znać kodowanie, zanim przeczyta tytuł i „trójkąt” z polskimi literami.

    index.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 (index.html)
  7. Krok 7: Tytuł strony i viewport

    Kryteria:

    R.2.2 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków i tytuł strony "Pola figur"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Pola figur”

    <title> to tekst karty (z kodowaniem - R.2.2). <meta name="viewport"> każe telefonowi pokazać stronę w jego prawdziwej szerokości, zamiast udawać ekran szeroki na ok. 980 px i pomniejszać wszystko. Arkusz tego nie wymaga.

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  8. Krok 8: 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

    <link rel="stylesheet" href="styl.css"> - znacznik pusty, w HTML5 bez ukośnika />. Całe formatowanie pochodzi z tego pliku (R.3.2); w HTML nie ma żadnego atrybutu style.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  9. Krok 9: Bloki semantyczne

    Kryteria:

    R.2.3 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header, main->nav+section+aside, footer (dopuszcza się stosowanie bloków pomocniczych)

    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. Zawartość bloku głównego: bloki nawigacyjny, sekcji i boczny

    Klucz R.2.3 wymienia znaczniki: header, main z nav, section i aside w środku, footer. Kolejność w <main> to kolejność kolumn z ilustracji 4: menu, figura, kalkulator. Trzy bloki są jedynymi dziećmi <main>, więc siatka ustawiona na <main> rozłoży je w kolumny bez dodatkowych klas.

    W tym arkuszu dwie ilustracje mają numer 4 (układ bloków i wynik dla trójkąta) - tutaj chodzi o układ.

    index.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <main>
            <nav>
            </nav>
            <section>
            </section>
            <aside>
            </aside>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  10. Krok 10: Nagłówek strony

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego: nagłówek drugiego stopnia o treści „Pola figur płaskich”

    Drugiego stopnia, czyli <h2> - arkusz mówi to wprost, choć to najważniejszy nagłówek strony. Kryterium R.2.4 sprawdza właśnie <h2>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
            </nav>
            <section>
            </section>
            <aside>
            </aside>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  11. Krok 11: Menu: nagłówek

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nawigacyjnego: Nagłówek trzeciego stopnia o treści „MENU”

    <h3> na początku bloku nawigacyjnego. Powiększoną pierwszą literę z ilustracji 2 zrobi CSS, bez dzielenia słowa na znaczniki.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
            </nav>
            <section>
            </section>
            <aside>
            </aside>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  12. Krok 12: Menu: lista z dwoma odsyłaczami

    Kryteria:

    R.2.5 W bloku nawigacyjnym umieszczona jedna lista punktowana z dwoma elementami, zastosowane znaczniki <ul> i <li>

    ok. 2 min
    Polecenie z arkusza

    Lista punktowana (nieuporządkowana) z dwoma odsyłaczami o treści „Prostokąt i trójkąt”, prowadzący do strony index.html oraz „Okrąg i koło”, prowadzący do strony kolo.html

    <ul> z dwoma <li>, w każdym odnośnik z adresem względnym - obie strony leżą w tym samym folderze (R.2.5). Atrybut aria-current="page" przy odnośniku do bieżącej strony mówi czytnikowi ekranu „jesteś tutaj”; na kolo.html przejdzie na drugi odnośnik. Ten sam atrybut przyda się, gdyby menu miało kiedyś wyróżniać bieżącą stronę w CSS ([aria-current]).

    index.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
            </section>
            <aside>
            </aside>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: Stopka

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: paragraf o treści: „Autor: ”, dalej wpisany numer zdającego.

    Akapit w <footer>. Tu stoi imię i nazwisko autora rozwiązania - na egzaminie wpisujesz swój numer zdającego (PESEL).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
            </section>
            <aside>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  14. Krok 14: Sekcja: duża figura

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji strony index.html: Obraz 1d.bmp z tekstem alternatywnym „Figura”

    Duży trójkąt na start, z id="figure" - po nim skrypt znajdzie obraz i podmieni plik. Pliki BMP zostają w oryginalnym formacie, jak każe arkusz; przeglądarki wyświetlają BMP bez problemu.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
            </section>
            <aside>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  15. Krok 15: Sekcja: miniatury w osobnym bloku

    Kryteria: ,

    R.2.6 Na stronie głównej w bloku sekcji umieszczone grafiki z tekstem alternatywnym: 1d.bmp , "Figura"; 1m.bmp , "Wybierz trójkąt"; 2m.bmp , "Wybierz prostokąt" (dopuszcza się dla obrazów 1m i 2m przycisk z obrazem)

    R.3.6 Do grafik 1m.bmp i 2m.bmp przypisana jest klasa

    ok. 2 min
    Polecenie z arkusza

    Poniżej obok siebie dwa obrazy: 1m.bmp z tekstem alternatywnym „Wybierz trójkąt” oraz 2m.bmp, z tekstem alternatywnym „Wybierz prostokąt”. Kliknięcie dowolnego z tych obrazów uruchamia skrypt 1. Do obu obrazów należy przypisać tę samą klasę

    Miniatury stoją w bloku pomocniczym <div class="thumbnails"> - blok zawsze zaczyna się w nowej linii, więc są „poniżej” dużej figury bez znacznika <br>, który służy do łamania wierszy tekstu, a nie do układania obrazów. W bloku obrazy są elementami liniowymi i stają obok siebie.

    Oba obrazy mają tę samą klasę choice (R.3.6) - na nią czeka styl cienia. Obsługę kliknięcia dopisze skrypt.

    index.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Blok boczny: nagłówek kalkulatora

    Kryteria:

    R.2.4 W bloku nagłówkowym umieszczony <h2>: "Pola figur płaskich", w nawigacyjnym <h3> "MENU", na stronie głównej <h3> "Pole prostokąta / pole trójkąta" oraz w stopce <p> z numerem zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku bocznego strony index.html, rozkład elementów zgodny z ilustracją 2: Nagłówek trzeciego stopnia o treści: „Pole prostokąta / pole trójkąta”

    Drugi <h3> na stronie. Na stronie są już wszystkie nagłówki i akapit z R.2.4: <h2> w nagłówku, dwa <h3> i <p> w stopce.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Pierwsza etykieta i pole

    Kryteria:

    R.3.7 Przynajmniej jedna etykieta jest powiązana z polem edycyjnym

    ok. 2 min
    Polecenie z arkusza

    Etykieta „Bok prostokąta / podstawa trójkąta:” oraz pole edycyjne powiązane z etykietą

    <label for="side-a"> wskazuje id pola (R.3.7) - kliknięcie napisu ustawia kursor w polu, a czytnik ekranu przeczyta napis jako opis pola. Identyfikator side-a w stylu „z myślnikami”, typowym dla HTML i CSS.

    Pole type="number" z step="any": domyślny krok pola liczbowego to 1, więc bez step="any" przeglądarka oznaczyłaby bok 2,5 jako błędny. min="0" podpowiada, że ujemne długości nie mają sensu. Między etykietą a polem nie ma <br> - etykietę nad polem postawi CSS.

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Druga etykieta i pole

    ok. 1 min
    Polecenie z arkusza

    Etykieta „Drugi bok prostokąta / wysokość trójkąta:” oraz pole edycyjne powiązane z etykietą

    To samo dla drugiej wartości: for="side-b" i id="side-b". Każde id może wystąpić na stronie tylko raz - inaczej etykieta nie wiedziałaby, które pole opisuje.

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Przycisk „Oblicz”

    Kryteria:

    R.2.7 Na stronie głównej umieszczone dwa pola edycyjne oraz przycisk Oblicz

    ok. 1 min
    Polecenie z arkusza

    Przycisk „Oblicz”, którego wciśnięcie powoduje wywołanie skryptu 2

    type="button" mówi wprost: ten przycisk niczego nie wysyła, zrobi tylko to, co każe mu skrypt. To ważne, gdyby kalkulator trafił kiedyś do <form> - przycisk bez typu wysłałby wtedy formularz i przeładował stronę. Na stronie są dwa pola i przycisk (R.2.7).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Pusty akapit na wynik

    ok. 1 min
    Polecenie z arkusza

    Paragraf przeznaczony na wynik. W stanie początkowym jest on pusty

    <p id="result"> - pusty, pod przyciskiem. aria-live="polite" sprawia, że czytnik ekranu sam przeczyta nowy wynik, gdy skrypt go wpisze - bez tego osoba niewidoma nie wiedziałaby, że coś się zmieniło.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
                <p id="result" aria-live="polite"></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Podstrona kolo.html z animacją

    Kryteria: ,

    R.2.8 Na podstronie umieszczona animacja/grafika z kołem, z tekstem alternatywnym "koło"

    R.3.3 Wybranie odnośnika "Prostokąt i trójkąt" otwiera stronę główną, "Okrąg i koło" otwiera podstronę

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku sekcji strony kolo.html: Animacja kolo.gif z tekstem alternatywnym „koło”

    Zapisz jako kolo.html - przychodzą razem wszystkie cechy wspólne: nagłówek strony, styl, menu i stopka. W sekcji zamiast figury i miniatur jest animacja z alt="koło", a aria-current="page" przechodzi na odnośnik „Okrąg i koło”. Teraz oba odnośniki działają: „Prostokąt i trójkąt” otwiera stronę główną, „Okrąg i koło” - podstronę (R.3.3).

    kolo.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html" aria-current="page">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="kolo.gif" alt="koło">
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
                <p id="result" aria-live="polite"></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kolo.html)
  22. Krok 22: Podstrona: wzór na pole koła

    Kryteria:

    R.2.9 Na podstronie umieszczony paragraf o treści: Pole koła: P = Π * r2

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku bocznego strony kolo.html: Paragraf o treści „Pole koła: P = Π * r2”. Litera Pi (Π) powinna być zapisana za pomocą znaku specjalnego; oznaczenie potęgi powinno znajdować się w indeksie górnym.

    Kalkulator w bloku bocznym zastępuje jeden akapit. &Pi; to encja nazwana z tabeli 1 arkusza (to samo daje &#928;), a <sup> podnosi dwójkę do indeksu górnego: r<sup>2</sup>. <sup> jest tu na miejscu, bo potęga to część treści, a nie ozdoba - czytnik ekranu też ją rozpozna.

    ⚠️ Sprzeczność w arkuszu: polecenie i tabela 1 każą użyć wielkiej litery Π (&Pi;), a ilustracja 3 pokazuje małą π (&pi;), poprawną matematycznie we wzorze na pole koła. Klucz CKE przyjmuje &Pi; - na egzaminie punkt daje wersja z klucza.

    Typowe błędy

    „r2” zwykłym tekstem albo π wklejone ze schowka nie spełnia wymagań: potęga ma być w <sup>, a Pi - znakiem specjalnym.

    kolo.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html" aria-current="page">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="kolo.gif" alt="koło">
            </section>
            <aside>
                <p>Pole koła: P = &Pi; * r<sup>2</sup></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (kolo.html)
  23. Etap 3: Styl CSS

    Kroki 23-36 · po tym etapie masz 28 z 38 kryteriów (pkt)

    Krok 23: Zmienne CSS z kolorami arkusza

    ok. 2 min
    Polecenie z arkusza

    Styl CSS zdefiniowany jest w całości w zewnętrznym pliku o nazwie styl.css.

    Plik styl.css zaczyna się od zmiennych CSS w :root. Nazwy opisują rolę koloru, nie sam kolor: --color-side to tło obu bocznych kolumn - gdyby ktoś zmienił DodgerBlue na inny odcień, nazwa zmiennej nadal będzie prawdziwa. W regułach kolor pojawia się jako var(--color-side). Podgląd wraca na stronę główną.

    styl.css CSS nowy plik
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Krój Garamond dla wszystkich selektorów

    Kryteria:

    R.4.1 styl domyślny dla wszystkich selektorów (*): krój czcionki Garamond, serif (dozwolona tylko taka kolejność)

    ok. 1 min
    Polecenie z arkusza

    Domyślnie, dla wszystkich selektorów: krój czcionki Garamond, w przypadku braku serif

    Selektor * (R.4.1) obejmuje też pola i przycisk, które domyślnie mają krój systemowy. Najpierw Garamond, na końcu rodzina zapasowa serif - klucz dopuszcza tylko taką kolejność.

    styl.css CSS zmienione: 4 linie
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: Nagłówek i stopka

    Kryteria: ,

    R.4.3 kolor czcionki: blok nagłówkowy i stopka - biały

    R.4.7 odstęp między literami: blok nagłówkowy i stopka - letter-spacing: 3px;

    ok. 2 min
    Polecenie z arkusza

    Wspólne dla bloku nagłówkowego i stopki: kolor tła Navy, biały kolor czcionki, wyrównanie tekstu do środka, marginesy wewnętrzne 5 px, odstępy między literami 3 px

    Jedna reguła dla dwóch selektorów. letter-spacing: 3px rozstrzela litery, jak „P o l a” na ilustracji 2 (R.4.7).

    styl.css CSS zmienione: 9 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Trzy bloki: wysokość

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla bloku nawigacyjnego, sekcji i bocznego: wysokość 500 px

    Trzy selektory po przecinku - wspólna cecha w jednym miejscu.

    styl.css CSS zmienione: 6 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Menu i blok boczny: tło

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku nawigacyjnego i bocznego: kolor tła DodgerBlue, szerokość 35%

    Tło ze zmiennej. Szerokości tu nie ma - wszystkie trzy kolumny wyznaczy jedna linia siatki w kroku układu. Klucz R.4.4 dopuszcza to wprost: „szerokość (width lub grid-template-columns lub flex)”.

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    Podgląd strony po tym kroku (index.html)
  28. Krok 28: Sekcja: tło i wyśrodkowanie

    Kryteria:

    R.4.2 kolor tła: blok nagłówkowy i stopka - Navy, blok nawigacyjny i boczny - DodgerBlue, blok sekcji - SkyBlue

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku sekcji: kolor tła SkyBlue, szerokość 30%, wyrównanie tekstu do środka

    text-align: center działa też na obrazy, bo są elementami liniowymi - duża figura i obie miniatury stają na środku sekcji. Z tą regułą jest komplet kolorów tła (R.4.2).

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  29. Krok 29: Układ: siatka trzech kolumn

    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)

    R.4.4 szerokość: blok nawigacyjny i boczny - 35%, blok sekcji - 30% (width lub grid-template- columns lub flex) wysokość: blok nawigacyjny, boczny oraz blok sekcji - 500px

    ok. 3 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

    <main> staje się siatką o trzech kolumnach: grid-template-columns: 35% 30% 35% - menu, sekcja i blok boczny wpadają do kolumn w kolejności z HTML. Szerokości wszystkich bloków stoją w jednej linii, więc od razu widać, że sumują się do 100%. Nagłówek i stopka są poza siatką, więc stoją nad i pod nią - bez float i bez clear (R.3.1). Z tą regułą są komplet wymiarów (R.4.4): szerokości w siatce i wysokości 500 px.

    Typowe błędy

    Odstęp gap przy kolumnach w procentach dokłada się do 100% - siatka wyjechałaby poza ekran. Przy procentach z arkusza odstępów nie ma.

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Kalkulator: etykieta nad polem

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku bocznego strony index.html, rozkład elementów zgodny z ilustracją 2

    Na ilustracji 2 każde pole stoi pod swoją etykietą, a przycisk pod drugim polem. display: block dla etykiet i pól kalkulatora daje każdemu z nich własną linię - to samo, co <br> w wersji podstawowej, ale wygląd zostaje w CSS, a HTML opisuje tylko treść. Selektory z aside nie ruszają innych etykiet na stronie.

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: Pola i przycisk: marginesy

    Kryteria:

    R.4.6 marginesy wewnętrzne (padding) : blok nagłówkowy i stopka - 5px marginesy zewnętrzne (margin) : pole edycyjne i przycisk - 10px

    ok. 1 min
    Polecenie z arkusza

    Dla pola edycyjnego i przycisku: marginesy zewnętrzne 10 px

    Selektory znaczników input i button (R.4.6). Przy polu z display: block margines działa ze wszystkich stron, przy przycisku (liniowo-blokowym) też.

    styl.css CSS zmienione: 5 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    
    input,
    button {
        margin: 10px;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Nagłówki trzeciego stopnia wyśrodkowane

    Kryteria:

    R.4.5 wyrównanie tekstu do środka: blok nagłówkowy, stopka, blok sekcji oraz selektor h3

    ok. 1 min
    Polecenie z arkusza

    Dla selektora nagłówka trzeciego stopnia: wyrównanie tekstu do środka

    Selektor znacznika h3, jak każe uwaga arkusza. Z nagłówkiem, stopką i sekcją to komplet R.4.5.

    styl.css CSS zmienione: 4 linie
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    
    input,
    button {
        margin: 10px;
    }
    
    h3 {
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Pierwsza litera nagłówka dwa razy większa

    Kryteria:

    R.4.9 pseudoelement first-letter dla nagłówka trzeciego stopnia: rozmiar czcionki 200%

    ok. 2 min
    Polecenie z arkusza

    Dla selektora nagłówka trzeciego stopnia: pierwsza litera nagłówka ma rozmiar czcionki 200%

    Pseudoelement ::first-letter (R.4.9) wybiera pierwszą literę tekstu - bez <span> w HTML. Podwójny dwukropek odróżnia pseudoelement (część elementu) od pseudoklasy (stanu, np. :hover); stary zapis z jednym dwukropkiem też działa.

    styl.css CSS zmienione: 4 linie
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    
    input,
    button {
        margin: 10px;
    }
    
    h3 {
        text-align: center;
    }
    
    h3::first-letter {
        font-size: 200%;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Akapity

    Kryteria:

    R.4.8 dla selektora p rozmiar czcionki - 150%

    ok. 1 min
    Polecenie z arkusza

    Dla selektora paragrafu: rozmiar czcionki 150%

    Selektor znacznika p (R.4.8): stopka, wynik obliczenia i wzór na podstronie.

    styl.css CSS zmienione: 4 linie
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    
    input,
    button {
        margin: 10px;
    }
    
    h3 {
        text-align: center;
    }
    
    h3::first-letter {
        font-size: 200%;
    }
    
    p {
        font-size: 150%;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Miniatury: cień, zaokrąglenie, kursor

    Kryteria:

    R.4.10 styl klasy przypisanej do grafik 1m.bmp i 2m.bmp : box-shadow: 5px 5px 10px DimGray; zaokrąglenie rogów 10px, marginesy zewnętrzne 5px, kursor pointer

    ok. 2 min
    Polecenie z arkusza

    Dla klasy przypisanej do grafik 1m.bmp i 2m.bmp: cień przesunięty o 5 px w pionie i poziomie, rozmycie 10 px kolor DimGray, zaokrąglenie rogów 10 px, marginesy zewnętrzne 5 px, kursor pointer.

    box-shadow: 5px 5px 10px - przesunięcie w poziomie, w pionie, rozmycie, potem kolor ze zmiennej (R.4.10). cursor: pointer zmienia strzałkę w rączkę: miniaturę da się kliknąć.

    styl.css CSS zmienione: 7 linii
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    
    input,
    button {
        margin: 10px;
    }
    
    h3 {
        text-align: center;
    }
    
    h3::first-letter {
        font-size: 200%;
    }
    
    p {
        font-size: 150%;
    }
    
    .choice {
        box-shadow: 5px 5px 10px var(--color-shadow);
        border-radius: 10px;
        margin: 5px;
        cursor: pointer;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Miniatury: widoczny fokus z klawiatury

    ok. 1 min
    Polecenie z arkusza

    Kliknięcie dowolnego z tych obrazów uruchamia skrypt 1

    Miniatury będzie można wybrać także klawiszem Tab. :focus-visible rysuje granatową obwódkę tylko wtedy, gdy fokus przyszedł z klawiatury - kliknięcie myszą jej nie pokaże. Bez widocznego fokusu osoba korzystająca z klawiatury nie wie, na czym jest. Klucz tego nie ocenia.

    styl.css CSS zmienione: 4 linie
    :root {
        --color-dark: Navy;
        --color-side: DodgerBlue;
        --color-section: SkyBlue;
        --color-shadow: DimGray;
    }
    
    * {
        font-family: Garamond, serif;
    }
    
    header,
    footer {
        background-color: var(--color-dark);
        color: white;
        text-align: center;
        padding: 5px;
        letter-spacing: 3px;
    }
    
    nav,
    section,
    aside {
        height: 500px;
    }
    
    nav,
    aside {
        background-color: var(--color-side);
    }
    
    section {
        background-color: var(--color-section);
        text-align: center;
    }
    
    main {
        display: grid;
        grid-template-columns: 35% 30% 35%;
    }
    
    aside label,
    aside input {
        display: block;
    }
    
    input,
    button {
        margin: 10px;
    }
    
    h3 {
        text-align: center;
    }
    
    h3::first-letter {
        font-size: 200%;
    }
    
    p {
        font-size: 150%;
    }
    
    .choice {
        box-shadow: 5px 5px 10px var(--color-shadow);
        border-radius: 10px;
        margin: 5px;
        cursor: pointer;
    }
    
    .choice:focus-visible {
        outline: 3px solid var(--color-dark);
    }
    Podgląd strony po tym kroku (index.html)
  37. Etap 4: JavaScript

    Kroki 37-48 · po tym etapie masz 38 z 38 kryteriów (pkt)

    Krok 37: Plik skrypt.js dołączony z atrybutem defer

    ok. 2 min
    Polecenie z arkusza

    Wykonywane po stronie klienta, na stronie index.html

    Skrypt mieszka w osobnym pliku skrypt.js, dołączonym tylko do index.html (podstrona go nie potrzebuje). <script src="skrypt.js" defer> stoi w <head>, a defer każe przeglądarce pobrać plik od razu, ale wykonać go dopiero po wczytaniu całego HTML - skrypt znajdzie wszystkie elementy, choć jest dołączony na górze. Arkusz pozwala na dodatkowe pliki, a osobny plik trafia na płytę razem ze stroną.

    Typowe błędy

    Skrypt w <head> bez defer wykona się przed wczytaniem <body> - document.querySelector("#figure") zwróci null.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
                <p id="result" aria-live="polite"></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript nowy plik
    // Skrypty strony index.html
    Podgląd strony po tym kroku (index.html)
  38. Krok 38: Obiekt FIGURES z opisem figur

    Kryteria:

    R.5.1 Skrypt napisany w języku JavaScript i zawiera on przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania

    ok. 3 min
    Polecenie z arkusza

    Należy stosować znaczące nazewnictwo zmiennych i funkcji w języku polskim lub angielskim

    Wszystko, czym różnią się figury, trafia do jednego obiektu: klucz triangle albo rectangle, a w środku plik dużego obrazu i nazwa do wyniku. Dalej skrypt nie będzie miał ani jednej nazwy pliku wpisanej w kod funkcji - dołożenie trzeciej figury (np. trapezu) to jeden wpis w obiekcie.

    const - tej zmiennej nikt nie nadpisze. Nazwa wielkimi literami to umowa: „stała konfiguracja, nie stan”. To pierwsza instrukcja JavaScript na stronie (R.5.1).

    skrypt.js JavaScript zmienione: 6 linii
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta' },
    };
    Podgląd strony po tym kroku (index.html)
  39. Krok 39: Elementy strony i wybrana figura

    ok. 2 min
    Polecenie z arkusza

    Obliczenia powinny też działać dla stanu początkowego witryny (Skrypt 1 nie wykonał się ani razu), wtedy liczone jest pole trójkąta

    Elementy, których skrypt będzie używał, wyszukuje raz i trzyma w stałych: querySelector przyjmuje selektor CSS (#figure - identyfikator), więc ten sam zapis co w styl.css.

    let currentFigure = 'triangle' to stan strony: która figura jest wybrana. Wartość startowa to trójkąt - dokładnie stan początkowy z arkusza, w którym duży obraz to 1d.bmp. let, bo ta zmienna będzie się zmieniać po kliknięciu miniatury.

    skrypt.js JavaScript zmienione: 6 linii
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta' },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    Podgląd strony po tym kroku (index.html)
  40. Krok 40: Skrypt 1: funkcja wybierająca figurę

    ok. 2 min
    Polecenie z arkusza

    Skrypt 1: gdy kliknięto w obraz 1m.bmp to duży obraz powyżej ustawiany jest na 1d.bmp, gdy kliknięto w obraz 2m.bmp to duży obraz powyżej ustawiany jest na 2d.bmp

    selectFigure robi dwie rzeczy: zapamiętuje wybór w currentFigure i podmienia plik dużego obrazu na ten z obiektu FIGURES. Jedna funkcja obsłuży obie miniatury - różnią się tylko kluczem figury w parametrze.

    skrypt.js JavaScript zmienione: 6 linii
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta' },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    Podgląd strony po tym kroku (index.html)
  41. Krok 41: Skrypt 1: kliknięcie miniatury trójkąta

    Kryteria: ,

    R.5.2 Po kliknięciu w obraz 1m.bmp duży obraz zmieniany jest na 1d.bmp (trójkąt)

    R.3.4 Zdefiniowane dla przynajmniej jednej grafiki zdarzenie związane z jej kliknięciem, które uruchamia funkcję skryptu (obsługa zdarzenia zdefiniowana w HTML np. onClick lub w skrypcie np.: element.addEventListener(...), element.onClick = …)

    ok. 3 min
    Polecenie z arkusza

    Gdy kliknięto w obraz 1m.bmp to duży obraz powyżej ustawiany jest na 1d.bmp

    Miniatura trójkąta dostaje atrybut data-figure="triangle" - własny atrybut danych, który skrypt czyta jako thumbnail.dataset.figure. Skrypt wyszukuje wszystkie elementy z tym atrybutem ([data-figure]) i każdemu przypina obsługę kliknięcia: addEventListener('click', ...) (R.3.4). Funkcja strzałkowa () => ... to krótki zapis funkcji wywoływanej przy kliknięciu.

    Podział ról: klasa choice jest dla stylu, data-figure - dla zachowania. Kliknięcie trójkąta ustawia 1d.bmp (R.5.2).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice" data-figure="triangle">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
                <p id="result" aria-live="polite"></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 4 linie
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta' },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
    });
    Podgląd strony po tym kroku (index.html)
  42. Krok 42: Skrypt 1: kliknięcie miniatury prostokąta

    Kryteria:

    R.5.3 Po kliknięciu w obraz 2m.bmp duży obraz zmieniany jest na 2d.bmp (prostokąt)

    ok. 1 min
    Polecenie z arkusza

    Gdy kliknięto w obraz 2m.bmp to duży obraz powyżej ustawiany jest na 2d.bmp

    Wystarczy atrybut data-figure="rectangle" w HTML - pętla z poprzedniego kroku sama znajdzie drugą miniaturę i przypnie jej to samo kliknięcie, a obiekt FIGURES podpowie plik 2d.bmp (R.5.3). W skrypcie nie zmienia się ani jedna linia. Kliknij miniatury w podglądzie: duża figura zmienia się na prostokąt i z powrotem.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice" data-figure="triangle">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice" data-figure="rectangle">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
                <p id="result" aria-live="polite"></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  43. Krok 43: Skrypt 1: wybór figury z klawiatury

    ok. 2 min
    Polecenie z arkusza

    Kliknięcie dowolnego z tych obrazów uruchamia skrypt 1

    Obraz nie jest przyciskiem, więc klawiatura go nie zauważa. tabindex="0" dodaje obie miniatury do kolejki klawisza Tab, a obsługa keydown reaguje na Enter i spację - tak jak działa prawdziwy przycisk. event.preventDefault() przy spacji powstrzymuje przewinięcie strony.

    Klucz tego nie ocenia (R.2.6 dopuszcza nawet <button> z obrazem w środku, który miałby to wszystko wbudowane), ale bez tego osoba, która nie używa myszy, nie wybierze prostokąta.

    index.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pola figur</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header>
            <h2>Pola figur płaskich</h2>
        </header>
        <main>
            <nav>
                <h3>MENU</h3>
                <ul>
                    <li><a href="index.html" aria-current="page">Prostokąt i trójkąt</a></li>
                    <li><a href="kolo.html">Okrąg i koło</a></li>
                </ul>
            </nav>
            <section>
                <img src="1d.bmp" alt="Figura" id="figure">
                <div class="thumbnails">
                    <img src="1m.bmp" alt="Wybierz trójkąt" class="choice" tabindex="0" data-figure="triangle">
                    <img src="2m.bmp" alt="Wybierz prostokąt" class="choice" tabindex="0" data-figure="rectangle">
                </div>
            </section>
            <aside>
                <h3>Pole prostokąta / pole trójkąta</h3>
                <label for="side-a">Bok prostokąta / podstawa trójkąta:</label>
                <input type="number" id="side-a" min="0" step="any">
                <label for="side-b">Drugi bok prostokąta / wysokość trójkąta:</label>
                <input type="number" id="side-b" min="0" step="any">
                <button type="button" id="calculate">Oblicz</button>
                <p id="result" aria-live="polite"></p>
            </aside>
        </main>
        <footer>
            <p>Autor: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 6 linii
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta' },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
        thumbnail.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                selectFigure(thumbnail.dataset.figure);
            }
        });
    });
    Podgląd strony po tym kroku (index.html)
  44. Krok 44: Skrypt 2: dane z pól edycyjnych

    Kryteria: ,

    R.5.4 Skrypt 2 pobiera dane z dwóch pól edycyjnych

    R.3.5 Zdefiniowane dla przycisku zdarzenie związane z jego wciśnięciem, które uruchamia funkcję skryptu (obsługa zdarzenia zdefiniowana w HTML np. onClick lub w skrypcie np.: element.addEventListener(...), element.onClick = …)

    ok. 2 min
    Polecenie z arkusza

    Skrypt 2: pobiera dane z pól edycyjnych

    calculateArea odczytuje oba pola właściwością valueAsNumber (R.5.4): pole type="number" oddaje wtedy od razu liczbę, a dla pustego pola - NaN („nie liczba”). Zwykłe value dałoby tekst „5”, a tekst przy dodawaniu skleja się zamiast sumować ("5" + "10" to „510”).

    Przycisk dostaje obsługę kliknięcia przez addEventListener (R.3.5) - bez onclick w HTML.

    skrypt.js JavaScript zmienione: 8 linii
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta' },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
        thumbnail.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                selectFigure(thumbnail.dataset.figure);
            }
        });
    });
    
    // Skrypt 2: pole wybranej figury
    function calculateArea() {
        const a = sideA.valueAsNumber;
        const b = sideB.valueAsNumber;
    }
    
    document.querySelector('#calculate').addEventListener('click', calculateArea);
    Podgląd strony po tym kroku (index.html)
  45. Krok 45: Skrypt 2: pole prostokąta

    Kryteria:

    R.5.6 Po wybraniu grafiki prostokąta skrypt liczy pole prostokąta na podstawie danych

    ok. 3 min
    Polecenie z arkusza

    Gdy w bloku głównym wybrano prostokąt (duży obraz to 2d.bmp), to na podstawie danych jest liczone pole prostokąta (ilustracja 5)

    Wzór trafia do obiektu: prostokąt dostaje funkcję area: (a, b) => a * b (R.5.6). W calculateArea wybrana figura to FIGURES[currentFigure], a jej pole - figure.area(a, b).

    Wersja podstawowa sprawdzała, która figura jest wybrana, porównując getAttribute("src") z nazwą pliku. Tu decyduje zmienna currentFigure ustawiana razem z obrazem w selectFigure - wynik jest ten sam, a skrypt nie zależy od nazw plików ani od tego, czy przeglądarka zapisze w src pełny adres.

    skrypt.js JavaScript zmienione: 3 linie
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta' },
        rectangle: { image: '2d.bmp', name: 'prostokąta', area: (a, b) => a * b },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
        thumbnail.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                selectFigure(thumbnail.dataset.figure);
            }
        });
    });
    
    // Skrypt 2: pole wybranej figury
    function calculateArea() {
        const a = sideA.valueAsNumber;
        const b = sideB.valueAsNumber;
        const figure = FIGURES[currentFigure];
        const area = figure.area(a, b);
    }
    
    document.querySelector('#calculate').addEventListener('click', calculateArea);
    Podgląd strony po tym kroku (index.html)
  46. Krok 46: Skrypt 2: pole trójkąta, także na starcie

    Kryteria:

    R.5.5 Po wybraniu grafiki trójkąta skrypt liczy pole trójkąta na podstawie danych

    ok. 2 min
    Polecenie z arkusza

    Gdy w bloku głównym wybrano trójkąt (duży obraz to 1d.bmp) to na podstawie danych jest liczone pole trójkąta (ilustracja 4)

    Trójkąt dostaje wzór (a, b) => a * b / 2 - podstawa razy wysokość przez dwa (R.5.5). W calculateArea nie zmienia się nic: drabinkę if/else zastąpił wybór wzoru z obiektu. Stan początkowy jest obsłużony od kroku ze zmienną currentFigure = 'triangle' - zanim ktokolwiek kliknie miniaturę, liczy się pole trójkąta.

    skrypt.js JavaScript zmienione: 1 linia
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta', area: (a, b) => a * b / 2 },
        rectangle: { image: '2d.bmp', name: 'prostokąta', area: (a, b) => a * b },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
        thumbnail.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                selectFigure(thumbnail.dataset.figure);
            }
        });
    });
    
    // Skrypt 2: pole wybranej figury
    function calculateArea() {
        const a = sideA.valueAsNumber;
        const b = sideB.valueAsNumber;
        const figure = FIGURES[currentFigure];
        const area = figure.area(a, b);
    }
    
    document.querySelector('#calculate').addEventListener('click', calculateArea);
    Podgląd strony po tym kroku (index.html)
  47. Krok 47: Skrypt 2: wynik w akapicie pod przyciskiem

    Kryteria: ,

    R.5.7 Wynik jest wyświetlany pod przyciskiem

    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

    Wynik wyświetlany jest w paragrafie pod przyciskiem

    Szablon tekstowy w odwrotnych apostrofach wstawia wartości w ${...}: „Pole trójkąta: 25”. Opis słowami mówi, czego dotyczy liczba - ilustracje 4 i 5 pokazują samą liczbę, a klucz ocenia, że wynik stoi pod przyciskiem (R.5.7).

    textContent zamiast innerHTML: wpisuje zwykły tekst, którego przeglądarka nie interpretuje jako HTML. Nazwy mówią, do czego służą: FIGURES, currentFigure, selectFigure, calculateArea, figureImage, result (R.5.8).

    skrypt.js JavaScript zmienione: 1 linia
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta', area: (a, b) => a * b / 2 },
        rectangle: { image: '2d.bmp', name: 'prostokąta', area: (a, b) => a * b },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
        thumbnail.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                selectFigure(thumbnail.dataset.figure);
            }
        });
    });
    
    // Skrypt 2: pole wybranej figury
    function calculateArea() {
        const a = sideA.valueAsNumber;
        const b = sideB.valueAsNumber;
        const figure = FIGURES[currentFigure];
        result.textContent = `Pole ${figure.name}: ${figure.area(a, b)}`;
    }
    
    document.querySelector('#calculate').addEventListener('click', calculateArea);
    Podgląd strony po tym kroku (index.html)
  48. Krok 48: Skrypt 2: sprawdzenie danych

    ok. 2 min
    Polecenie z arkusza

    Skrypt 2: pobiera dane z pól edycyjnych

    Wersja podstawowa z egzaminu dla pustych pól pokazuje pole 0, a dla podstawy -4 - pole -20. Warunek !(a > 0 && b > 0) łapie wszystko naraz: puste pole (NaN > 0 to fałsz), zero i liczby ujemne. Wtedy zamiast wyniku jest komunikat, a return kończy funkcję - to „wczesne wyjście”, dzięki któremu dalsza część funkcji nie potrzebuje już else.

    skrypt.js JavaScript zmienione: 4 linie
    // Skrypty strony index.html
    
    // Figury do wyboru: wszystko, czym się różnią
    const FIGURES = {
        triangle: { image: '1d.bmp', name: 'trójkąta', area: (a, b) => a * b / 2 },
        rectangle: { image: '2d.bmp', name: 'prostokąta', area: (a, b) => a * b },
    };
    
    const figureImage = document.querySelector('#figure');
    const sideA = document.querySelector('#side-a');
    const sideB = document.querySelector('#side-b');
    const result = document.querySelector('#result');
    let currentFigure = 'triangle';   // stan początkowy: duży obraz to 1d.bmp
    
    // Skrypt 1: wybór figury miniaturą
    function selectFigure(figure) {
        currentFigure = figure;
        figureImage.src = FIGURES[figure].image;
    }
    
    document.querySelectorAll('[data-figure]').forEach((thumbnail) => {
        thumbnail.addEventListener('click', () => selectFigure(thumbnail.dataset.figure));
        thumbnail.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                selectFigure(thumbnail.dataset.figure);
            }
        });
    });
    
    // Skrypt 2: pole wybranej figury
    function calculateArea() {
        const a = sideA.valueAsNumber;
        const b = sideB.valueAsNumber;
        if (!(a > 0 && b > 0)) {
            result.textContent = 'Podaj dwie liczby większe od zera.';
            return;
        }
        const figure = FIGURES[currentFigure];
        result.textContent = `Pole ${figure.name}: ${figure.area(a, b)}`;
    }
    
    document.querySelector('#calculate').addEventListener('click', calculateArea);
    Podgląd strony po tym kroku (index.html)
  49. Etap 5: Porównanie z wersją podstawową

    Kroki 49-50 · po tym etapie masz 38 z 38 kryteriów (pkt)

    Krok 49: Co jest inaczej i dlaczego

    ok. 3 min
    Polecenie z arkusza

    Ocenie będzie podlegać 5 rezultatów: animacja, zawartość witryny internetowej, działanie witryny internetowej, styl CSS witryny internetowej oraz skrypt.

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

    wersja podstawowata wersja
    układdisplay: flex na <main>, szerokości w trzech regułachdisplay: grid, grid-template-columns: 35% 30% 35%
    kolorywpisane w regułachzmienne w :root
    łamanie linii<br> w HTMLblok .thumbnails i display: block w CSS
    zdarzeniaonclick w HTMLaddEventListener w skrypt.js z defer
    wybrana figuraporównanie getAttribute("src")zmienna currentFigure i obiekt FIGURES
    wynikinnerHTML z samą liczbątextContent z opisem, aria-live
    złe danewynik 0 albo ujemnykomunikat
    klawiaturabrakTab, Enter, spacja, widoczny fokus

    W podglądzie tej wersji sprawdzone są w Chrome: kliknięcia obu miniatur, wybór Enterem i spacją, wynik 25 i 50 z ilustracji, liczba niecałkowita (2,5 × 4 = 10) oraz puste i ujemne pole.

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

  50. Krok 50: 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: onclick i getElementById są w tabeli 2 arkusza, a cały skrypt to kilkanaście linii w jednym pliku.
    • Ta wersja, gdy addEventListener, obiekty i funkcje strzałkowe są pisane z pamięci. Osobny plik skrypt.js trzeba pamiętać nagrać na płytę - bez niego miniatury i kalkulator przestaną działać.

    Mieszanie jest dopuszczalne: siatka z tej wersji i skrypt z podstawowej dadzą pełne punkty.

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

  51. Etap 6: Oddanie pracy

    Krok 51 · po tym etapie masz 38 z 38 kryteriów (pkt)

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

    ok. 5 min
    Polecenie z arkusza

    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: 1d.bmp, 1m.bmp, 2d.bmp, 2m.bmp (bez zmian z archiwum), index.html, kolo.html, kolo.gif, parametry.jpg, przeglądarka.txt, styl.css oraz skrypt.js - bez niego strona główna nie zareaguje na kliknięcia. Po nagraniu sprawdź odczyt płyty.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.