// csstahak/ · 10 z 10 — poslední stránka

Responzivita & Media Queries

@media, container queries, viewport jednotky, mobile-first přístup, breakpointy, prefers-* — kompletní průvodce responzivním designem.

Mobile-first přístup

Základ moderní responzivity

Píšte styly nejprve pro mobil, pak přidávejte breakpointy pro větší obrazovky pomocí min-width.

Mobile-first: základní CSS je pro nejmenší obrazovku. Přidáváme styly pro větší viewport pomocí min-width. Výhody: menší CSS pro mobily (nejčastější zařízení), přirozená progresivní logika, výkon. Desktop-first (max-width) je opak — styly pro desktop, pak "odstraňování" pro mobil.

// Proč min-width místo max-widthMobile-first s min-width: CSS se načítá pro nejmenší zařízení, větší dostávají víc. Přirozená logika. Desktop-first s max-width: na mobilu se stahuje desktopové CSS a přepisuje se. Horší výkon. Google preferuje mobile-first (mobile-first indexing).
Mobile-first vs Desktop-first
✅ Mobile-first (min-width) Základní = mobil, přidáváme pro větší. Přirozené, výkonnější.
❌ Desktop-first (max-width) Základní = desktop, přepisujeme pro mobil. Méně přirozené.
  • min-width pro mobile-first (preferováno)
  • max-width pro desktop-first (starší přístup)
  • Začněte layoutem pro 320px — pak rozšiřujte
  • Klíčové: obsah určuje breakpointy, ne zařízení
Mobile-first vs Desktop-first srovnání
CSS
/* ✅ MOBILE-FIRST (min-width) */
/* Základní = pro mobil */
.card { flex-direction: column; }
.sidebar { display: none; }
.grid { grid-template-columns: 1fr; }

/* Přidáváme pro větší */
@media (min-width: 640px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .card { flex-direction: row; }
  .sidebar { display: block; }
  .grid { grid-template-columns: repeat(3, 1fr); }
}

/* ❌ DESKTOP-FIRST (max-width) */
/* Základní = pro desktop */
.grid { grid-template-columns: repeat(3, 1fr); }
.sidebar { display: block; }

/* Přepisujeme pro menší */
@media (max-width: 1023px) {
  .sidebar { display: none; }
  .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 639px) {
  .grid { grid-template-columns: 1fr; }
}
@media

Media queries

Aplikovat CSS podmíněně. min-width, max-width, orientation, prefers-color-scheme, hover a další.

@media aplikuje styly pokud je splněna podmínka. Typy médií: screen, print, all. Funkce: min-width, max-width, orientation, hover, pointer, prefers-color-scheme, prefers-reduced-motion, prefers-contrast, forced-colors. Kombinovat: and, or (čárka), not.

// Obsah určuje breakpointyNenavrhujte breakpointy pro konkrétní zařízení (iPhone, iPad...). Zmenšujte okno prohlížeče — kde se design "zlomí"? Tam přidejte breakpoint. Breakpointy jsou specifické pro váš obsah, ne pro zařízení.
Breakpoint systém (doporučený)
xs
0–639
sm
640–767
md
768–1023
lg
1024–1279
xl
1280–1535
2xl
1536+
Klíčové media features
min-widthŠířka viewportu ≥ hodnota (mobile-first)
max-widthŠířka viewportu ≤ hodnota (desktop-first)
orientationportrait nebo landscape
hoverhover: hover = má myš, hover: none = touch
pointerpointer: coarse = touch, pointer: fine = myš
prefers-color-schemelight nebo dark
prefers-reduced-motionreduce = animace minimalizovat
prefers-contrastmore nebo less — kontrast preference
forced-colorsWindows Contrast Mode (high contrast)
printTiskový mód — výčet specificky
  • Obsah určuje breakpointy, ne zařízení
  • hover: none = zařízení bez myši (mobil, tablet)
  • pointer: coarse = nepřesný vstup (prst)
  • @media print pro tiskové styly
Příklady
CSS
/* Základní breakpointy (Tailwind-inspired) */
/* xs: < 640px  — žádný breakpoint (default) */
/* sm: ≥ 640px */
@media (min-width: 640px)  { }
/* md: ≥ 768px */
@media (min-width: 768px)  { }
/* lg: ≥ 1024px */
@media (min-width: 1024px) { }
/* xl: ≥ 1280px */
@media (min-width: 1280px) { }

/* Kombinace podmínek */
@media (min-width: 768px) and (max-width: 1023px) {
  /* Pouze tablet */
}
@media (min-width: 768px), print {
  /* Tablet nebo tisk (čárka = OR) */
}
@media not (min-width: 1024px) {
  /* Negace (ne desktop) */
}

