Media query w jednym przykładzie
Media query otacza CSS warunkiem. Reguły wewnątrz @media (min-width: 600px) działają tylko wtedy, gdy viewport ma co najmniej 600px szerokości:
Podgląd to ramka, a media query wewnątrz niej mierzy ramkę, a nie twój ekran. Na komputerze ma ona mniej więcej szerokość kolumny tego artykułu, zwykle ponad 600px, więc pudełko jest niebieskie. Zwęź okno przeglądarki tak, żeby ramka spadła poniżej 600px, a pudełko zmieni kolor na bursztynowy; linijka pod pudełkiem na żywo podaje szerokość ramki. Na telefonie ramka jest już wąska, więc widzisz wersję bursztynową.
Składnia @media
@media (min-width: 600px) { ... } /* one condition */
@media (min-width: 600px) and (max-width: 899px) { ... } /* both must be true */
@media (max-width: 599px), print { ... } /* either one (comma = or) */
@media not print { ... } /* negation */
@media screen and (orientation: landscape) { ... } /* media type plus a feature */
@media (width >= 600px) { ... } /* range syntax */
@media (600px <= width < 900px) { ... } /* a range with both ends */
and wymaga spacji po obu stronach: (min-width: 600px)and(max-width: 900px) jest nieprawidłowe i całe zapytanie zostaje zignorowane. Składnia zakresów (width >= 600px) jest obsługiwana w aktualnych wersjach Chrome, Firefoksa i Safari i czyta się ją łatwiej niż min-width, zwłaszcza przy "do, ale bez".
Funkcje, których będziesz używać najczęściej:
| Funkcja | Pasuje, gdy | Przykład |
|---|---|---|
min-width / width >= | viewport ma co najmniej tę szerokość | (min-width: 768px) |
max-width / width <= | viewport ma co najwyżej tę szerokość | (max-width: 767px) |
orientation | portrait (wyższy niż szeroki) lub landscape | (orientation: landscape) |
hover | główny wskaźnik może najeżdżać (hover) lub nie (none, większość ekranów dotykowych) | (hover: hover) |
pointer | główny wskaźnik jest fine (mysz) lub coarse (palec) | (pointer: coarse) |
prefers-color-scheme | użytkownik wybrał motyw dark lub light | (prefers-color-scheme: dark) |
prefers-reduced-motion | użytkownik poprosił system o mniej ruchu | (prefers-reduced-motion: reduce) |
print (typ mediów) | strona jest drukowana lub zapisywana jako PDF | @media print |
Mobile first: breakpointy min-width
Napisz układ na telefon jako bazowy CSS, a potem dodaj zapytania min-width, które zmieniają układ, gdy przybywa miejsca. Każde zapytanie musi opisać tylko to, co się zmienia:
W szerokim oknie na komputerze podgląd ma ponad 720px, więc widzisz trzy kolumny; linijka pod siatką podaje szerokość i liczbę kolumn. Zwęź okno, a poniżej 720px zostaną dwie kolumny, a poniżej 480px jedna. Kolejność obu zapytań ma znaczenie: na szerokim ekranie oba są prawdziwe i wygrywa późniejsze, więc zapytania min-width idą od najmniejszego do największego. (Przy zapytaniach max-width jest odwrotnie: najpierw największe.)
Wybór breakpointów
Nie ma oficjalnej listy. Oto popularne wartości i to, co zwykle rozdzielają:
| Breakpoint | Zwykle |
|---|---|
min-width: 640px | duże telefony w poziomie, małe tablety |
min-width: 768px | tablety w pionie |
min-width: 1024px | tablety w poziomie, małe laptopy |
min-width: 1280px | komputery stacjonarne |
Lepsza metoda: zacznij od wąskiego układu, poszerzaj okno, aż coś zacznie źle wyglądać (za długie linie, za szerokie karty), i tam postaw breakpoint. Dla większości stron wystarczą dwa lub trzy breakpointy. Często nie potrzebujesz żadnego: repeat(auto-fit, minmax(200px, 1fr)) w grid, flex-wrap i clamp() dopasowują się płynnie.
Każda strona potrzebuje metatagu viewport
Bez tego tagu w <head> przeglądarki na telefonach układają stronę tak, jakby ekran miał około 980px szerokości, a potem ją oddalają, więc twoje zapytanie min-width: 480px jest zawsze prawdziwe, a układ na telefon nigdy się nie pokazuje:
<meta name="viewport" content="width=device-width, initial-scale=1">
Strona o meta viewport wyjaśnia każdą jego wartość.
Tryb ciemny z prefers-color-scheme
prefers-color-scheme podąża za jasnym lub ciemnym ustawieniem systemu operacyjnego. Najczystszy sposób użycia to trzymanie kolorów w zmiennych CSS i zmienianie wewnątrz zapytania tylko zmiennych:
W tym podglądzie zapytanie może wypisać false, nawet gdy system ma ustawiony ciemny motyw: Chrome nie przekazuje ustawienia systemu do izolowanej ramki takiej jak ta. Przycisk ustawia te same zmienne ręcznie, tak jak działa przełącznik motywu na stronie. :root[data-theme] jest bardziej specyficzny niż zwykły :root wewnątrz zapytania, więc wybór czytelnika wygrywa z systemem. Zapisz przykład jako plik i otwórz go, żeby zobaczyć, jak zapytanie podąża za systemem.
Skrypt pokazuje drugą połowę media queries: matchMedia() uruchamia to samo zapytanie z JavaScriptu, zwraca, czy teraz pasuje, i wywołuje zdarzenie change, gdy odpowiedź się zmienia. Używaj go, gdy od ekranu zależy zachowanie (a nie tylko wygląd), na przykład inny sposób otwierania menu na urządzeniach dotykowych.
Z ruchem jest tak samo. Duże lub zapętlone animacje umieszczaj w sprawdzeniu prefers-reduced-motion, jak pokazuje strona o animacjach.
Container queries: gdy decydować ma komponent
Media query zna tylko viewport. Karta, która na tej samej stronie stoi w szerokiej kolumnie głównej i w wąskim panelu bocznym, musi zamiast tego znać własną przestrzeń. Do tego służy container query: oznacz rodzica przez container-type: inline-size, a potem użyj @container z tymi samymi warunkami.
Przeciągnij róg szarego pudełka, żeby zmienić jego rozmiar. Karta zmienia układ przy 360px szerokości pudełka, bez względu na rozmiar okna:
Przy początkowych 480px obrazek stoi obok tekstu. Zwęź pudełko poniżej 376px (360px treści plus 8px paddingu z każdej strony), a obrazek przesunie się nad tekst. Container queries działają we wszystkich aktualnych głównych przeglądarkach.
Style do druku
@media print działa tylko wtedy, gdy strona jest drukowana lub zapisywana jako PDF. Ukryj nawigację i przyciski i użyj ciemnego tekstu na białym tle:
@media print {
nav, .ad, button { display: none; }
body { color: black; background: white; }
a::after { content: " (" attr(href) ")"; } /* print the URL after each link */
}
Częste błędy
- Brak metatagu viewport. Telefony zgłaszają wtedy szeroki viewport układu i zapytania dla małych ekranów nigdy nie pasują.
- Zapytania w złej kolejności. Dwa prawdziwe zapytania z tym samym selektorem: wygrywa późniejsze. Układaj zapytania
min-widthod małych do dużych. - Nakładające się lub rozłączne granice.
max-width: 768pximin-width: 768pxpasują oba przy dokładnie 768px. Użyj w jednym z nich767pxalbo składni zakresów(width < 768px)i(width >= 768px). - Brak spacji po
and.and(jest nieprawidłowe i zapytanie po cichu przepada. - Testowanie tylko przez zmianę rozmiaru okna na komputerze. Sprawdź też prawdziwy telefon albo tryb urządzenia w przeglądarce, który stosuje viewport, gęstość pikseli i dotyk telefonu.
- Za dużo breakpointów. Jeśli każdy komponent potrzebuje własnego, spróbuj zamiast tego
auto-fitw grid,flex-wrapalbo container queries.
Najczęściej zadawane pytania
Czym jest media query w CSS?
To reguła, która stosuje zawarty w niej CSS tylko wtedy, gdy spełniony jest warunek dotyczący urządzenia lub okna. @media (min-width: 600px) { ... } stosuje swoje style tylko wtedy, gdy viewport ma co najmniej 600px szerokości, i właśnie tak jedna strona dopasowuje się od telefonów po komputery.
Używać media queries z min-width czy z max-width?
Większość stron pisze się w podejściu mobile first: bazowy CSS jest dla małych ekranów, a zapytania min-width dodają układ, gdy ekran rośnie. Zapytania max-width działają odwrotnie, zaczynając od układu na komputer. Oba podejścia działają; mieszanie obu na tym samym elemencie prowadzi do nakładania się i luk na granicach.
Jakie są standardowe breakpointy w media queries?
Nie ma oficjalnego standardu. Popularne wartości to około 640px, 768px, 1024px i 1280px, ale lepsza zasada to dodawać breakpoint tam, gdzie twój własny układ zaczyna źle wyglądać, i trzymać liczbę breakpointów na niskim poziomie.
Dlaczego moje media query nie działa na telefonie?
Najczęstszą przyczyną jest brak metatagu viewport. Bez <meta name="viewport" content="width=device-width, initial-scale=1"> mobilne przeglądarki udają, że strona ma około 980px szerokości, więc zapytania dla małych szerokości nigdy nie pasują. Sprawdź też, czy zapytanie stoi po regułach, które nadpisuje.
Jak napisać media query dla trybu ciemnego?
Użyj @media (prefers-color-scheme: dark) { ... }. Pasuje, gdy system operacyjny lub przeglądarka użytkownika ma ustawiony ciemny motyw, a wewnątrz możesz nadpisać kolory albo zmienne CSS.
Czym różnią się media queries od container queries?
Media query sprawdza viewport (całe okno). Container query, zapisywane przez @container, sprawdza rozmiar elementu rodzica, który oznaczasz przez container-type: inline-size. Używaj container queries dla komponentu, który pojawia się na tej samej stronie zarówno w szerokich, jak i wąskich miejscach.