@media
Włącza style tylko wtedy, gdy urządzenie spełnia warunek: ma odpowiednią szerokość okna, ciemny motyw, mysz albo drukuje stronę.
Przykład
#.courses {
display: grid;
gap: 10px;
}
@media (width >= 500px) {
.courses {
grid-template-columns: repeat(3, 1fr);
}
}<style>
.course { padding: 12px 14px; border: 1px solid #27272a; border-radius: 12px; background: #18181b; }
.course strong { display: block; }
.course span { color: #a1a1aa; font-size: 13px; }
</style>
<div class="courses">
<div class="course"><strong>HTML i CSS</strong><span>11 modułów</span></div>
<div class="course"><strong>JavaScript</strong><span>12 modułów</span></div>
<div class="course"><strong>Python</strong><span>12 modułów</span></div>
</div>Na komputerze ramka ma ponad 500 px szerokości i karty stoją w trzech kolumnach. Na wąskim ekranie telefonu zostaje jedna kolumna, czyli styl bazowy.
Definicja i zastosowanie
#Reguła @media zamyka część arkusza w warunku. Style z jej wnętrza działają tylko wtedy, gdy okno przeglądarki lub urządzenie spełnia podane kryteria: ma określoną szerokość, preferuje ciemny motyw, obsługuje najechanie kursorem albo właśnie drukuje stronę. Przeglądarka sprawdza warunek na bieżąco, więc po zwężeniu okna czy zmianie motywu style włączają się i wyłączają bez przeładowania.
Najpopularniejsze podejście to mobile first. Styl bazowy, zapisany poza jakąkolwiek regułą, projektujesz dla wąskiego ekranu telefonu, a reguły @media (width >= …) dokładają zmiany dla coraz szerszych ekranów: więcej kolumn, większe odstępy, poziome menu. Arkusz jest wtedy krótszy, bo na telefonie niczego nie trzeba nadpisywać, a jedna kolumna to naturalny punkt wyjścia dla treści.
Szerokość zapiszesz na dwa sposoby. Klasyczny to (min-width: 600px) i (max-width: 599px), nowszy to składnia zakresów: (width >= 600px), (width < 600px), a nawet (600px <= width < 900px). Działają tak samo, ale zakresy czyta się jak zwykłą nierówność. Kilka warunków łączysz słowem and, alternatywę zapisujesz przecinkiem, a not odwraca całe zapytanie.
Częsta pułapka: bez znacznika <meta name="viewport" content="width=device-width, initial-scale=1"> telefon udaje szeroki ekran (zwykle około 980 px) i pomniejsza stronę, więc progi dla małych ekranów się nie włączają. Pamiętaj też, że @media pyta o całe okno. Gdy komponent ma się dopasować do miejsca, które dostał w układzie, użyj @container.
Składnia
#@media [<typ medium> and]? (<warunek>) [and (<warunek>)]* {
selektor { właściwość: wartość; }
}Cechy mediów
#(width >= 300px)
Styl działa od progu w górę, tak samo jak klasyczne(min-width: 300px). Każda lampka ma własny warunek i zapala się, gdy ramka podglądu jest co najmniej tak szeroka jak jej próg. Aktualną szerokość ramki widać pod lampkami.(width < 500px)
Styl działa tylko poniżej progu. Klasycznie pisze się(max-width: 499px), co zostawia lukę dla ułamkowych szerokości okna, np. 499,5 px, a zapis ze znakiem<jej nie ma. Tym razem świecą lampki, których próg jest większy niż szerokość ramki.(prefers-color-scheme: dark)
Pyta o motyw wybrany w systemie lub w przeglądarce:lightalbodark. Karta jest jasna, a przy ciemnym motywie przechodzi na ciemne kolory. Przełącz motyw w ustawieniach systemu, a karta zmieni się na żywo.(prefers-reduced-motion: no-preference)
Sprawdza, czy użytkownik poprosił system o ograniczenie ruchu. Tu animacja działa tylko przy wartościno-preference, czyli u osób, które tej opcji nie włączyły. Z włączonym ograniczeniem (reduce) kafelek stoi w miejscu.(hover: hover)
Czy główne urządzenie wskazujące potrafi najechać na element. Najedź kursorem na przycisk: efekt działa przy myszy i gładziku, a na telefonie reguła się nie włącza, więc po stuknięciu nie zostaje „przyklejone” podświetlenie.(pointer: coarse)
Jak dokładny jest główny wskaźnik:fineto mysz lub rysik,coarseto palec. Na ekranie dotykowym przyciski urosną do co najmniej 44 px wysokości, żeby łatwo było w nie trafić. Przy myszy zostają kompaktowe.(orientation: landscape)
Porównuje wysokość i szerokość okna:landscape, gdy okno jest szersze niż wyższe,portraitw przeciwnym razie. Ramka podglądu jest pozioma, więc obrazek staje obok tekstu.print
To typ medium, a nie cecha: style działają przy drukowaniu i zapisie do PDF. Na wydruku przyciski znikną, a tło zrobi się białe. Podgląd jest ekranem, więc tutaj widzisz wersję ekranową.
Cechy mediów w praktyce
#min-width
(min-width: 300px). Każda lampka ma własny warunek i zapala się, gdy ramka podglądu jest co najmniej tak szeroka jak jej próg. Aktualną szerokość ramki widać pod lampkami.@media (width >= 300px) {
.a { background: #10b981; color: #fff; }
}
@media (width >= 500px) {
.b { background: #10b981; color: #fff; }
}
@media (width >= 700px) {
.c { background: #10b981; color: #fff; }
}max-width
(max-width: 499px), co zostawia lukę dla ułamkowych szerokości okna, np. 499,5 px, a zapis ze znakiem < jej nie ma. Tym razem świecą lampki, których próg jest większy niż szerokość ramki.@media (width < 300px) {
.a { background: #f59e0b; color: #000; }
}
@media (width < 500px) {
.b { background: #f59e0b; color: #000; }
}
@media (width < 700px) {
.c { background: #f59e0b; color: #000; }
}prefers-color-scheme
light albo dark. Karta jest jasna, a przy ciemnym motywie przechodzi na ciemne kolory. Przełącz motyw w ustawieniach systemu, a karta zmieni się na żywo.@media (prefers-color-scheme: dark) {
.card {
background: #18181b;
color: #f4f4f5;
border-color: #3f3f46;
}
}prefers-reduced-motion
no-preference, czyli u osób, które tej opcji nie włączyły. Z włączonym ograniczeniem (reduce) kafelek stoi w miejscu.@media (prefers-reduced-motion: no-preference) {
.mover {
animation: slide 1.4s infinite alternate;
}
}hover
@media (hover: hover) {
.btn:hover {
background: #10b981;
translate: 0 -3px;
}
}pointer
fine to mysz lub rysik, coarse to palec. Na ekranie dotykowym przyciski urosną do co najmniej 44 px wysokości, żeby łatwo było w nie trafić. Przy myszy zostają kompaktowe.@media (pointer: coarse) {
.btn {
min-height: 44px;
padding-inline: 20px;
}
}orientation
landscape, gdy okno jest szersze niż wyższe, portrait w przeciwnym razie. Ramka podglądu jest pozioma, więc obrazek staje obok tekstu.@media (orientation: landscape) {
.orient {
display: flex;
align-items: center;
gap: 12px;
}
.orient p { margin: 0; }
}@media print {
.toolbar { display: none; }
.doc { background: #fff; color: #000; }
}Więcej przykładów
#:root {
--bg: #ffffff;
--text: #18181b;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #18181b;
--text: #f4f4f5;
}
}
.panel {
background: var(--bg);
color: var(--text);
}<div class="panel" style="padding: 14px 16px; border: 1px solid #52525b; border-radius: 12px;">
<strong>Twój postęp</strong>
<p style="margin: 4px 0 0;">Ukończone lekcje: 18 z 24</p>
</div>Panel przyjmuje kolory motywu ustawionego w systemie. Zmienne nadpisujesz w jednym miejscu, a wszystkie komponenty, które z nich korzystają, dostosują się same.
Obsługa przeglądarek
#Szeroko dostępne
Działa we wszystkich nowoczesnych przeglądarkach, także na telefonach. Możesz używać bez obaw.
- Chrome
- Edge
- Firefox
- Safari
Dobre praktyki
#- Zaczynaj od układu na telefon i dokładaj reguły
@media (width >= …). Progi dobieraj do treści: dodaj próg tam, gdzie układ zaczyna się psuć, a nie pod konkretne modele urządzeń. - Sprawdź, czy w
<head>jest<meta name="viewport" content="width=device-width, initial-scale=1">. Bez niego progi dla telefonów się nie włączą. - Animacje zamykaj w
@media (prefers-reduced-motion: no-preference). Osoby wrażliwe na ruch zobaczą wtedy spokojną wersję strony.
Powiązane hasła
#- @containerNakłada style zależnie od rozmiaru kontenera, a nie całego okna. Komponent dopasowuje się do miejsca, które dostał w układzie.
- @supportsWłącza style tylko w przeglądarkach, które obsługują daną właściwość, wartość albo selektor. Pozwala bezpiecznie korzystać z nowości.
- JednostkiPrzegląd jednostek długości w CSS: od stałych pikseli, przez em i rem zależne od czcionki, po jednostki okna, kontenera i siatki.
- :hoverPasuje do elementu, nad którym znajduje się kursor myszy. Podstawa efektów najechania na przyciski, linki i karty.
- grid-template-columnsDefiniuje kolumny siatki: ich liczbę i szerokości.
Widzisz błąd albo brakuje przykładu? Napisz do nas.