/* Orientace */
@media (orientation: landscape) {
  .hero { min-height: 50vh; }
}

/* Touch vs myš */
@media (hover: none) {
  /* Zařízení bez myši (mobil) */
  .hover-menu { display: none; }
  .touch-menu { display: block; }
}
@media (hover: hover) {
  /* Zařízení s myší */
  .btn:hover { background: #1d4ed8; }
}

/* Preference */
@media (prefers-color-scheme: dark) {
  :root { --bg: #0a0a0f; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; }
}
@media (prefers-contrast: more) {
  :root { --border: #000; }
}

/* Tisk */
@media print {
  .nav, .footer, .sidebar { display: none; }
  body { font-size: 12pt; color: #000; }
  a::after { content: " (" attr(href) ")"; }
  @page { margin: 2cm; }
}

/* CSS proměnné s breakpointy */
:root { --cols: 1; }
@media (min-width: 640px) { :root { --cols: 2; } }
@media (min-width: 1024px) { :root { --cols: 3; } }
.grid {
  grid-template-columns: repeat(var(--cols), 1fr);
}
@container

Container queries

Stylování dle šířky rodiče — ne viewportu. Základ skutečně znovupoužitelných komponent. CSS 2023.

CSS 2023

Container queries umožňují stylovat element podle rozměrů jeho rodiče, ne celého okna. Komponent se přizpůsobí kde je umístěn — v sidebaru bude úzký, v main contentu bude wide. Bez úprav na místě použití.

// Container vs media queryMedia query: .card reaguje na šířku okna. Container query: .card reaguje na šířku svého kontejneru. Výsledek: stejná .card v sidebaru zobrazí sloupec, v main contentu zobrazí řadu — bez jediné media query na místě použití.
Kroky pro container queries
1. Rodič: container-type: inline-size;
2. Dítě: @container (min-width: 400px) { ... }
Živá ukázka — tažte za okraj
← táhněte za pravý okraj pro změnu šířky →
Produkt
Karta reaguje na šířku kontejneru, ne okna.
container-type hodnoty
normal inline-size ← nejčastější size
  • container-type: inline-size = sleduje šířku
  • container-type: size = sleduje šířku i výšku
  • container-name pro pojmenované kontejnery
  • Nelze stylovat samotný kontejner — jen jeho děti
  • Podpora: Chrome 105+, Firefox 110+, Safari 16+
Příklady
CSS
/* 1. Definice kontejneru */
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

/* 2. Stylování dle kontejneru */
.card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

@container card (min-width: 400px) {
  .card {
    flex-direction: row;
    align-items: center;
  }
  .card-img {
    width: 40%;
    flex-shrink: 0;
  }
}

@container card (min-width: 600px) {
  .card { gap: 2rem; }
  .card-title { font-size: 1.5rem; }
}

/* Bez pojmenování */
.sidebar { container-type: inline-size; }

@container (min-width: 300px) {
  .widget { /* Reaguje na sidebar šířku */ }
}

/* Container query + grid */
.products {
  container-type: inline-size;
}
.product-grid {
  display: grid;
  grid-template-columns: 1fr;
}
@container (min-width: 500px) {
  .product-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@container (min-width: 800px) {
  .product-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Logické operátory */
@container (min-width: 400px) and
           (max-width: 700px) {
  .card { /* Jen v tomto rozmezí */ }
}

/* Container Units (cqw, cqh...) */
.responsive-text {
  font-size: clamp(1rem, 4cqw, 2rem);
  /* 4% šířky kontejneru, min 1rem, max 2rem */
}
Viewport jednotky

vw, vh, dvh, svh, lvh, vmin, vmax, vi, vb

dvh/svh řeší problém mobilního prohlížeče s adresním řádkem. Moderní viewport jednotky.

MODERNÍ

vh = výška viewportu — ale na mobilu se počítá bez adresního řádku → overflow. dvh (Dynamic) = mění se se scrollem. svh (Small) = nejmenší výška (s adresním řádkem). lvh (Large) = největší výška (bez adresního řádku). vw = viewport width.

// Problém 100vh na mobiluNa mobilu: 100vh = výška viewportu při načtení stránky (bez adresního řádku). Při scrollu adresní řádek zmizí → stránka je kratší než 100vh. Rušivé "skočení". Řešení: min-height: 100dvh (dynamic) nebo 100svh (conservative).
Přehled viewport jednotek
vw
1% šířky viewportu
vh
1% výšky viewportu (starý)
dvh
Dynamic vh (mění se)
svh
Small vh (konzervativní)
lvh
Large vh (maximální)
vmin
Menší z vw/vh
vmax
Větší z vw/vh
cqw
1% šířky kontejneru
  • min-height: 100dvh místo 100vh pro hero sekce
  • svh = nejbezpečnější pro mobily (s adresním řádkem)
  • vw: 100vw způsobí vodorovný scroll (scrollbar šířka)
  • 100% místo 100vw pro šířku kontejnerů
Příklady
CSS
/* Hero sekce — mobilní fix */
.hero {
  /* Starý způsob — problém na mobilu */
  min-height: 100vh;

  /* ✅ Moderní — dvh */
  min-height: 100dvh;

  /* ✅ Konzervativní — svh */
  min-height: 100svh;

  /* Fallback pro starší prohlížeče */
  min-height: 100vh;
  min-height: 100dvh;
}

/* Full viewport overlay */
.modal-backdrop {
  position: fixed;
  inset: 0;
  /* inset: 0 = top:0 right:0 bottom:0 left:0 */
  /* Nepotřebuje vh */
}

/* Fluid typografie s vw */
.display-title {
  font-size: clamp(2rem, 8vw, 6rem);
}

/* Čtverec z viewport */
.vp-square {
  width: 50vmin;
  height: 50vmin; /* = 50% menší strany */
}

/* Full width bez scrollbaru */
.full-width {
  width: 100%;   /* ✅ správně */
  /* width: 100vw; ❌ může způsobit scroll */
}

/* Breakpoint bez media query */
.responsive-font {
  font-size: clamp(1rem, 2vw + 0.5rem, 1.5rem);
}

/* Container jednotky */
.container { container-type: inline-size; }
.title {
  font-size: clamp(1rem, 5cqw, 2rem);
}
Responzivní obrázky

srcset, sizes, picture — správné obrázky na správném displeji

Prohlížeč vybere optimální obrázek dle viewport šířky a DPR displeje.

Responzivní obrázky zajistí správnou velikost pro každé zařízení — malý obrázek na mobilu, velký na desktopu, 2× pro Retina displeje. srcset + sizes = nápověda pro prohlížeč. picture = pevná pravidla (art direction, formáty).

// srcset vs picturesrcset+sizes: dáte prohlížeči možnosti, on vybere optimální (dle DPR, viewport, cache). picture: vy určíte přesná pravidla — pro art direction (různý ořez pro mobil/desktop) nebo pro formáty (AVIF/WebP/JPG).
Deskriptory srcset
400w — pixel šířka souboru 2x — DPR pro Retina
  • loading="lazy" pro obrázky pod záhybem
  • loading="eager" pro LCP hero obrázek
  • width + height atributy zabrání CLS
  • decoding="async" pro neblokující dekódování
  • Squoosh.app nebo sharp pro generování formátů
Příklady
HTML + CSS
<!-- srcset + sizes -->
<img
  src="hero-800.jpg"
  srcset="
    hero-400.jpg  400w,
    hero-800.jpg  800w,
    hero-1200.jpg 1200w,
    hero-1600.jpg 1600w
  "
  sizes="
    (max-width: 640px)  100vw,
    (max-width: 1024px) 80vw,
    1200px
  "
  alt="Hero obrázek"
  width="1200" height="600"
  loading="eager"
  decoding="async"
>

<!-- picture: formáty + fallback -->
<picture>
  <source type="image/avif"
    srcset="img.avif 1x, img@2x.avif 2x">
  <source type="image/webp"
    srcset="img.webp 1x, img@2x.webp 2x">
  <img src="img.jpg"
    srcset="img@2x.jpg 2x"
    alt="Popis"
    width="800" height="600"
    loading="lazy">
</picture>

<!-- Art direction: jiný ořez -->
<picture>
  <source media="(max-width: 640px)"
    srcset="hero-mobile.jpg">
  <source media="(max-width: 1024px)"
    srcset="hero-tablet.jpg">
  <img src="hero-desktop.jpg"
    alt="Hero" width="1440" height="600">
</picture>

/* CSS: responzivní obrázky */
img {
  max-width: 100%;
  height: auto;
  display: block;
}
.card-img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
prefers-* media features

Uživatelské preference

prefers-color-scheme, prefers-reduced-motion, prefers-contrast, prefers-reduced-data — respektujte nastavení systému.

CSS dokáže detekovat systémové preference uživatele a přizpůsobit se jim automaticky — bez JavaScriptu. prefers-color-scheme: dark/light motiv. prefers-reduced-motion: méně animací. prefers-contrast: vyšší kontrast. forced-colors: Windows High Contrast Mode.

Přehled prefers-* features
prefers-color-schemelight / dark — systémový motiv
prefers-reduced-motionno-preference / reduce
prefers-contrastno-preference / more / less
prefers-reduced-datano-preference / reduce (datová úspora)
forced-colorsnone / active (Windows HC Mode)
prefers-reduced-transparencyno-preference / reduce
  • prefers-color-scheme: dark — podrobně v 09-promenne
  • prefers-reduced-motion — podrobně v 07-animace
  • forced-colors: Systém vybere barvy — respektujte!
  • prefers-reduced-data: nenačítat velké obrázky
Příklady
CSS
/* Dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0a0a0f;
    --text: #f3f4f6;
  }
}

/* Animace */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Vyšší kontrast */
@media (prefers-contrast: more) {
  :root {
    --border: #000000;
    --text: #000000;
    --bg: #ffffff;
  }
  .btn { border: 2px solid currentColor; }
}

/* Datová úspora (nenačítat velké obrázky) */
@media (prefers-reduced-data: reduce) {
  .hero-bg { background-image: none; }
  .video-autoplay { display: none; }
}

/* Windows High Contrast Mode */
@media (forced-colors: active) {
  .custom-checkbox {
    forced-color-adjust: none;
    /* Použijte vlastní barvy i v HC */
  }
  .btn {
    border: 2px solid ButtonText;
  }
}

/* Průhlednost */
@media (prefers-reduced-transparency: reduce) {
  .glass {
    backdrop-filter: none;
    background: rgba(255,255,255,0.95);
  }
}
// Copy-paste: kompletní responzivní CSS základ
CSS — production-ready responsive base
/* === KOMPLETNÍ RESPONZIVNÍ ZÁKLAD === */

/* 1. Viewport meta (v HTML <head>) */
/* <meta name="viewport"
     content="width=device-width, initial-scale=1.0"> */

/* 2. Reset a box-model */
*, *::before, *::after { box-sizing: border-box; }
img, video { max-width: 100%; height: auto; }

/* 3. CSS proměnné pro breakpointy */
:root {
  --bp-sm:  640px;
  --bp-md:  768px;
  --bp-lg:  1024px;
  --bp-xl:  1280px;
  --bp-2xl: 1536px;
}

/* 4. Fluid typografie */
:root {
  --text-sm:   clamp(0.875rem, 1vw,  0.9375rem);
  --text-base: clamp(1rem,     1.5vw, 1.125rem);
  --text-xl:   clamp(1.25rem,  2vw,   1.5rem);
  --text-3xl:  clamp(2rem,     5vw,   3rem);
}

/* 5. Kontejner */
.container {
  width: min(90%, 1280px);
  margin-inline: auto;
  padding-inline: 1rem;
}

/* 6. Responzivní grid */
.auto-grid {
  display: grid;
  grid-template-columns:
    repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: clamp(1rem, 2vw, 2rem);
}

/* 7. Responzivní layout s media queries */
.layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
@media (min-width: 768px) {
  .layout {
    grid-template-columns: 240px 1fr;
  }
}

/* 8. Responzivní stack → row */
.card { display: flex; flex-direction: column; }
@media (min-width: 640px) {
  .card { flex-direction: row; }
}

/* 9. Container queries pro komponenty */
.card-wrapper {
  container-type: inline-size;
}
@container (min-width: 400px) {
  .card { flex-direction: row; }
}

/* 10. Hero sekce s dvh */
.hero {
  min-height: 100svh; /* konzervativní */
  min-height: 100dvh; /* moderní */
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 11. Responzivní typography scale */
h1 { font-size: clamp(2rem,   5vw, 4rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.5rem); }
h3 { font-size: clamp(1.25rem, 2vw, 1.75rem); }
p  { font-size: var(--text-base); line-height: 1.6; }

/* 12. Utility classes */
.hide-mobile  { display: none; }
.hide-desktop { display: block; }
@media (min-width: 768px) {
  .hide-mobile  { display: block; }
  .hide-desktop { display: none; }
}

/* 13. Prefers */
@media (prefers-color-scheme: dark) { /* ... */ }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
@media print {
  .nav, aside, footer { display: none; }
  body { font-size: 12pt; color: #000; }
}
🎉

CSS Taháček dokončen!

Prošli jste všechny kapitoly — Box Model, Flexbox, Grid, Typografie, Barvy, Layout, Animace, Pseudo selektory, Proměnné a Responzivitu.

← CSS přehled HTML taháček ↗
← 09 Proměnné 10 / 10 — Responzivita ↑ CSS Přehled