Projektowanie stron i Frontend (HTML5 i CSS3)
Znaczniki strukturalne i semantyczne HTML, formularze, multimedia, selektory CSS, model pudełkowy (Box Model), pozycjonowanie, tworzenie layoutów (Flexbox, Grid), responsywność (RWD, Media Queries)
Wstęp: frontend to dział, w którym punkty daje precyzja
W części praktycznej INF.03 arkusz podaje makietę strony i listę wymagań:
„nagłówek o wysokości 100 px", „menu wyrównane do prawej", „formularz
wysyłający dane metodą POST". Egzaminator nie ocenia, czy strona jest ładna —
ocenia, czy każdy punkt z listy da się zobaczyć w przeglądarce i znaleźć
w kodzie. W części pisemnej pytania są jeszcze bardziej dosłowne: który
selektor ma wyższą specyficzność, ile wyniesie szerokość elementu przy
ustawieniu box-sizing: border-box,
który znacznik jest liniowy. Ten dział jest w całości do wyuczenia na pamięć
i w całości do policzenia.
📋 Spis treści
1
Szkielet dokumentu HTML5
Każde zadanie praktyczne zaczyna się tak samo: masz utworzyć plik
index.html
z poprawnym szkieletem. Ten szkielet musisz umieć napisać z pamięci w minutę,
bo za brak deklaracji typu dokumentu albo kodowania znaków traci się punkty
jeszcze zanim zacznie się właściwa strona.
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Krotki opis strony dla wyszukiwarek">
<title>Serwis komputerowy - strona glowna</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Serwis komputerowy</h1>
</header>
<nav>
<ul>
<li><a href="index.html">Strona glowna</a></li>
<li><a href="uslugi.html">Uslugi</a></li>
<li><a href="kontakt.html">Kontakt</a></li>
</ul>
</nav>
<main>
<article>
<h2>Naprawa laptopow</h2>
<p>Diagnostyka w 24 godziny.</p>
</article>
</main>
<aside>
<h3>Godziny otwarcia</h3>
<p>Pon-Pt 9:00-17:00</p>
</aside>
<footer>
<p>Copyright 2026 Serwis komputerowy</p>
</footer>
</body>
</html>
<!DOCTYPE html>
to deklaracja typu dokumentu, a nie znacznik. Musi stać w pierwszej linii,
przed <html>.
Jej brak przełącza przeglądarkę w tryb zgodności wstecznej (quirks mode),
w którym model pudełkowy liczony jest inaczej i strona rozjeżdża się bez
widocznej przyczyny.
<meta charset="UTF-8">
ustawia kodowanie znaków. Bez niego polskie znaki diakrytyczne wyświetlą
się jako krzaczki. Musi stać jak najwyżej w sekcji
<head>.
Uwaga: sam plik też trzeba zapisać w UTF-8 — deklaracja nie naprawi pliku
zapisanego w Windows-1250.
width=device-width, initial-scale=1.0
mówi przeglądarce mobilnej, żeby traktowała szerokość okna jako szerokość
urządzenia i nie skalowała strony. Bez tego znacznika media queries
w praktyce nie zadziałają na telefonie — to warunek konieczny RWD.
<title>— tekst na karcie przeglądarki i w wynikach wyszukiwania. Jedyny element sekcji head widoczny dla użytkownika. Jest obowiązkowy.<link rel="stylesheet" href="style.css">— dołączenie zewnętrznego arkusza stylów. Znacznik pusty, bez zamknięcia.<script src="skrypt.js" defer></script>— skrypt JavaScript; atrybut defer odracza wykonanie do czasu zbudowania drzewa dokumentu. Znacznik <style> to wewnętrzny arkusz stylów, a <link rel="icon"> — ikona na karcie.- Atrybut
lang="pl"w znaczniku<html>deklaruje język treści — korzystają z niego czytniki ekranowe i wyszukiwarki.
Znaczniki puste (samozamykające)
Nie mają treści ani znacznika zamykającego:
<br>,
<hr>,
<img>,
<input>,
<meta>,
<link>.
W HTML5 zapis z ukośnikiem na końcu jest dopuszczalny, ale zbędny. Napisanie
</img>
to błąd składniowy.
2
Znaczniki semantyczne, blokowe i liniowe
Semantyka to nadawanie znaczenia fragmentom strony. Wizualnie
<header>
niczym nie różni się od zwykłego kontenera, ale wyszukiwarka i czytnik
ekranowy wiedzą, że to nagłówek strony. Egzamin regularnie każe „zastąpić
znaczniki ogólne odpowiednimi znacznikami semantycznymi HTML5" — trzeba znać
ich listę i przeznaczenie.
| Znacznik | Do czego służy | Częsty błąd |
|---|---|---|
| <header> | Nagłówek strony lub sekcji: logo, tytuł, podtytuł. | Mylenie z <head>. Head jest niewidoczny, header leży w body. |
| <nav> | Blok nawigacji: menu główne, spis treści, okruszki. | Wrzucanie do niego każdego odnośnika. Pojedynczy link w akapicie to nie nawigacja. |
| <main> | Główna, unikalna treść dokumentu. | Użycie kilka razy. Element main może wystąpić w dokumencie tylko raz. |
| <section> | Tematycznie spójna sekcja, zwykle z własnym nagłówkiem. | Traktowanie jak kontenera do stylowania. Do tego służy <div>. |
| <article> | Samodzielna treść, sensowna po wyjęciu ze strony: wpis bloga, ogłoszenie, komentarz. | Mylenie z <section>. Test: czy da się to opublikować osobno? |
| <aside> | Treść poboczna: pasek boczny, reklama, notka na marginesie. | Utożsamianie z „kolumną po prawej". To znaczenie, nie położenie. |
| <footer> | Stopka strony lub sekcji: prawa autorskie, kontakt, autor wpisu. | Przekonanie, że może być tylko jedna. Własną stopkę może mieć każdy article. |
| <figure> | Ilustracja, schemat lub listing wraz z podpisem. | Podpis wpisany jako <p> zamiast <figcaption>. |
| <div> | Kontener bez znaczenia — wyłącznie do grupowania i stylowania. | Budowanie z niego całej strony mimo istnienia odpowiedników semantycznych. |
<figure>
<img src="plyta.jpg" alt="Plyta glowna ATX z opisanymi zlaczami">
<figcaption>Rys. 1. Rozmieszczenie zlaczy na plycie ATX</figcaption>
</figure>
Zaczynają się od nowej linii i domyślnie zajmują całą dostępną szerokość rodzica. Przyjmują szerokość, wysokość oraz wszystkie marginesy i dopełnienia.
div, p, h1–h6, ul, ol, li, table, form, header, nav, main, section, article, aside, footer, figure, blockquote, hr
Płyną w linii tekstu i zajmują tylko tyle miejsca, ile potrzebuje ich treść. Ignorują ustawienia szerokości i wysokości oraz marginesy górny i dolny.
span, a, strong, em, b, i, img, input, label, button, small, sub, sup, code, br
Podział na blokowe i liniowe to tylko wartość domyślna. Zmienia się ją
właściwością display:
block,
inline,
inline-block,
flex,
grid,
none.
Wartość inline-block
to hybryda: element stoi w linii jak liniowy, ale przyjmuje wymiary jak
blokowy. To klasyczne rozwiązanie dla poziomego menu zbudowanego z listy.
Uwaga na różnicę: display: none
usuwa element z układu (miejsce po nim znika), a
visibility: hidden
tylko go ukrywa — puste miejsce zostaje. To pytanie pojawia się regularnie.
3
Formularze i typy pól
Formularz to most między frontendem a PHP. Na egzaminie praktycznym prawie
zawsze trzeba zbudować formularz, wysłać go metodą POST i odebrać dane
w skrypcie. Kluczowa zasada: pole bez atrybutu
name
nie zostanie wysłane. To najczęstsza przyczyna sytuacji „formularz
działa, ale skrypt nic nie dostaje".
<form action="zapisz.php" method="post">
<label for="imie">Imie i nazwisko:</label>
<input type="text" id="imie" name="imie" placeholder="Jan Kowalski" required>
<label for="mail">Adres e-mail:</label>
<input type="email" id="mail" name="email" required>
<label for="haslo">Haslo:</label>
<input type="password" id="haslo" name="haslo" minlength="8" required>
<label for="wiek">Wiek:</label>
<input type="number" id="wiek" name="wiek" min="18" max="99" step="1">
<label for="data">Data zgloszenia:</label>
<input type="date" id="data" name="data">
<label for="usluga">Rodzaj uslugi:</label>
<select id="usluga" name="usluga">
<option value="">-- wybierz --</option>
<option value="diagnostyka">Diagnostyka</option>
<option value="naprawa" selected>Naprawa</option>
<option value="czyszczenie">Czyszczenie</option>
</select>
<p>Priorytet zlecenia:</p>
<input type="radio" id="p1" name="priorytet" value="normalny" checked>
<label for="p1">Normalny</label>
<input type="radio" id="p2" name="priorytet" value="pilny">
<label for="p2">Pilny</label>
<input type="checkbox" id="regulamin" name="regulamin" value="tak" required>
<label for="regulamin">Akceptuje regulamin</label>
<label for="opis">Opis usterki:</label>
<textarea id="opis" name="opis" rows="5" cols="40"
placeholder="Opisz objawy"></textarea>
<input type="hidden" name="zrodlo" value="strona-www">
<button type="submit">Wyslij zgloszenie</button>
<button type="reset">Wyczysc</button>
</form>
- action — adres skryptu, który odbierze dane. Pusty lub pominięty oznacza wysyłkę do tej samej strony.
- method —
getalbopost. Domyślnie GET. - enctype — przy wysyłce plików konieczne
multipart/form-data. - novalidate — wyłącza wbudowaną walidację przeglądarki.
- target — gdzie otworzyć odpowiedź, np.
_blank.
- GET — dane doklejane do adresu po znaku zapytania, widoczne w pasku i w historii, ograniczona długość. Nadaje się do wyszukiwarek i filtrów, bo taki adres da się zapisać w zakładkach.
- POST — dane w treści żądania, niewidoczne w adresie, brak praktycznego limitu długości, obsługa plików. Do logowania, rejestracji i zapisu do bazy.
- POST nie jest szyfrowany — jest tylko niewidoczny w adresie. Poufność daje dopiero HTTPS. To ulubione pytanie-pułapka.
- W PHP dane odbierasz z tablicy superglobalnej GET albo POST, indeksując ją wartością atrybutu name.
| type | Efekt | Uwagi |
|---|---|---|
| text | Jednoliniowe pole tekstowe | Wartość przyjmowana, gdy pominiesz atrybut type |
| password | Znaki maskowane kropkami | Maskuje tylko wygląd; bez HTTPS dane lecą jawnie |
| Walidacja formatu adresu | Na telefonie zmienia układ klawiatury | |
| number | Pole liczbowe ze strzałkami | Współpracuje z atrybutami min, max, step |
| radio | Wybór jednej opcji z grupy | Wszystkie pola grupy muszą mieć ten sam name i różne value |
| checkbox | Pole wielokrotnego wyboru | Niezaznaczone nie jest wysyłane w ogóle |
| date / time | Kalendarz lub zegar | Data wysyłana w formacie rok-miesiąc-dzień |
| file | Wybór pliku z dysku | Wymaga enctype multipart/form-data w znaczniku form |
| hidden | Pole ukryte przed użytkownikiem | Widoczne w kodzie źródłowym — nie na dane wrażliwe |
| range / color | Suwak / próbnik koloru | Kolor wysyłany jako zapis szesnastkowy |
| submit / reset | Wysłanie / wyczyszczenie formularza | Alternatywnie znacznik button z atrybutem type |
id identyfikuje element w dokumencie i musi być unikalny. name to nazwa, pod jaką dane trafią do skryptu na serwerze. Atrybut for w znaczniku label wskazuje id pola, a nie jego name. Poprawnie połączona etykieta sprawia, że kliknięcie w tekst ustawia kursor w polu i zaznacza pole wyboru — to również kryterium oceny dostępności.
Różnica pól tekstowych: <input type="text">
jest jednoliniowe, puste i ma wartość w atrybucie
value. Natomiast
<textarea>
jest wieloliniowe, ma znacznik zamykający, a treść domyślną wpisuje się
między znacznikami — nie w atrybucie value.
placeholder to podpowiedź znikająca po kliknięciu — nie zastępuje etykiety i nie jest wysyłana jako wartość pola. Z kolei required blokuje wysłanie pustego pola po stronie przeglądarki, ale walidację i tak trzeba powtórzyć w PHP — użytkownik może wysłać żądanie z pominięciem formularza.
4
Multimedia i tabele
Obrazy, dźwięk i film w HTML5 wstawia się bez żadnych wtyczek. Punktowanym
szczegółem jest zawsze atrybut
alt
przy obrazie oraz podanie kilku formatów źródłowych dla audio i wideo.
<!-- Obraz: alt jest obowiazkowy -->
<img src="img/serwis.jpg" alt="Technik naprawiajacy laptopa" width="600" height="400">
<!-- Audio -->
<audio controls loop>
<source src="dzwiek.mp3" type="audio/mpeg">
<source src="dzwiek.ogg" type="audio/ogg">
Twoja przegladarka nie obsluguje odtwarzacza audio.
</audio>
<!-- Wideo -->
<video width="640" height="360" controls poster="miniatura.jpg" muted>
<source src="film.mp4" type="video/mp4">
<source src="film.webm" type="video/webm">
Twoja przegladarka nie obsluguje odtwarzacza wideo.
</video>
- alt — tekst alternatywny czytany przez czytniki ekranowe i wyświetlany, gdy plik się nie wczyta. Wymagany przez standard; dla grafiki czysto dekoracyjnej zostawia się go pustym.
- title — dymek po najechaniu kursorem; to nie jest zamiennik atrybutu alt. width i height podane w kodzie rezerwują miejsce i zapobiegają przeskakiwaniu treści podczas ładowania.
- Formaty: JPG — zdjęcia, kompresja stratna; PNG — grafika z przezroczystością, bezstratna; GIF — animacje, 256 kolorów; SVG — grafika wektorowa, skaluje się bez utraty jakości; WebP — nowoczesny, mniejszy od JPG i PNG.
- controls — pokazuje panel sterowania. Bez niego użytkownik nie ma jak włączyć odtwarzania.
- autoplay — automatyczne odtwarzanie. Przeglądarki blokują je, jeśli nie towarzyszy mu muted.
- loop — zapętlenie; preload — strategia wczytywania danych.
- poster (tylko wideo) — obrazek wyświetlany przed startem odtwarzania.
- Kilka znaczników source pozwala przeglądarce wybrać obsługiwany format. Tekst między znacznikami to komunikat zastępczy.
<table>
<caption>Cennik uslug serwisowych</caption>
<thead>
<tr>
<th>Usluga</th>
<th>Czas</th>
<th>Cena</th>
</tr>
</thead>
<tbody>
<tr>
<td>Diagnostyka</td>
<td>24 h</td>
<td>50 zl</td>
</tr>
<tr>
<td>Wymiana dysku na SSD</td>
<td>2 h</td>
<td>120 zl</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Razem</td>
<td>170 zl</td>
</tr>
</tfoot>
</table>
Tabela — punktowane szczegóły
<th>
to komórka nagłówkowa (domyślnie pogrubiona i wyśrodkowana), a
<td>
to komórka danych. Atrybut
colspan
scala komórki w poziomie (w obrębie wiersza), a
rowspan
w pionie (w obrębie kolumny) — to najczęściej mylona para
w całym dziale. Po scaleniu trzeba usunąć nadmiarowe komórki z odpowiednich
wierszy, inaczej tabela wyjedzie poza obrys. Właściwość
border-collapse: collapse
scala podwójne obramowania sąsiednich komórek w jedną linię. Tabel
nie używa się do budowania układu strony — od tego są
Flexbox i Grid.
5
Style, selektory i specyficzność
Reguła CSS ma trzy części: selektor, właściwość i wartość. Zapis
p { color: red; }
znaczy „każdy akapit ma mieć czerwony tekst". Trudność zaczyna się wtedy, gdy
do jednego elementu pasuje kilka reguł ustawiających tę samą właściwość —
wtedy rozstrzyga specyficzność.
Styl wpisany w atrybucie
style
konkretnego znacznika. Ma najwyższy priorytet, ale dotyczy
jednego elementu i miesza treść z wyglądem. Odradzany poza wyjątkami.
Blok <style>
w sekcji <head>.
Działa na całą jedną stronę. Wygodne przy pojedynczym pliku, bezużyteczne
przy serwisie z wieloma podstronami.
Osobny plik .css
dołączony znacznikiem <link>.
Jedna zmiana działa na wszystkie podstrony, a plik trafia do pamięci
podręcznej przeglądarki. Zalecany sposób i ten oczekiwany
w zadaniach egzaminacyjnych.
/* selektor elementu - wszystkie akapity */
p { color: #333333; }
/* selektor klasy - elementy majace class="ostrzezenie" */
.ostrzezenie { background-color: yellow; }
/* selektor identyfikatora - element majacy id="menu" (jeden w dokumencie) */
#menu { width: 100%; }
/* selektor grupujacy - ta sama regula dla kilku selektorow */
h1, h2, h3 { font-family: Arial, sans-serif; }
/* selektor potomka (spacja) - kazdy link WEWNATRZ nav, na dowolnym poziomie */
nav a { text-decoration: none; }
/* selektor dziecka - tylko bezposrednie dzieci elementu ul */
ul > li { list-style: square; }
/* selektor uniwersalny - wszystkie elementy */
* { margin: 0; padding: 0; box-sizing: border-box; }
/* selektory atrybutu */
input[type="text"] { border: 1px solid gray; }
a[href^="https"] { color: green; }
/* pseudoklasy - stan elementu */
a:hover { color: red; }
a:visited { color: purple; }
input:focus { outline: 2px solid blue; }
tr:nth-child(even) { background-color: #f2f2f2; }
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
/* pseudoelementy - fragment elementu, zapis z dwoma dwukropkami */
p::first-letter { font-size: 200%; }
p::before { content: "-- "; }Gdy do elementu pasuje kilka reguł ustawiających tę samą właściwość, wygrywa ta o wyższej sumie punktów. Punkty liczysz, sumując wszystkie składniki selektora:
| Składnik selektora | Punkty | Przykład |
|---|---|---|
| Styl inline (atrybut style) | 1000 | style="color: red" |
| Identyfikator | 100 | #menu |
| Klasa, pseudoklasa, atrybut | 10 | .aktywny, :hover, [type] |
| Element, pseudoelement | 1 | div, a, ::before |
| Selektor uniwersalny | 0 | * |
Treść: W arkuszu stylów znajdują się trzy reguły. Jakiego koloru będzie tekst odnośnika o klasie link, leżącego wewnątrz listy w elemencie o identyfikatorze menu?
nav ul li a { color: green; }
.link { color: blue; }
#menu li a { color: red; }Rozwiązanie:
reguła 1 — cztery elementy, czyli 1 + 1 + 1 + 1 = 4 punkty;
reguła 2 — jedna klasa, czyli 10 punktów;
reguła 3 — identyfikator i dwa elementy, czyli 100 + 1 + 1 = 102 punkty.
Wygrywa reguła trzecia, więc tekst będzie czerwony.
Zasady dodatkowe: przy równej specyficzności wygrywa
reguła zapisana później w arkuszu — to działanie kaskady.
Deklaracja z dopiskiem
!important
przebija wszystko, łącznie ze stylem inline, dlatego stosuje się ją
wyjątkowo. Znaczenie ma też kolejność dołączania: jeśli plik CSS jest
podpięty po bloku
<style>,
to przy tej samej specyficzności wygrają reguły z pliku.
Dziedziczenie: część właściwości (kolor, krój i rozmiar pisma, wyrównanie tekstu) przechodzi z rodzica na dzieci. Właściwości układu — marginesy, dopełnienia, obramowania, szerokość — nie są dziedziczone.
6
Model pudełkowy i pozycjonowanie
Każdy element to prostokątne pudełko złożone z czterech warstw, liczonych od
środka na zewnątrz: treść (content), dopełnienie (padding), obramowanie
(border) i margines zewnętrzny (margin). Zadanie „oblicz rzeczywistą szerokość
elementu" to jeden z najpewniejszych punktów w całej kwalifikacji — pod
warunkiem, że pamiętasz o właściwości
box-sizing.
.karta {
width: 300px;
height: 150px;
padding: 20px; /* dopelnienie ze wszystkich stron */
border: 5px solid #333333; /* grubosc, styl, kolor */
margin: 10px; /* margines zewnetrzny */
background-color: #f5f5f5;
}
/* Zapisy skrocone:
padding: 20px; - wszystkie strony
padding: 10px 20px; - gora/dol, lewo/prawo
padding: 10px 20px 15px; - gora, lewo/prawo, dol
padding: 10px 20px 15px 5px; - gora, prawo, dol, lewo (zgodnie z zegarem)
margin: 0 auto; - wysrodkowanie bloku w poziomie
*/
Wariant A: box-sizing: content-box (wartość domyślna)
Zadeklarowana szerokość dotyczy wyłącznie obszaru treści.
Dopełnienie i obramowanie dokładane są na zewnątrz:
szerokość widoczna = 300 (treść) + 2 × 20 (padding) + 2 × 5 (border) =
300 + 40 + 10 = 350 px
miejsce zajęte w układzie = 350 + 2 × 10 (margin) = 370 px
wysokość widoczna = 150 + 40 + 10 = 200 px
Wariant B: box-sizing: border-box
Zadeklarowana szerokość obejmuje treść, dopełnienie i obramowanie razem.
Pudełko nie rośnie — kurczy się obszar treści:
szerokość widoczna = 300 px (dokładnie tyle, ile w kodzie)
szerokość samego obszaru treści = 300 − 40 − 10 = 250 px
miejsce zajęte w układzie = 300 + 2 × 10 = 320 px
Wniosek: margines nigdy nie wlicza się do szerokości
elementu — ani w jednym, ani w drugim modelu. Wpływa tylko na miejsce zajęte
w układzie. Dlatego niemal każdy arkusz stylów zaczyna się od reguły
* { box-sizing: border-box; }
— dzięki niej dwie kolumny po 50% szerokości z dopełnieniem nadal mieszczą
się obok siebie.
- padding leży wewnątrz obramowania, więc przyjmuje kolor i obrazek tła elementu. Odsuwa treść od krawędzi pudełka.
- margin leży na zewnątrz obramowania i zawsze jest przezroczysty. Odsuwa element od sąsiadów.
- Marginesy pionowe sąsiadujących elementów zlewają się (margin collapsing): 20 px z dołu i 30 px z góry dadzą odstęp 30 px, a nie 50 px. Marginesy poziome nigdy się nie zlewają.
margin: 0 autocentruje element blokowy w poziomie, ale tylko wtedy, gdy ma ustawioną szerokość mniejszą od rodzica.- Margines ujemny jest dozwolony i przesuwa element w stronę sąsiada. Ujemne dopełnienie nie istnieje.
| Wartość | Względem czego | Zachowanie |
|---|---|---|
| static | — | Wartość domyślna. Element stoi tam, gdzie postawi go normalny przepływ. Właściwości top, left, right, bottom oraz z-index są ignorowane. |
| relative | własnej pierwotnej pozycji | Przesuwa się o zadaną wartość, ale miejsce po nim zostaje puste — sąsiedzi się nie przesuwają. Tworzy układ odniesienia dla dzieci ustawionych jako absolute. |
| absolute | najbliższego przodka o pozycjonowaniu innym niż static | Wypada z normalnego przepływu — miejsce po nim znika, sąsiedzi zajmują je natychmiast. Gdy żaden przodek nie jest pozycjonowany, odnosi się do całego dokumentu. |
| fixed | okna przeglądarki | Wypada z przepływu i nie przewija się razem ze stroną. Typowe zastosowania: przyklejone menu górne, przycisk powrotu na górę, okno modalne. |
| sticky | kontenera przewijania | Hybryda: zachowuje się jak relative do momentu osiągnięcia zadanego progu (np. top: 0), a potem przykleja się jak fixed. Wymaga podania co najmniej jednej wartości top, bottom, left lub right. |
Kolejność nakładania się elementów pozycjonowanych ustala właściwość z-index — większa wartość znaczy „bliżej użytkownika". Działa wyłącznie na elementach o pozycjonowaniu innym niż static; to najczęstsza przyczyna narzekania, że „z-index nie działa".
/* Menu przyklejone do gory ekranu */
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 80px;
z-index: 100;
}
/* Uwaga: fixed wypada z przeplywu, wiec tresc wjechalaby pod naglowek.
Trzeba ja odsunac o wysokosc naglowka: */
main { margin-top: 80px; }
/* Etykieta "NOWOSC" przypieta do rogu karty produktu */
.produkt { position: relative; }
.produkt .etykieta {
position: absolute;
top: 10px;
right: 10px;
}
/* Pasek boczny przyklejajacy sie przy przewijaniu */
aside { position: sticky; top: 90px; }
7
Layout: Flexbox i CSS Grid
Zasada wyboru jest prosta: Flexbox układa elementy w jednej osi (rząd albo kolumna), Grid w dwóch naraz (wiersze i kolumny). Menu poziome, pasek przycisków, wyśrodkowanie w pionie — Flexbox. Cały układ strony z nagłówkiem, panelem bocznym i stopką — Grid. Obie techniki włącza się na kontenerze, a działają na jego bezpośrednich dzieciach.
/* HTML:
<nav class="menu">
<a href="index.html">Start</a>
<a href="uslugi.html">Uslugi</a>
<a href="kontakt.html">Kontakt</a>
</nav>
*/
.menu {
display: flex; /* wlacza Flexbox na kontenerze */
flex-direction: row; /* os glowna: poziomo (domyslnie) */
justify-content: space-between; /* rozklad wzdluz osi glownej */
align-items: center; /* wyrownanie w osi poprzecznej */
flex-wrap: wrap; /* zawijaj, gdy zabraknie miejsca */
gap: 20px; /* odstep miedzy elementami */
padding: 0 30px;
height: 70px;
background-color: #222222;
}
.menu a {
color: white;
text-decoration: none;
padding: 10px 15px;
}
/* Wlasciwosci ustawiane na elementach potomnych */
.logo { flex: 0 0 150px; } /* nie rosnie, nie kurczy sie, ma 150px */
.wypelnij { flex: 1; } /* zajmuje cala wolna przestrzen */
.ostatni { order: 99; } /* zmiana kolejnosci bez ruszania HTML */
/* Wysrodkowanie w pionie i poziomie - najkrotszy przepis w CSS */
.ekran {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}- flex-start — wszystko dosunięte do początku (domyślnie).
- flex-end — dosunięte do końca.
- center — wyśrodkowane.
- space-between — pierwszy przy lewej, ostatni przy prawej, reszta równomiernie pomiędzy.
- space-around — równe odstępy wokół każdego elementu (skrajne mają połowę).
- space-evenly — wszystkie odstępy identyczne, także skrajne.
- stretch — elementy rozciągają się na całą wysokość kontenera (domyślnie).
- flex-start i flex-end — dosunięcie do góry albo do dołu.
- center — wyśrodkowanie w pionie.
- baseline — wyrównanie do linii bazowej tekstu.
Uwaga: po ustawieniu flex-direction: column osie się zamieniają — wtedy justify-content steruje pionem, a align-items poziomem. To ulubione pytanie-pułapka.
/* HTML:
<div class="strona">
<header>...</header>
<nav>...</nav>
<main>...</main>
<aside>...</aside>
<footer>...</footer>
</div>
*/
.strona {
display: grid;
grid-template-columns: 200px 1fr 250px; /* trzy kolumny */
grid-template-rows: 100px auto 80px; /* trzy wiersze */
grid-template-areas:
"naglowek naglowek naglowek"
"menu tresc bok"
"stopka stopka stopka";
gap: 15px;
min-height: 100vh;
}
header { grid-area: naglowek; }
nav { grid-area: menu; }
main { grid-area: tresc; }
aside { grid-area: bok; }
footer { grid-area: stopka; }
/* Alternatywnie - bez nazw obszarow, przez numery linii siatki */
.baner {
grid-column: 1 / 4; /* od linii 1 do linii 4, czyli przez 3 kolumny */
grid-row: 1 / 2;
}
.szeroki { grid-column: span 2; } /* rozciagnij na dwie kolumny */
/* Galeria, ktora sama dobiera liczbe kolumn */
.galeria {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}Jednostka fr, funkcja repeat i numeracja linii
1fr
to jedna część wolnej przestrzeni, jaka zostaje po rozdaniu miejsca
kolumnom o stałej szerokości. Zapis
grid-template-columns: 200px 1fr 250px
znaczy: skrajne kolumny mają stałe 200 i 250 pikseli, a środkowa bierze całą
resztę.
repeat(3, 1fr)
to skrót od trzech równych kolumn, a
minmax(220px, 1fr)
ustala szerokość minimalną i maksymalną. Słowo
auto-fit
każe przeglądarce zmieścić tyle kolumn, ile się da — dzięki temu galeria jest
responsywna bez ani jednego media query.
Numeracja linii siatki zaczyna się od 1, a układ o trzech
kolumnach ma cztery linie pionowe. Dlatego
grid-column: 1 / 4
rozciąga element przez wszystkie trzy kolumny. Mylenie numeru kolumny
z numerem linii to najczęstszy błąd w tym temacie.
Starsza technika układania treści to
float: left
i float: right.
Element pływający wypada z przepływu, przez co kontener traci wysokość — trzeba
go domknąć regułą
clear: both
albo overflow: hidden.
Do budowania layoutów float już się nie używa, ale nadal pojawia się
w zadaniach o oblewaniu obrazka tekstem.
8
Responsywność, jednostki i media queries
RWD (Responsive Web Design) to jedna strona, która dopasowuje układ do szerokości ekranu — w odróżnieniu od osobnej wersji mobilnej pod innym adresem. Składają się na nią trzy rzeczy: znacznik viewport w sekcji head, jednostki względne zamiast sztywnych pikseli oraz media queries.
| Jednostka | Względem czego | Kiedy jej używać |
|---|---|---|
| px | Jednostka bezwzględna — piksel | Obramowania, cienie, drobne odstępy. Nie skaluje się z ustawieniami użytkownika. |
| % | Wymiaru elementu nadrzędnego | Szerokości kolumn i kontenerów. |
| em | Rozmiaru pisma rodzica | Dopełnienia zależne od wielkości tekstu. Uwaga: zagnieżdżanie mnoży wartości. |
| rem | Rozmiaru pisma elementu html | Rozmiary pisma i odstępy w całym serwisie. Bez efektu kuli śnieżnej. |
| vw / vh | 1% szerokości / wysokości okna | Sekcje na pełny ekran, np. min-height: 100vh. |
| fr | Część wolnej przestrzeni w siatce | Wyłącznie w CSS Grid. |
Domyślny rozmiar pisma w przeglądarce to 16 px, więc 1rem = 16px, 1.5rem = 24px, 0.875rem = 14px. Różnica em kontra rem na przykładzie: jeśli rodzic ma pismo 20 px, to dziecko z ustawieniem font-size: 1.5em dostanie 30 px, a z 1.5rem — zawsze 24 px, niezależnie od rodzica.
/* Podejscie mobile first: najpierw style dla telefonu,
potem kolejne progi rozszerzaja uklad. */
.strona {
display: grid;
grid-template-columns: 1fr; /* telefon: jedna kolumna */
gap: 10px;
}
/* Tablet - od 768 pikseli wzwyz */
@media screen and (min-width: 768px) {
.strona { grid-template-columns: 200px 1fr; }
.menu { flex-direction: row; }
}
/* Desktop - od 1024 pikseli wzwyz */
@media screen and (min-width: 1024px) {
.strona { grid-template-columns: 200px 1fr 250px; }
aside { display: block; }
}
/* Wariant desktop first - warunek maksymalnej szerokosci */
@media screen and (max-width: 767px) {
.menu { flex-direction: column; }
aside { display: none; }
}
/* Styl dla wydruku */
@media print {
nav, footer, .reklama { display: none; }
body { color: #000000; background: #ffffff; }
}
/* Warunek orientacji urzadzenia */
@media (orientation: landscape) {
.baner { height: 40vh; }
}
/* Obraz responsywny */
img { max-width: 100%; height: auto; }
- Reguła media query ma budowę: znak małpy, słowo media, typ nośnika (screen, print, all), słowo and i warunek w nawiasie okrągłym.
- Typowe punkty przełamania (breakpointy): około 480 px telefon, 768 px tablet, 1024 px laptop, 1280 px duży monitor. To konwencja, nie norma — dobiera się je pod projekt.
- Mobile first — style bazowe piszesz dla najmniejszego ekranu, a media queries z min-width dokładają elementy przy większych. Podejście odwrotne (desktop first) korzysta z max-width.
- Kolejność ma znaczenie: media queries umieszcza się po stylach bazowych, bo mają tę samą specyficzność i rozstrzyga kaskada. Bez znacznika viewport w sekcji head żadna z nich nie zadziała poprawnie na telefonie.
- Doliczanie marginesu do szerokości elementu. Margin nigdy nie wchodzi w skład szerokości pudełka — ani przy content-box, ani przy border-box. Wpływa tylko na miejsce zajmowane w układzie.
- Mylenie content-box z border-box. Przy domyślnym content-box element o szerokości 300 px z dopełnieniem 20 px i obramowaniem 5 px zajmuje 350 px. Przy border-box zajmuje dokładnie 300 px, bo kurczy się obszar treści.
- Zamiana colspan z rowspan. Colspan scala w poziomie (w wierszu), rowspan w pionie (w kolumnie). Po scaleniu trzeba usunąć nadmiarowe komórki.
- Pole formularza bez atrybutu name. Takie pole nie zostanie wysłane do skryptu — formularz „działa", ale dane nie docierają. Atrybut id służy do etykiet i CSS, nie do wysyłki. POST przy tym niczego nie szyfruje, tylko ukrywa dane przed paskiem adresu.
- Liczenie specyficzności na oko. Jeden identyfikator (100 punktów) przebija dowolną liczbę klas i elementów. Przy remisie wygrywa reguła zapisana później.
- Ustawianie szerokości elementowi liniowemu. Znaczniki span czy a ignorują width i height, dopóki nie zmienisz im właściwości display na block albo inline-block.
- Brak znacznika viewport przy RWD. Media queries są napisane poprawnie, a na telefonie strona i tak wygląda jak pomniejszony desktop.
- Pominięcie atrybutu alt przy obrazie i mylenie head z header. Dwa drobiazgi, dwa gotowe odjęte punkty: alt jest wymagany, a head to niewidoczna sekcja metadanych, nie widoczny nagłówek strony.
HTML i CSS wchodzą do głowy dopiero wtedy, gdy policzysz kilka pudełek i rozstrzygniesz kilka konfliktów selektorów bez zaglądania do notatek. Rozwiąż test z tego działu i zobacz, gdzie jeszcze masz luki.