Przejdź do treści

Responsive Web Design — mobile-first i media queries w praktyce

Mobile-first zmienia kolejność myślenia o layoutach. Media queries, fluid typography i container queries — jak to działa w praktyce.

Maciej Sala

Founder StriveLab

5 min czytaniaOpublikowano 25 listopada 2025 (Aktualizacja 25 maja 2026)

Responsive Web Design (RWD) to podejście, w którym strona automatycznie dostosowuje się do rozmiaru ekranu. W tym artykule nauczysz się jak to robić — od mobile-first, przez media queries, po responsywne obrazy.

Viewport meta tag jako fundament Responsive Web Design

Bez tego tagu responsywność nie zadziała:

Code
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
  • width=device-width — szerokość strony = szerokość urządzenia
  • initial-scale=1.0 — brak domyślnego zoomu

Powyższy kod dodaj to do każdej klasycznej strony HTML, ponieważ bez tego przeglądarka mobilna wyrenderuje stronę w szerokim, wirtualnym viewportcie i pomniejszy całość.

Mobile-first vs desktop-first w Responsive Web Design

Desktop-first jako starsze podejście

Piszesz style dla desktopu, potem "naprawiasz" dla mobile:

Code
/* Domyślne — desktop */
.container {
  width: 1200px;
  display: flex;
}
 
/* Nadpisanie dla mobile */
@media (max-width: 768px) {
  .container {
    width: 100%;
    flex-direction: column;
  }
}

Mobile-first jako zalecane podejście

Piszesz style dla mobile, potem "rozszerzasz" dla większych ekranów:

Code
/* Domyślne — mobile */
.container {
  width: 100%;
  display: flex;
  flex-direction: column;
}
 
/* Rozszerzenie dla tabletu */
@media (min-width: 768px) {
  .container {
    flex-direction: row;
  }
}
 
/* Rozszerzenie dla desktopu */
@media (min-width: 1024px) {
  .container {
    max-width: 1200px;
    margin: 0 auto;
  }
}

Dlaczego podejście mobile-first jest lepsze?

  • Zaczynasz od najtrudniejszego. Projektowanie na małym ekranie zmusza do myślenia o ograniczeniach, ponieważ musisz zdecydować, co jest absolutnie kluczowe dla użytkownika - nie masz miejsca na zbędne elementy.
  • Treść jest priorytetem. Zamiast upychać wszystko, co masz na desktopie, skupiasz się na najważniejszej treści i funkcjach, a to oznacza lepsze i bardziej przemyślane .
  • Stopniowo ulepszasz, a nie psujesz. Zamiast tworzyć skomplikowany layout desktopowy i potem próbować go "naprawić" dla telefonów (degradacja), budujesz prostą, solidną podstawę mobilną i stopniowo ją rozbudowujesz (progresywne ulepszanie).
  • Czystszy i lżejszy kod. Piszesz mniej stylów, które nadpisują inne, a to oznacza mniej konfliktów w CSS, łatwiejsze utrzymanie projektu i szybsze wczytywanie strony na urządzeniach mobilnych, które pobierają tylko niezbędny kod.

Media queries w praktyce

Składnia media queries

Code
@media (warunek) {
  /* style */
}
 
/* Przykłady */
@media (min-width: 768px) {
} /* od 768px w górę */
@media (max-width: 767px) {
} /* do 767px */
@media (min-width: 768px) and (max-width: 1023px) {
} /* zakres */

Popularne breakpoints dla responsywnych stron

Code
/* Mobile — domyślne, bez media query */
 
/* Tablet */
@media (min-width: 768px) {
}
 
/* Desktop */
@media (min-width: 1024px) {
}
 
/* Duży desktop */
@media (min-width: 1280px) {
}

To tylko sensowny punkt startowy, ponieważ dobre breakpointy wynikają z treści i layoutu, nie z listy konkretnych urządzeń.

Inne media features w CSS

Code
/* Orientacja */
@media (orientation: landscape) {
}
 
/* Hover */
@media (hover: hover) {
} /* desktop */
@media (hover: none) {
} /* touch */
 
/* Dark mode */
@media (prefers-color-scheme: dark) {
}
 
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
}
 
/* Print */
@media print {
}

Fluid typography i skalowanie tekstu

clamp() i płynne skalowanie fontów

Code
h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
  /* Min: 24px, preferowane: 4% viewport, max: 48px */
}
 
p {
  font-size: clamp(1rem, 2vw + 0.5rem, 1.25rem);
}
 
