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

Rozwiązanie krok po kroku: Witryna studia tatuażu (Nowoczesny kod (grid, osobny skrypt))

To drugi sposób rozwiązania tego samego arkusza: baza studiotatuazu z czterema zapytaniami, logo przygotowane w edytorze grafiki i strona index.html z czcionką Dancing Script, galerią i formularzem „Dodaj wzór”. 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:

  • układ na siatce CSS z nazwanymi obszarami (grid-template-areas): całą mapę strony z ilustracji 3 widać w jednej regule, zamiast wynikać z kombinacji float: left, float: right i clear,
  • kolor z arkusza w zmiennej CSS, odnośniki do czcionki w jednej regule @font-face,
  • formularz bez znaczników <br> - etykiety i pola ustawia siatka w bloku bocznym,
  • skrypt w osobnym pliku skrypt.js z defer i addEventListener, sprawdzenie pustych pól od pierwszej linii, komunikat z szablonu tekstowego, klasa dodana przez classList,
  • zapytania z aliasami tabel i kolumn oraz drugim kluczem sortowania - wynik zawsze w tej samej kolejności.

Kroki nadal idą zdanie po zdaniu za treścią arkusza. Baza, wzory i czcionka pochodzą z prawdziwego archiwum pliki16, zapytania są sprawdzone na MariaDB, a skrypt w prawdziwej przeglądarce Chrome z wybranym plikiem rozeta.png.

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 studiotatuazu

    ok. 2 min
    Polecenie z arkusza

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

    Archiwum pliki16.7z ma hasło <Studio&T@tu> razem z nawiasami ostrymi - w arkuszu są pogrubione jak reszta hasła, więc łatwo je pominąć. W phpMyAdmin: Nowa, nazwa studiotatuazu (bez polskich liter), porównywanie np. utf8mb4_polish_ci - utf8mb4 mieści każdy znak Unicode, polish sortuje polskie litery na swoich miejscach.

    Typowe błędy

    Hasło bez nawiasów < i > nie otwiera archiwum - a bez niego nie ma bazy, wzorów ani czcionki.

  2. Krok 2: Import tabel z pliku studiotatuazu.sql

    ok. 2 min
    Polecenie z arkusza

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

    Zaznaczona baza studiotatuazu, Import → studiotatuazu.sql → Wykonaj. Dwie tabele z ilustracji 1: style (6 stylów) i tatuaze (22 tatuaże z kluczem obcym style_id).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabel do bazy danych studiotatuazu - plik 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 i zapis jako import.png - w tym arkuszu wszystkie zrzuty są w 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: czarne tatuaże droższe niż 100 zł

    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 wzór i cenę tatuaży, tylko dla czarnych tatuaży, których cena jest większa niż 100 zł, posortowane według ceny malejąco. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT wzor, cena FROM tatuaze WHERE kolor = "czarny" AND cena > 100 ORDER BY cena DESC; oraz na zrzucie widoczne są dane: koliber 200, anioł 200, kwiat 130

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie wzór i cenę tatuaży, dla tatuaży w kolorze czarnym, których cena jest większa niż 100 zł, posortowane według ceny malejąco

    • WHERE kolor = 'czarny' AND cena > 100 - oba warunki naraz, ostra nierówność (tygrys za 100 zł odpada),
    • ORDER BY cena DESC, wzor - malejąco według ceny, a przy równej cenie alfabetycznie według wzoru.

    Drugi klucz sortowania to drobiazg, który robi różnicę: koliber i anioł kosztują po 200 zł, a bez niego baza może je zwrócić w dowolnej kolejności - raz tak, raz inaczej. Z nim wynik jest zawsze ten sam: anioł 200, koliber 200, kwiat 130. Klucz sprawdza trzy wiersze i ich kolejność według ceny. Zapytanie trafia do kwerendy.txt, zrzut do kw1.png.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT wzor, cena
    FROM tatuaze
    WHERE kolor = 'czarny' AND cena > 100
    ORDER BY cena DESC, wzor;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: liczba tatuaży w każdym kolorze

    Kryteria:

    R.1.4 Wykonane zapytanie 2 wybierające nazwę koloru tatuażu i zliczające ile jest tatuaży danego koloru. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT kolor, COUNT(*) FROM tatuaze GROUP BY kolor; oraz na zrzucie widoczne są jedynie dane: czarny 8, czerwony 4, niebieski 3, szary 1, wielokolorowy 1, zielony 3, złoty 1, żółty 1

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające nazwę koloru tatuażu i zliczające ile jest tatuaży danego koloru. Należy zastosować grupowanie

    GROUP BY kolor - jeden wiersz na kolor, COUNT(*) - liczba tatuaży w grupie. Alias AS liczba daje kolumnie czytelny nagłówek zamiast „COUNT(*)” - przyda się też, gdyby wynik czytał skrypt PHP ($row['liczba']).

    Wynik: 8 wierszy - czarny 8, czerwony 4, niebieski 3, szary 1, wielokolorowy 1, zielony 3, złoty 1, zółty 1. Zrzut: kw2.png.

    ⚠️ Rozbieżność arkusz-klucz: w bazie z archiwum kolor zapisano jako „zółty” (bez kropki nad „z” - literówka w danych CKE), a klucz CKE podaje „żółty 1”. Zapytanie i liczby są poprawne - punkt daje zapytanie, danych nie trzeba poprawiać.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT wzor, cena
    FROM tatuaze
    WHERE kolor = 'czarny' AND cena > 100
    ORDER BY cena DESC, wzor;
    
    -- Zapytanie 2
    SELECT kolor, COUNT(*) AS liczba
    FROM tatuaze
    GROUP BY kolor;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: zielone tatuaże i ich styl

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające jedynie wzór tatuażu i odpowiadającą mu nazwę stylu dla tatuaży w kolorze zielonym. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT wzor, nazwa FROM tatuaze JOIN style ON style_id = style.id WHERE kolor = 'zielony'; (lub porównanie kluczy po WHERE ) oraz na zrzucie widoczne są dane: waz hanpoke, smok orientalne, kwiat orientalne

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie wzór tatuażu i odpowiadającą mu nazwę stylu dla tatuaży w kolorze zielonym. Należy posłużyć się relacją

    Tabele z aliasami tatuaze AS t i style AS s, każda kolumna z aliasem tabeli - od razu widać, że nazwa to nazwa stylu, a kolor należy do tatuażu.

    • JOIN style AS s ON s.id = t.style_id - relacja z ilustracji 1,
    • WHERE t.kolor = 'zielony'.

    Wynik: waz - hanpoke, smok - orientalne, kwiat - orientalne. Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT wzor, cena
    FROM tatuaze
    WHERE kolor = 'czarny' AND cena > 100
    ORDER BY cena DESC, wzor;
    
    -- Zapytanie 2
    SELECT kolor, COUNT(*) AS liczba
    FROM tatuaze
    GROUP BY kolor;
    
    -- Zapytanie 3
    SELECT t.wzor, s.nazwa
    FROM tatuaze AS t
    JOIN style AS s ON s.id = t.style_id
    WHERE t.kolor = 'zielony';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: czerwone tatuaże drożeją o 10%

    Kryteria:

    R.1.6 Wykonane zapytanie 4 aktualizujące cenę tatuażu. Cena wzrasta o 10% dla tatuaży w kolorze czerwonym. W pliku z kwerendami lub na zrzucie istnieje zapis np. UPDATE tatuaze SET cena = cena * 1.1 WHERE kolor='czerwony'; oraz na zrzucie widoczny jest komunikat o poprawnym działaniu zapytania lub zmienione ceny produktów dla koloru czerwonego

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: aktualizujące cenę tatuażu. Cena wzrasta o 10% dla tatuaży w kolorze czerwonym

    UPDATE tatuaze SET cena = cena * 1.1 WHERE kolor = 'czerwony' - nowa cena liczona ze starej. Dobry nawyk przy UPDATE: najpierw ten sam warunek w SELECT (SELECT wzor, cena FROM tatuaze WHERE kolor = 'czerwony') - widać, które wiersze się zmienią, zanim się zmienią.

    Zmienione 4 rekordy: przed zapytaniem smok 150, rozeta 60, kwiaty 40, kwiat 140, po nim 165, 66, 44 i 154. Zrzut z komunikatem „Zmodyfikowanych rekordów: 4” albo z nowymi cenami: kw4.png.

    Typowe błędy

    Bez WHERE podrożałyby wszystkie 22 tatuaże - UPDATE nie pyta o potwierdzenie.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT wzor, cena
    FROM tatuaze
    WHERE kolor = 'czarny' AND cena > 100
    ORDER BY cena DESC, wzor;
    
    -- Zapytanie 2
    SELECT kolor, COUNT(*) AS liczba
    FROM tatuaze
    GROUP BY kolor;
    
    -- Zapytanie 3
    SELECT t.wzor, s.nazwa
    FROM tatuaze AS t
    JOIN style AS s ON s.id = t.style_id
    WHERE t.kolor = 'zielony';
    
    -- Zapytanie 4
    UPDATE tatuaze
    SET cena = cena * 1.1
    WHERE kolor = 'czerwony';
    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: Logo: przycięcie do krawędzi ptaka

    ok. 2 min
    Polecenie z arkusza

    Skadrowana do krawędzi kształtu ptaka i przeskalowana z zachowaniem proporcji do wysokości 300 px

    logo.png z archiwum ma 640 × 360 px i przezroczyste tło. W GIMP-ie Obraz → Przytnij do zawartości obcina przezroczyste brzegi: zostaje 368 × 356 px, a ptak dotyka każdej krawędzi.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Logo: skala do wysokości 300 px

    Kryteria:

    R.2.1 Grafika logo.png jest skadrowana do krawędzi kształtu ptaka (sprawdzić bez powiększania ) i przeskalowana do wysokości 300 px

    ok. 2 min
    Polecenie z arkusza

    Skadrowana do krawędzi kształtu ptaka i przeskalowana z zachowaniem proporcji do wysokości 300 px

    Obraz → Skaluj obraz, łańcuch zamknięty, wysokość 300 px - szerokość wyjdzie sama, około 310 px. Najpierw kadr, potem skala: odwrotnie ptak miałby mniej niż 300 px wysokości.

    Typowe błędy

    Skalowanie z rozpiętym łańcuchem (np. do 300 × 300) spłaszcza ptaka.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Logo: litery S i T czcionką ozdobną, zrzut czcionka.jpg

    Kryteria:

    R.2.2 W grafice, w prawym dolnym rogu znajdują się litery „S” oraz „T”, litera „T” jest przesunięta w dół względem litery „S”. Wybór czcionki jest udokumentowany na zrzucie ekranu w pliku czcionka.jpg (nieistotna wielkość liter)

    ok. 4 min
    Polecenie z arkusza

    W prawym dolnym rogu należy dodać litery „S” oraz „T”, litera „T” jest przesunięta w dół względem litery „S”. Litery są zapisane dowolną dostępną czcionką ozdobną. Należy wykonać zrzut ekranu z edytora grafiki z ustawioną widoczną nazwą czcionki i zapisać pod nazwą czcionka.jpg

    Narzędzie Tekst, czcionka ozdobna, np. Freestyle Script jak na ilustracji 2. Każda litera jako osobna warstwa tekstowa - „T” łatwo przesunąć niżej niż „S”. Zrzut ekranu z widoczną nazwą czcionki w opcjach narzędzia to czcionka.jpg (R.2.2). Na koniec Plik → Wyeksportuj jako logo.png - PNG zachowuje przezroczystość.

    Typowe błędy

    Plik → Zapisz tworzy plik .xcf GIMP-a, a nie PNG - przeglądarka go nie wyświetli.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 10
  11. Krok 11: Plik index.html w HTML5, wzory i czcionka w folderze

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony index.html. Zapisana w języku HTML5

    Deklaracja <!DOCTYPE html> i szkielet strony. Do folderu z numerem zdającego trafiają wszystkie wzory PNG z archiwum oraz oba pliki czcionki: DancingScript-Regular.woff i DancingScript-Regular.woff2. Skrypt wstawia obrazy po samej nazwie pliku, więc wzory muszą leżeć obok strony.

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

    Kryteria:

    R.2.3 W pliku index.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> - razem z deklaracją HTML5 to jedno kryterium (R.2.3).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: 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>.

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

    Kryteria:

    R.2.4 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków oraz stronie nadano tytuł "Tatuaże"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Tatuaże”

    <title> - z kodowaniem jedno kryterium (R.2.4). <meta name="viewport"> każe telefonowi pokazać stronę w jego prawdziwej szerokości - 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>Tatuaże</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  15. Krok 15: 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

    Nazwa pliku: styl.css. Także reguła @font-face trafi do tego pliku, a nie do znacznika <style> (R.3.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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Bloki: dwa nagłówkowe, sekcja, boczny, stopka

    Kryteria:

    R.2.5 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header+header, section, aside, footer (dopuszcza się zastosowanie 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ą 3

    Klucz wymaga header + header, section, aside i footer (R.2.5). Kolejność w kodzie to kolejność czytania: logo, nazwa studia, galeria, formularz, stopka - tak przeczyta stronę czytnik ekranu i tak przejdzie po niej klawisz Tab. Gdzie który blok stoi na ekranie, rozstrzygnie siatka CSS, niezależnie od tej kolejności.

    index.html HTML zmienione: 10 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
        </header>
        <header id="studio">
        </header>
        <section id="gallery">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Blok nagłówkowy 1: logo

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego 1: obraz logo.png z tekstem alternatywnym „salon”

    Logo z tekstem alternatywnym. width i height z wymiarami pliku: przeglądarka rezerwuje miejsce, zanim obraz się wczyta, więc reszta strony nie podskakuje.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
        </header>
        <section id="gallery">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Blok nagłówkowy 2: nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego 2: nagłówek pierwszego stopnia o treści „Studio Tatuażu”

    <h1> w drugim bloku nagłówkowym.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Sekcja: nagłówek Galeria

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji: Nagłówek drugiego stopnia o treści „Galeria”

    <h2> na początku sekcji gallery - po tym identyfikatorze skrypt znajdzie galerię.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Sekcja: obraz smok.png z klasą miniatury

    ok. 1 min
    Polecenie z arkusza

    Obraz smok.png z tekstem alternatywnym „smok.png”, z przypisaną klasą miniatury

    Tekst alternatywny to dosłownie nazwa pliku - tak samo skrypt podpisze obrazy dodane z formularza. Klasa miniatury ma nazwę narzuconą przez arkusz.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Sekcja: obraz koliber.png z klasą miniatury

    Kryteria: ,

    R.2.7 W bloku nagłówkowym 1 znajduje się obraz z logiem z tekstem alternatywnym „salon” w bloku sekcji obrazy smok.png i koliber.png , tekst alternatywny jak nazwa pliku (rozszerzenie pliku opcjonalnie)

    R.3.5 Obrazy z bloku sekcji mają przypisaną klasę miniatury

    ok. 1 min
    Polecenie z arkusza

    Obraz koliber.png z tekstem alternatywnym „koliber.png”, z przypisaną klasą miniatury

    Drugi obraz. Z logo to komplet obrazów strony (R.2.7), oba obrazy galerii mają klasę miniatury (R.3.5).

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Blok boczny: nagłówek trzeciego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku bocznego: Nagłówek trzeciego stopnia o treści „Dodaj wzór”

    <h3> na początku bloku bocznego. Pod nim kontrolki - bez znacznika <form>, bo dane nie są nigdzie wysyłane, odczyta je skrypt.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: Etykieta „Wzór:”

    Kryteria:

    R.2.8 Przynajmniej jedna etykieta jest powiązana z kontrolką

    ok. 1 min
    Polecenie z arkusza

    Etykieta o treści „Wzór:”, powiązana z polem edycyjnym do podania nazwy pliku

    <label for="file"> - wskazuje identyfikator pola, które za chwilę powstanie (R.2.8). Bez <br>: każdą etykietę i każde pole w osobnym wierszu ustawi siatka CSS.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Pole wyboru pliku przyjmujące tylko PNG

    ok. 1 min
    Polecenie z arkusza

    Poniżej pole edycyjne do wyboru pliku w oknie dialogowym, przyjmujące jedynie obrazy w formacie PNG

    type="file" otwiera okno wyboru pliku, accept="image/png" pokazuje w nim tylko pliki PNG (ramka pod tabelą 1 arkusza). To podpowiedź dla okna - w polu „Wszystkie pliki” da się wybrać inny plik, więc prawdziwy serwis sprawdziłby typ jeszcze raz po swojej stronie.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: Etykieta „Kolor:” i lista rozwijana

    Kryteria:

    R.2.10 Pole listy rozwijanej zawiera opcje: „Czarny”, „Czerwony”, „Zielony”, „Niebieski”, użyte znaczniki <select> i <option>

    ok. 2 min
    Polecenie z arkusza

    Poniżej etykieta o treści „Kolor:”, powiązana z listą rozwijaną. Poniżej lista rozwijana z opcjami: „Czarny”, „Czerwony”, „Zielony”, „Niebieski”

    Etykieta powiązana z listą color. Opcje bez value - wartością jest tekst, więc skrypt odczyta „Zielony” z wielką literą, jak w komunikacie z ilustracji 5 (R.2.10).

    index.html HTML zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Etykieta „Cena:” i pole liczbowe

    Kryteria:

    R.3.4 Jedno pole edycyjne jest typu file z atrybutem accept="image/png" (lub accept=".png"), a drugie jest typu number

    ok. 1 min
    Polecenie z arkusza

    Poniżej etykieta o treści „Cena:”, powiązana z polem edycyjnym do wpisania ceny. Poniżej pole edycyjne typu liczbowego przeznaczone do wpisywania ceny

    type="number" - z polem pliku to kryterium R.3.4. min="1" blokuje strzałkami cenę zero i ujemną.

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Przycisk „Dodaj Wzór”

    Kryteria:

    R.2.9 W bloku bocznym znajdują się dwa pola edycyjne, pole listy rozwijanej oraz przycisk "Dodaj Wzór"

    ok. 1 min
    Polecenie z arkusza

    Poniżej przycisk o treści „Dodaj Wzór”. Wciśnięcie przycisku powoduje wywołanie skryptu

    <button type="button"> z identyfikatorem add, bez onclick - zdarzenie podepnie skrypt (klucz R.3.3 wymienia addEventListener). Blok boczny ma już oba pola edycyjne, listę i przycisk (R.2.9).

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  28. Krok 28: Stopka z autorem

    Kryteria:

    R.2.6 W bloku nagłówkowym 2 znajduje się <h1>: "Studio Tatuażu", w bloku sekcji <h2>: "Galeria", w bloku bocznym <h3>: "Dodaj wzór", w stopce <p> z numerem zdającego

    ok. 1 min
    Polecenie z arkusza

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

    Na egzaminie w miejscu imienia i nazwiska wpisuje się numer zdającego (PESEL); tu stoi „Bartosz Bryniarski”. Strona ma już wszystkie nagłówki i paragraf stopki (R.2.6).

    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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  29. Etap 3: Styl CSS

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

    Krok 29: Zmienna z kolorem i czcionka przez @font-face

    Kryteria:

    R.4.10 Czcionka Dancing Script działa na stronie, w stylach zdefiniowano dyrektywę @font-face, z rzeczywistymi ścieżkami URL w obu przypadkach

    ok. 3 min
    Polecenie z arkusza

    Styl CSS korzysta z kroju czcionki Dancing Script znajdującej się w folderze czcionki. Czcionkę należy dodać do projektu i zdefiniować jej stosowanie dla wariantu regular (normal). W pliku styl.css należy zapisać reguły dla czcionki. Przykład znajduje się w pliku stylesheet.css

    Zmienna --color-rose z kolorem trzech bloków. Reguła @font-face rejestruje czcionkę „Dancing Script”: wzór to stylesheet.css z folderu czcionki, z poprawionymi ścieżkami - pliki czcionki leżą obok styl.css, więc w url() są same nazwy. woff2 pierwszy (mniejszy), woff dla starszych przeglądarek; font-weight i font-style normal to wariant regular (R.4.10).

    Jedna linia ponad wzór: font-display: swap. Dopóki plik czcionki się pobiera, tekst jest pokazany krojem zapasowym, a potem podmieniony - bez tej linii przeglądarka może przez chwilę nie pokazywać napisów wcale.

    Typowe błędy

    Ścieżka url("czcionki/...") przy plikach leżących obok strony (albo odwrotnie) nie wczytuje czcionki - strona pokazuje krój zapasowy i R.4.10 przepada.

    styl.css CSS nowy plik
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Ciało strony: czcionka, rozmiar, wyśrodkowanie

    Kryteria:

    R.4.1 styl selektora body: krój czcionki "Dancing Script", serif (dozwolona tylko taka kolejność ), rozmiar czcionki 120%, wyrównanie tekstu do środka

    ok. 1 min
    Polecenie z arkusza

    Dla selektora ciała strony: krój czcionki Dancing Script, w przypadku braku serif, rozmiar czcionki 120%, wyrównanie tekstu do środka

    Nazwa w font-family taka jak w @font-face, a serif jako rodzina zapasowa - klucz uznaje tylko tę kolejność. Selektor znacznika body, jak każe uwaga arkusza (R.4.1).

    styl.css CSS zmienione: 5 linii
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  31. Krok 31: Układ bloków: siatka z nazwanymi obszarami

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 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)

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

    Druga reguła dla body włącza siatkę i rysuje ilustrację 3 dosłownie:

    • grid-template-columns: 30% 70% - dwie kolumny o szerokościach z arkusza (klucz R.4.3 wymienia wprost grid-template-columns jako sposób na szerokości),
    • grid-template-areas - mapa strony, wiersz po wierszu: logo zajmuje dwa wiersze po lewej, obok nazwa studia, a pod nią galeria, która sięga w dół obok bloku bocznego; stopka na całą szerokość,
    • grid-area przypisuje każdy blok do obszaru mapy,
    • align-items: start - bloki trzymają swoją wysokość z arkusza i nie rozciągają się do wysokości wiersza,
    • #logo img { max-width: 100%; height: auto; } - na wąskim oknie kolumna 30% bywa węższa niż logo (310 px); obraz zmniejsza się wtedy do szerokości kolumny i zachowuje proporcje, zamiast wystawać na nazwę studia. height: auto jest potrzebne, bo znacznik <img> ma atrybut height.

    W wersji podstawowej ten sam układ wynika z float: left dla lewej kolumny, float: right dla prawej i clear: both dla stopki - działa, ale trzeba wiedzieć, jak pływające bloki się układają. Tu mapa stoi w kodzie i zmiana układu to przestawienie nazw w grid-template-areas, bez ruszania HTML.

    styl.css CSS zmienione: 29 linii
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Bloki nagłówkowe i boczny: tło

    Kryteria:

    R.4.2 kolor tła: oba bloki nagłówkowe, blok boczny - RosyBrown

    ok. 1 min
    Polecenie z arkusza

    Dla bloków nagłówkowego 1 i bocznego: kolor tła RosyBrown, szerokość 30%

    Tło RosyBrown ze zmiennej dla obu bloków nagłówkowych i bloku bocznego (R.4.2) - arkusz podaje ten kolor dla nagłówka 1 i bocznego, a w następnym zdaniu dla nagłówka 2, więc jedna reguła obejmuje wszystkie trzy. Szerokości 30% nie trzeba już wpisywać - daje ją pierwsza kolumna siatki.

    styl.css CSS zmienione: 3 linie
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    #logo, #studio, aside {
        background-color: var(--color-rose);
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Blok boczny: tekst do lewej, wysokość

    Kryteria:

    R.4.5 wyrównanie tekstu: blok boczny - do lewej strony

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku bocznego: wyrównanie tekstu do lewej strony, wysokość 350 px

    text-align: left nadpisuje wyśrodkowanie odziedziczone z body (R.4.5).

    styl.css CSS zmienione: 4 linie
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    #logo, #studio, aside {
        background-color: var(--color-rose);
    }
    aside {
        text-align: left;
        height: 350px;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Blok nagłówkowy 2: wysokość

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nagłówkowego 2: kolor tła RosyBrown, szerokość 70%, wysokość 100 px

    Tło jest już ze wspólnej reguły, szerokość 70% z drugiej kolumny siatki - zostaje wysokość 100 px.

    styl.css CSS zmienione: 3 linie
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    #logo, #studio, aside {
        background-color: var(--color-rose);
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        height: 100px;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Sekcja: wysokość i paski przewijania

    Kryteria: , ,

    R.4.3 szerokość: blok nagłówkowy 1, boczny - 30%, blok nagłówkowy 2, blok sekcji - 70% (width lub grid-template-columns lub flex )

    R.4.4 wysokość: blok nagłówkowy 2 - 100px, blok boczny - 350px, blok sekcji - 550px

    R.4.6 paski przewijania: blok sekcji - scroll

    ok. 2 min
    Polecenie z arkusza

    Dla bloku sekcji: szerokość 70%, wysokość 550 px, paski przewijania zawsze widoczne

    „Zawsze widoczne” to overflow: scroll (R.4.6) - auto pokazałby paski dopiero po przepełnieniu. Szerokość 70% daje kolumna siatki. Komplet szerokości (30% i 70% w grid-template-columns) i wysokości z klucza (100, 350 i 550 px) jest na miejscu (R.4.3, R.4.4).

    styl.css CSS zmienione: 4 linie
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    #logo, #studio, aside {
        background-color: var(--color-rose);
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        height: 100px;
    }
    section {
        height: 550px;
        overflow: scroll;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Formularz: siatka w bloku bocznym i wysokość linii etykiet

    Kryteria:

    R.4.7 wysokość linii: selektor label - 50px (line-height)

    ok. 2 min
    Polecenie z arkusza

    Dla selektora etykiety: wysokość linii 50 px

    label { line-height: 50px; } rozsuwa formularz w pionie (R.4.7). Dodatkowo blok boczny dostaje własną siatkę: każda etykieta, pole, lista i przycisk to osobny wiersz - ten sam efekt, co znaczniki <br> w wersji podstawowej. justify-items: start dosuwa kontrolki do lewej i nie rozciąga ich, a align-content: start trzyma je przy górze bloku o stałej wysokości 350 px. Siatki można zagnieżdżać: aside jest jednocześnie obszarem siatki strony i siatką dla swoich kontrolek.

    styl.css CSS zmienione: 8 linii
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    #logo, #studio, aside {
        background-color: var(--color-rose);
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        height: 100px;
    }
    section {
        height: 550px;
        overflow: scroll;
    }
    aside {
        display: grid;
        justify-items: start;
        align-content: start;
    }
    label {
        line-height: 50px;
    }
    Podgląd strony po tym kroku (index.html)
  37. Krok 37: Klasa miniatury i powiększenie pod kursorem

    Kryteria: ,

    R.4.8 styl klasy .miniatury : szerokość 150px

    R.4.9 gdy kursor znajdzie się na elemencie z przypisaną klasą miniatury , kolor jego tła zmienia się na Bisque, a szerokość na 200px. Widoczna jest animacja powiększania się elementu (transition: width 1s;)

    ok. 2 min
    Polecenie z arkusza

    Dla klasy miniatury przypisanej do obrazów generowanych skryptem: szerokość 150 px. W momencie, gdy kursor znajdzie się na elemencie z przypisaną klasą miniatury, kolor jego tła zmienia się na Bisque, a szerokość na 200 px. Zmiana szerokości ma zdefiniowane przejście z czasem trwania 1 s (ilustracja 4)

    .miniatury - szerokość 150 px (R.4.8). transition: width 1s stoi w zwykłej regule, nie w :hover: przejście działa wtedy w obie strony, obraz płynnie rośnie i płynnie wraca. :hover zmienia tło (widać je w przezroczystych miejscach PNG) i szerokość (R.4.9).

    styl.css CSS zmienione: 8 linii
    :root {
        --color-rose: RosyBrown;
    }
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
        font-display: swap;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    body {
        display: grid;
        grid-template-columns: 30% 70%;
        grid-template-areas:
            "logo   studio"
            "logo   gallery"
            "aside  gallery"
            "footer footer";
        align-items: start;
    }
    #logo {
        grid-area: logo;
    }
    #logo img {
        max-width: 100%;
        height: auto;
    }
    #studio {
        grid-area: studio;
    }
    #gallery {
        grid-area: gallery;
    }
    aside {
        grid-area: aside;
    }
    footer {
        grid-area: footer;
    }
    #logo, #studio, aside {
        background-color: var(--color-rose);
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        height: 100px;
    }
    section {
        height: 550px;
        overflow: scroll;
    }
    aside {
        display: grid;
        justify-items: start;
        align-content: start;
    }
    label {
        line-height: 50px;
    }
    .miniatury {
        width: 150px;
        transition: width 1s;
    }
    .miniatury:hover {
        background-color: Bisque;
        width: 200px;
    }
    Podgląd strony po tym kroku (index.html)
  38. Etap 4: JavaScript

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

    Krok 38: Plik skrypt.js z defer: odczyt danych z kontrolek

    Kryteria: , ,

    R.3.3 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 = …)

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

    R.5.2 Skrypt pobiera dane z przynajmniej jednej kontrolki, np. zastosowano funkcję document.getElementById z parametrem, który zdefiniowano w kontrolce jako id

    ok. 3 min
    Polecenie z arkusza

    Wykonywany po stronie klienta, po kliknięciu przycisku. Pobiera dane z kontrolek

    Skrypt w pliku skrypt.js, dołączonym w <head> z defer - uruchamia się po wczytaniu całego HTML. Na górze stałe const z odnośnikami do kontrolek i galerii, znalezione raz. addEventListener('click', addPattern) podpina funkcję pod przycisk (R.3.3). W funkcji .value odczytuje ścieżkę pliku, kolor i cenę (R.5.1, 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>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript nowy plik
    const fileInput = document.querySelector('#file');
    const colorSelect = document.querySelector('#color');
    const priceInput = document.querySelector('#price');
    const gallery = document.querySelector('#gallery');
    
    function addPattern() {
        const path = fileInput.value;
        const color = colorSelect.value;
        const price = priceInput.value;
    }
    
    document.querySelector('#add').addEventListener('click', addPattern);
    Podgląd strony po tym kroku (index.html)
  39. Krok 39: Sprawdzenie pustych pól

    ok. 2 min
    Polecenie z arkusza

    Pobiera dane z kontrolek

    Pole pliku bez wybranego pliku i puste pole ceny oddają pusty napis. Wtedy komunikat i return - funkcja kończy się, zanim cokolwiek doda do galerii. Bez tego sprawdzenia wersja podstawowa pokazuje „Wzór: , kolor Czarny w cenie zł” i dokłada do galerii pusty obraz (sprawdzone w Chrome).

    index.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 4 linie
    const fileInput = document.querySelector('#file');
    const colorSelect = document.querySelector('#color');
    const priceInput = document.querySelector('#price');
    const gallery = document.querySelector('#gallery');
    
    function addPattern() {
        const path = fileInput.value;
        const color = colorSelect.value;
        const price = priceInput.value;
        if (path === '' || price === '') {
            alert('Wybierz plik wzoru i wpisz cenę.');
            return;
        }
    }
    
    document.querySelector('#add').addEventListener('click', addPattern);
    Podgląd strony po tym kroku (index.html)
  40. Krok 40: Nazwa pliku bez ścieżki dostępu

    Kryteria:

    R.5.3 Nazwa pliku jest ustalana poprzez usunięcie ścieżki dostępu

    ok. 2 min
    Polecenie z arkusza

    Ustala nazwę pliku (bez ścieżki dostępu) na podstawie wartości przekazanej z pola do wyboru pliku

    Pole pliku oddaje C:\fakepath\rozeta.png (ramka pod tabelą 1). Funkcja fileNameFromPath:

    • split(/[\\/]/) tnie napis na kawałkach przy każdym ukośniku - wyrażenie regularne [\\/] oznacza „ukośnik wsteczny albo zwykły”, więc działa też ze ścieżkami w stylu Linuksa,
    • pop() bierze ostatni kawałek, czyli nazwę pliku: rozeta.png (R.5.3).

    Osobna funkcja z nazwą mówiącą, co robi, czyta się lepiej niż substring z lastIndexOf w środku addPattern.

    index.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 5 linii
    const fileInput = document.querySelector('#file');
    const colorSelect = document.querySelector('#color');
    const priceInput = document.querySelector('#price');
    const gallery = document.querySelector('#gallery');
    
    function fileNameFromPath(path) {
        return path.split(/[\\/]/).pop();
    }
    
    function addPattern() {
        const path = fileInput.value;
        const color = colorSelect.value;
        const price = priceInput.value;
        if (path === '' || price === '') {
            alert('Wybierz plik wzoru i wpisz cenę.');
            return;
        }
        const fileName = fileNameFromPath(path);
    }
    
    document.querySelector('#add').addEventListener('click', addPattern);
    Podgląd strony po tym kroku (index.html)
  41. Krok 41: Komunikat z nazwą pliku, kolorem i ceną

    Kryteria:

    R.5.4 Skrypt wyświetla komunikat: "Wzór: <nazwaPliku>, kolor <kolor> w cenie <cena> zł", gdzie wartości pól <> pobrano z kontrolek (nazwa pliku ze ścieżką lub bez)

    ok. 2 min
    Polecenie z arkusza

    Wyświetla komunikat: "Wzór: <nazwaPliku>, kolor <kolor> w cenie <cena> zł" gdzie pola <> pobrano z kontrolek oraz nazwa pliku nie zawiera ścieżki dostępu (Ilustracja 5)

    alert z szablonem tekstowym: odwrotne apostrofy i wartości w ${...} - zdanie wygląda jak gotowy komunikat, spacje i przecinki stoją tam, gdzie w arkuszu. Dla rozeta.png, koloru „Zielony” i ceny 70: „Wzór: rozeta.png, kolor Zielony w cenie 70 zł” (R.5.4).

    index.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 1 linia
    const fileInput = document.querySelector('#file');
    const colorSelect = document.querySelector('#color');
    const priceInput = document.querySelector('#price');
    const gallery = document.querySelector('#gallery');
    
    function fileNameFromPath(path) {
        return path.split(/[\\/]/).pop();
    }
    
    function addPattern() {
        const path = fileInput.value;
        const color = colorSelect.value;
        const price = priceInput.value;
        if (path === '' || price === '') {
            alert('Wybierz plik wzoru i wpisz cenę.');
            return;
        }
        const fileName = fileNameFromPath(path);
        alert(`Wzór: ${fileName}, kolor ${color} w cenie ${price} zł`);
    }
    
    document.querySelector('#add').addEventListener('click', addPattern);
    Podgląd strony po tym kroku (index.html)
  42. Krok 42: Nowy obraz z nazwą pliku i klasą miniatury

    Kryteria: ,

    R.5.5 Skrypt tworzy element img ze źródłem i tekstem alternatywnym jak nazwa pliku (nazwa pliku ze ścieżką lub bez)

    R.5.7 Utworzony element img ma przypisaną klasę miniatury (sprawdzić w inspektorze)

    ok. 2 min
    Polecenie z arkusza

    Tworzy element obrazu i dodaje go do bloku sekcji (ilustracja 6): Źródłem i tekstem alternatywnym jest nazwa pliku. Obraz ma przypisaną klasę miniatury

    document.createElement('img') tworzy obraz w pamięci, src i alt to nazwa pliku bez ścieżki (R.5.5). classList.add('miniatury') dokłada klasę do listy klas elementu - w przeciwieństwie do className = '...' nie kasuje klas, które element już ma (R.5.7).

    index.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 4 linie
    const fileInput = document.querySelector('#file');
    const colorSelect = document.querySelector('#color');
    const priceInput = document.querySelector('#price');
    const gallery = document.querySelector('#gallery');
    
    function fileNameFromPath(path) {
        return path.split(/[\\/]/).pop();
    }
    
    function addPattern() {
        const path = fileInput.value;
        const color = colorSelect.value;
        const price = priceInput.value;
        if (path === '' || price === '') {
            alert('Wybierz plik wzoru i wpisz cenę.');
            return;
        }
        const fileName = fileNameFromPath(path);
        alert(`Wzór: ${fileName}, kolor ${color} w cenie ${price} zł`);
        const image = document.createElement('img');
        image.src = fileName;
        image.alt = fileName;
        image.classList.add('miniatury');
    }
    
    document.querySelector('#add').addEventListener('click', addPattern);
    Podgląd strony po tym kroku (index.html)
  43. Krok 43: Dodanie obrazu do galerii

    Kryteria: ,

    R.5.6 Utworzony element img jest wyświetlany w bloku sekcji

    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. 1 min
    Polecenie z arkusza

    Tworzy element obrazu i dodaje go do bloku sekcji (ilustracja 6)

    append wstawia obraz na koniec sekcji gallery, za smokiem, kolibrem i wcześniej dodanymi wzorami (R.5.6). To nowsza wersja appendChild - przyjmuje też kilka elementów naraz i zwykły tekst. Gdy obrazy się nie mieszczą, sekcja się przewija. Nazwy mówią, co robią: fileNameFromPath, addPattern, fileName, color, price, image, gallery (R.5.8).

    index.html HTML zmienione: 0 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
        <script src="skrypt.js" defer></script>
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon" width="310" height="300">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label>
            <input type="file" id="file" accept="image/png">
            <label for="color">Kolor:</label>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select>
            <label for="price">Cena:</label>
            <input type="number" id="price" min="1">
            <button type="button" id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    skrypt.js JavaScript zmienione: 1 linia
    const fileInput = document.querySelector('#file');
    const colorSelect = document.querySelector('#color');
    const priceInput = document.querySelector('#price');
    const gallery = document.querySelector('#gallery');
    
    function fileNameFromPath(path) {
        return path.split(/[\\/]/).pop();
    }
    
    function addPattern() {
        const path = fileInput.value;
        const color = colorSelect.value;
        const price = priceInput.value;
        if (path === '' || price === '') {
            alert('Wybierz plik wzoru i wpisz cenę.');
            return;
        }
        const fileName = fileNameFromPath(path);
        alert(`Wzór: ${fileName}, kolor ${color} w cenie ${price} zł`);
        const image = document.createElement('img');
        image.src = fileName;
        image.alt = fileName;
        image.classList.add('miniatury');
        gallery.append(image);
    }
    
    document.querySelector('#add').addEventListener('click', addPattern);
    Podgląd strony po tym kroku (index.html)
  44. Etap 5: Porównanie z wersją podstawową

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

    Krok 44: 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 oraz skrypt.

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

    wersja podstawowata wersja
    układfloat: left / float: right, clear: bothgrid-template-areas na body
    szerokości blokówwidth: 30% i width: 70%grid-template-columns: 30% 70%
    formularz<br> po każdej kontrolcesiatka w bloku bocznym
    zdarzenieonclick w HTML, skrypt w <script>addEventListener w skrypt.js z defer
    puste polakomunikat bez danych i pusty obraz w galeriiprośba o dane, nic nie jest dodawane
    nazwa plikusubstring + lastIndexOffunkcja fileNameFromPath ze split i pop
    klasa obrazuclassNameclassList.add
    SQLzapytania w jednej liniialiasy, drugi klucz sortowania, klauzule w liniach

    Wersja podstawowa w etapie „Dobre praktyki” bierze nazwę pliku wprost z obiektu File (files[0].name). Tu zostaje odczyt ze ścieżki, bo klucz R.5.3 ocenia właśnie usunięcie ścieżki dostępu.

    Skrypt i układ tej wersji są sprawdzone w prawdziwym Chrome: komunikat z ilustracji 5, nowa miniatura w galerii, puste pola i położenie każdego bloku na siatce.

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

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

    ok. 2 min
    Polecenie z arkusza

    Czas przeznaczony na wykonanie zadania wynosi 150 minut.

    • Wersja podstawowa, gdy float jest opanowany, a liczy się czas - skrypt z funkcjami z tabeli 1 pisze się najszybciej.
    • Ta wersja, gdy siatkę CSS pisze się z pamięci: grid-template-areas jest krótszy niż szukanie, dlaczego pływający blok spadł pod sąsiada. Plik skrypt.js trzeba nagrać na płytę razem z resztą.

    Mieszanie też daje pełne punkty - na przykład siatka z tej wersji i skrypt z podstawowej.

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

  46. Etap 6: Oddanie pracy

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

    Krok 46: 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: wszystkie wzory PNG, czcionka.jpg, oba pliki czcionki, import.png, index.html, kw1.png - kw4.png, kwerendy.txt, logo.png, przeglądarka.txt, styl.css i skrypt.js. Po nagraniu trzeba sprawdzić odczyt płyty i opisać ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.