Reguła CSSReguły @

@media

Włącza style tylko wtedy, gdy urządzenie spełnia warunek: ma odpowiednią szerokość okna, ciemny motyw, mysz albo drukuje stronę.

Na tej stronie

Przykład

#
CSS
.courses {
  display: grid;
  gap: 10px;
}

@media (width >= 500px) {
  .courses {
    grid-template-columns: repeat(3, 1fr);
  }
}
Podgląd

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

#
Składnia
@media [<typ medium> and]? (<warunek>) [and (<warunek>)]* {
  selektor { właściwość: wartość; }
}

Cechy mediów

#
  • min-width

    (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.
  • max-width

    (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

    (prefers-color-scheme: dark)

    Pyta o motyw wybrany w systemie lub w przeglądarce: 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.
  • prefers-reduced-motion

    (prefers-reduced-motion: no-preference)

    Sprawdza, czy użytkownik poprosił system o ograniczenie ruchu. Tu animacja działa tylko przy wartości no-preference, czyli u osób, które tej opcji nie włączyły. Z włączonym ograniczeniem (reduce) kafelek stoi w miejscu.
  • hover

    (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

    (pointer: coarse)

    Jak dokładny jest główny wskaźnik: 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.
  • orientation

    (orientation: landscape)

    Porównuje wysokość i szerokość okna: landscape, gdy okno jest szersze niż wyższe, portrait w przeciwnym razie. Ramka podglądu jest pozioma, więc obrazek staje obok tekstu.
  • print

    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

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.
@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

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.
@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

Pyta o motyw wybrany w systemie lub w przeglądarce: 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

Sprawdza, czy użytkownik poprosił system o ograniczenie ruchu. Tu animacja działa tylko przy wartości 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

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.
@media (hover: hover) {
  .btn:hover {
    background: #10b981;
    translate: 0 -3px;
  }
}

pointer

Jak dokładny jest główny wskaźnik: 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

Porównuje wysokość i szerokość okna: 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; }
}

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ą.
@media print {
  .toolbar { display: none; }
  .doc { background: #fff; color: #000; }
}

Więcej przykładów

#
Ciemny motyw przez zmienne CSS
CSS
:root {
  --bg: #ffffff;
  --text: #18181b;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #18181b;
    --text: #f4f4f5;
  }
}

.panel {
  background: var(--bg);
  color: var(--text);
}
Podgląd

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

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.