.section {
  padding: clamp(1rem, 5vw, 4rem);
}

Responsywne obrazy w HTML i CSS

Podstawy

Code
img {
  max-width: 100%;
  height: auto;
}

srcset i różne rozmiary obrazów

Code
<img
  src="image-800.jpg"
  srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
  sizes="(max-width: 600px) 100vw, 50vw"
  alt="Opis obrazu"
/>

picture dla różnych wariantów obrazów

Code
<picture>
  <source media="(min-width: 1024px)" srcset="desktop.jpg" />
  <source media="(min-width: 768px)" srcset="tablet.jpg" />
  <img src="mobile.jpg" alt="Opis" />
</picture>

Lazy loading

Code
<img src="image.jpg" alt="..." loading="lazy" />

Nie wrzucaj loading="lazy" bezrefleksyjnie na obraz hero albo kluczowy obraz . Tam zwykle chcesz ładowania od razu.

Responsywny layout strony

Flexbox wrap

Code
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
 
.card {
  flex: 1 1 300px;
}

Grid auto-fit

Code
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1rem;
}

Layout z media queries

Code
.layout {
  display: grid;
  grid-template-columns: 1fr;
}
 
@media (min-width: 768px) {
  .layout {
    grid-template-columns: 250px 1fr;
  }
}
 
@media (min-width: 1024px) {
  .layout {
    grid-template-columns: 250px 1fr 200px;
  }
}

Responsywna nawigacja na mobile

Code
/* Mobile: ukryte menu */
.nav-links {
  display: none;
  flex-direction: column;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: white;
}
 
.nav-links.active {
  display: flex;
}
 
.menu-toggle {
  display: block;
}
 
/* Desktop: widoczne menu */
@media (min-width: 768px) {
  .nav-links {
    display: flex;
    flex-direction: row;
    position: static;
  }
 
  .menu-toggle {
    display: none;
  }
}
Code
// Toggle menu
const toggle = document.querySelector('.menu-toggle')
const navLinks = document.querySelector('.nav-links')
 
toggle.addEventListener('click', () => {
  navLinks.classList.toggle('active')
})

Container queries w nowoczesnym CSS

Media queries reagują na viewport, a container queries reagują na rozmiar rodzica:

Code
.card-container {
  container-type: inline-size;
}
 
