@media, container queries, viewport jednotky, mobile-first přístup, breakpointy, prefers-* — kompletní průvodce responzivním designem.
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.
/* ✅ 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; }
}
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.
| min-width | Šířka viewportu ≥ hodnota (mobile-first) |
| max-width | Šířka viewportu ≤ hodnota (desktop-first) |
| orientation | portrait nebo landscape |
| hover | hover: hover = má myš, hover: none = touch |
| pointer | pointer: coarse = touch, pointer: fine = myš |
| prefers-color-scheme | light nebo dark |
| prefers-reduced-motion | reduce = animace minimalizovat |
| prefers-contrast | more nebo less — kontrast preference |
| forced-colors | Windows Contrast Mode (high contrast) |
| Tiskový mód — výčet specificky |
/* 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);
}
Stylování dle šířky rodiče — ne viewportu. Základ skutečně znovupoužitelných komponent. 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í.
1. Rodič: container-type: inline-size; 2. Dítě: @container (min-width: 400px) { ... }
/* 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 */
}
dvh/svh řeší problém mobilního prohlížeče s adresním řádkem. Moderní viewport jednotky.
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.
/* 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);
}
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 + 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-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.
| prefers-color-scheme | light / dark — systémový motiv |
| prefers-reduced-motion | no-preference / reduce |
| prefers-contrast | no-preference / more / less |
| prefers-reduced-data | no-preference / reduce (datová úspora) |
| forced-colors | none / active (Windows HC Mode) |
| prefers-reduced-transparency | no-preference / reduce |
/* 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);
}
}
/* === 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; }
}
Prošli jste všechny kapitoly — Box Model, Flexbox, Grid, Typografie, Barvy, Layout, Animace, Pseudo selektory, Proměnné a Responzivitu.