@container (min-width: 400px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

To bardzo skuteczne rozwiązanie dla komponentów używanych w różnych miejscach layoutu, ponieważ zamiast pytać o szerokość całego okna, pytasz o miejsce, w którym jest komponent.

Testowanie responsywności strony

Chrome DevTools

  1. F12 → Toggle Device Toolbar (Ctrl+Shift+M na Windows/Linux, Cmd+Shift+M na macOS),
  2. Wybierz urządzenie lub ustaw własny rozmiar,
  3. Testuj różne viewporty.

Narzędzia online

Lista kontrolna Responsive Web Design

  • Viewport meta tag,
  • Obrazy max-width: 100%,
  • Czytelny tekst bez zoomowania,
  • Tapalne elementy min. 44x44px
  • Nawigacja działa na mobile,
  • Formularze działają na touch,
  • Brak horizontal scroll,
TechnikaUżycie
viewport metaNa każdej stronie
Mobile-firstmin-width media queries
clamp()Fluid typography i spacing
srcset/pictureResponsywne obrazy
Flexbox wrapElastyczne layouty
Grid auto-fitSiatki kart
Container queriesKomponenty niezależne od viewport
Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.
React

Często zadawane pytania

Co oznacza mobile-first w CSS?

Mobile-first oznacza, że bazowe style piszesz dla najmniejszych ekranów, a większe warianty dodajesz przez media queries z min-width.

Czy media queries nadal są potrzebne przy container queries?

Tak. Container queries świetnie rozwiązują problemy komponentów zależnych od dostępnej szerokości, ale media queries nadal są przydatne do globalnych zmian layoutu.

Jak testować responsywność strony?

Najlepiej łączyć narzędzia deweloperskie w przeglądarce z testami na prawdziwych urządzeniach, bo emulacja nie pokazuje wszystkich problemów dotyku, wydajności i viewportu.

Czym jest podejście mobile-first i dlaczego jest zalecane?

Mobile-first oznacza pisanie domyślnych styli pod małe ekrany i rozszerzanie ich dla większych za pomocą @media (min-width: ...). Właśnie takie podejście jest najlepsze, ponieważ skłania do priorytetyzacji treści, zapewnia progresywne ulepszanie i generuje lepszą wydajność na urządzeniach mobilnych (ładują tylko niezbędne style).

Co to jest viewport meta tag i dlaczego jest obowiązkowy?

<meta name="viewport" content="width=device-width, initial-scale=1.0"> informuje przeglądarkę mobilną, żeby dopasowała szerokość strony do szerokości urządzenia i nie stosowała domyślnego zoomu. Dlaczego tak? Ponieważ w wypadku braku tego tagu przeglądarka renderuje stronę w szerokim wirtualnym viewportcie i całość wygląda jak pomniejszony desktop — responsywne style działają, ale efekt jest niewidoczny.

Jakie breakpointy powinienem używać w media queries?

Nie ma jednego słusznego zestawu, popularnym punktem startowym są w wypadku tabletu 768px, desktop to 1024px oraz duży desktop1280px — zbliżone do breakpointów Tailwind CSS. Najlepiej jednak dobierać breakpointy na podstawie tego, gdzie treść zaczyna wyglądać bardzo źle, a nie na podstawie listy urządzeń.

Czym jest clamp() i jak go używać do responsywnej typografii?

clamp(min, preferowane, max) określa zakres, w którym obraz płynnie skaluje się między minimum a maksimum. Na przykład font-size: clamp(1rem, 4vw, 2rem) oznacza: minimum 16px, 4% szerokości viewport jako wartość preferowaną, maksimum 32px, eliminuje to potrzebę media queries dla podstawowych rozmiarów tekstu i odstępów.

Co to są container queries i kiedy je stosować?

Container queries reagują na rozmiar elementu rodzica, a nie całego viewport. Używa się ich dla komponentów wielokrotnego użytku (np. karta produktu), które mogą być umieszczone zarówno w wąskim sidebarze, jak i szerokim głównym obszarze treści, a każde z innym layoutem.

Jak obsługiwać responsywne obrazy w HTML?

Podstawa to max-width: 100% i height: auto w CSS, dla lepszej wydajności używaj srcset z atrybutem sizes, żeby przeglądarka pobierała odpowiedni rozmiar obrazu dla wybranego ekranu. Element <picture> pozwala serwować zupełnie różne obrazy (np. kadrowanie dostosowane do mobile).

Jak testować responsywność strony?

Zacznij od Chrome DevTools, przez toggle device toolbar (Ctrl+Shift+M) możemy symulować różne rozmiary ekranów oraz urządzenia. Ważne jest też testowanie na prawdziwych urządzeniach, ponieważ emulacja nie oddaje wszystkiego np. wydajności czy renderowania. Rzuć też okiem na orientację poziomą i upewnij się, że nie ma poziomego przewijania.

O autorze

Maciej Sala

Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwijam własne projekty.

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy na temat UX

Czytaj dalej

Zobacz więcej wpisów
Core Web Vitals — jak przyspieszyć stronę i poprawić pozycję w Google

Google od wielu lat podkreśla, że wydajność i doświadczenie użytkownika mają znaczenie i Core Web Vitals są częścią sygnałów page experience. Najważniejsze jest jednak to, że wreszcie mierzą coś bardzo konkretnego: czy strona błyskawicznie pokazuje treść, czy odpowiednio reaguje na interakcje i czy nie „skacze" nieprzyjemnie podczas ładowania.

Maciej Sala

Maciej Sala

Founder StriveLab

next/image vs srcset vs CDN: ostateczny poradnik optymalizacji obrazów w Next.js

Obrazy są najcięższym bagażem większości stron internetowych. W skrajnych przypadkach, jedno niezoptymalizowane zdjęcie potrafi dorzucić kilka sekund do LCP, a brak zarezerwowanego miejsca rozjeżdża layout. Next.js daje gotowe narzędzie, next/image , ale to nie zawsze będzie to najlepszy wybór, dlatego porównuję trzy podejścia: komponent next/image , natywny srcset i dedykowane CDN do obrazów.

Maciej Sala

Maciej Sala

Founder StriveLab

Jak kontrolować JS w Astro? Dyrektywy klienta w praktyce

Oznaczanie wszystkich komponentów client:load w projektach Astro niweczy ich potencjał. W rezultacie strona, która powinna być wydajna jak samochód wyścigowy, zachowuje się jak tramwaj z lat 70. Dyrektywy hydratacji to kontrakt wydajnościowy, którego warunki bezpośrednio determinują wydajność aplikacji.

Maciej Sala

Maciej Sala

Founder StriveLab