Component
Syntax
Description
Example
@media
@media type and (feature)
Apply styles conditionally based on device characteristics
@media screen and (min-width: 768px)
Media Types
all | screen | print | speech
Target specific device types
@media print { ... }
Logical Operators
and | or | not | only
Combine multiple media features
(min-width: 768px) and (max-width: 1024px)
Width Queries
min-width | max-width | width
Query viewport or container width
(min-width: 768px)
Height Queries
min-height | max-height | height
Query viewport or container height
(min-height: 600px)
Orientation
portrait | landscape
Detect device orientation
(orientation: landscape)
Aspect Ratio
aspect-ratio: width/height
Query viewport aspect ratio
(aspect-ratio: 16/9)
Resolution
resolution: value
Query pixel density (dpi, dpcm, dppx)
(resolution: 2dppx) for Retina
Display Mode
display-mode: value
Detect PWA display mode
(display-mode: standalone)
Pointer
pointer: none | coarse | fine
Primary input mechanism precision
(pointer: coarse) for touch
Hover
hover: none | hover
Can primary input hover over elements
(hover: hover) for mouse
Any-pointer
any-pointer: none | coarse | fine
Any available input mechanism
(any-pointer: fine)
Any-hover
any-hover: none | hover
Any available input can hover
(any-hover: hover)
/* Mobile-first approach (min-width) */
.container {
width : 100 % ;
}
@media ( min-width : 768 px ) {
.container {
width : 750 px ;
}
}
@media ( min-width : 1024 px ) {
.container {
width : 980 px ;
}
}
@media ( min-width : 1280 px ) {
.container {
width : 1200 px ;
}
}
/* Desktop-first approach (max-width) */
.nav {
display : flex ;
}
@media ( max-width : 1023 px ) {
.nav {
display : none ;
}
}
/* Range queries (Level 4 syntax) */
@media ( 768 px <= width <= 1024 px ) {
.tablet-only {
display : block ;
}
}
/* Multiple conditions */
@media screen and ( min-width : 768 px ) and ( orientation : landscape ) {
.landscape-tablet {
grid-template-columns : repeat ( 3 , 1 fr );
}
}
/* Print styles */
@media print {
.no-print {
display : none ;
}
body {
font-size : 12 pt ;
color : black ;
background : white ;
}
}
Example: User interaction and device queries
/* Touch device detection */
@media ( hover : none) and (pointer: coarse) {
/* Touch-only device */
button {
min-height : 44 px ; /* Larger touch targets */
min-width : 44 px ;
}
}
/* Mouse/trackpad device */
@media ( hover : hover ) and (pointer: fine) {
.interactive:hover {
background : #f0f0f0 ;
}
}
/* Hybrid device (touch + mouse) */
@media (any-hover: hover ) {
.tooltip {
display : none ;
}
.element:hover .tooltip {
display : block ;
}
}
/* High-resolution displays (Retina) */
@media ( resolution : 2 dppx ), ( resolution : 192 dpi ) {
.logo {
background-image : url ( 'logo@2x.png' );
background-size : 100 px 50 px ;
}
}
/* PWA standalone mode */
@media ( display-mode : standalone ) {
.install-prompt {
display : none ;
}
.app-header {
padding-top : env(safe-area-inset-top);
}
}
/* Landscape orientation */
@media ( orientation : landscape ) {
.video-player {
height : 100 vh ;
}
}
/* Specific aspect ratios */
@media ( aspect-ratio : 16 / 9 ) {
.widescreen-layout {
display : grid ;
grid-template-columns : 2 fr 1 fr ;
}
}
Note: Use (hover: hover) to distinguish devices with mouse from touch devices. Use
any-hover for hybrid devices. Modern Level 4 range syntax: (width >= 768px) is
cleaner than (min-width: 768px).
2. Responsive Length Units and Viewport
Unit
Full Name
Description
Use Case
vw
Viewport Width
1% of viewport width
Full-width elements, responsive font sizes
vh
Viewport Height
1% of viewport height
Full-height sections, hero images
vmin
Viewport Minimum
1% of smaller viewport dimension
Square elements that fit any orientation
vmax
Viewport Maximum
1% of larger viewport dimension
Background images, diagonal layouts
svh NEW
Small Viewport Height
Height when UI is expanded (mobile)
Fixed mobile headers, reliable 100% height
lvh NEW
Large Viewport Height
Height when UI is retracted
Full-screen experiences
dvh NEW
Dynamic Viewport Height
Adjusts as browser UI shows/hides
Smooth mobile experiences
vi, vb
Viewport Inline/Block
Writing mode aware viewport units
Internationalized layouts
%
Percentage
Relative to parent element
Fluid layouts, responsive sizing
rem
Root Em
Relative to root font-size (html)
Consistent spacing, scalable layouts
em
Em
Relative to parent font-size
Component-scoped scaling
ch
Character
Width of "0" character
Optimal reading line length (45-75ch)
ex
X-height
Height of lowercase "x"
Vertical rhythm, icon sizing
Example: Viewport units for responsive layouts
/* Full-viewport hero section */
.hero {
height : 100 vh ; /* May have issues on mobile */
height : 100 dvh ; /* Better: adjusts with mobile browser UI */
display : flex ;
align-items : center ;
justify-content : center ;
}
/* Mobile-safe full height */
.mobile-full-height {
min-height : 100 svh ; /* Smallest viewport (UI visible) */
min-height : 100 dvh ; /* Fallback for dynamic */
}
/* Fluid typography with viewport units */
.responsive-text {
font-size : calc ( 16 px + 1 vw ); /* Grows with viewport */
/* Better: use clamp() for min/max bounds */
}
/* Square element regardless of orientation */
.square {
width : 50 vmin ;
height : 50 vmin ;
}
/* Responsive spacing with rem */
:root {
font-size : 16 px ;
}
@media ( min-width : 768 px ) {
:root {
font-size : 18 px ; /* All rem values scale up */
}
}
.section {
padding : 2 rem ; /* 32px mobile, 36px tablet+ */
margin-bottom : 3 rem ;
}
/* Optimal reading width */
.article {
max-width : 65 ch ; /* ~65 characters per line */
margin : 0 auto ;
}
/* Percentage-based fluid grid */
.grid {
display : grid ;
grid-template-columns : repeat ( auto-fit , minmax ( 250 px , 1 fr ));
gap : 2 % ; /* Scales with container */
}
Example: Small/Large/Dynamic viewport units (mobile)
/* Problem: 100vh on mobile includes browser UI space */
.old-full-height {
height : 100 vh ; /* May extend below visible area */
}
/* Solution 1: Small viewport (UI always visible) */
.safe-full-height {
height : 100 svh ; /* Accounts for mobile browser chrome */
}
/* Solution 2: Large viewport (UI hidden) */
.expanded-full-height {
height : 100 lvh ; /* Maximum available space */
}
/* Solution 3: Dynamic (recommended) */
.adaptive-full-height {
height : 100 vh ; /* Fallback */
height : 100 dvh ; /* Smoothly adjusts as UI shows/hides */
}
/* Width equivalents */
.full-width {
width : 100 vw ; /* Standard */
width : 100 dvw ; /* Dynamic (for horizontal scrolling scenarios) */
}
/* Practical example: Mobile modal */
.modal-overlay {
position : fixed ;
inset : 0 ;
height : 100 dvh ; /* Covers visible viewport */
width : 100 dvw ;
background : rgba ( 0 , 0 , 0 , 0.5 );
}
.modal-content {
max-height : 90 dvh ; /* Leave space for gestures */
overflow-y : auto ;
}
Warning: 100vh on mobile includes browser UI, causing overflow. Use
100dvh for dynamic adjustment or 100svh for consistently safe height. Browser support:
Chrome 108+, Safari 15.4+.
3. Container Queries Implementation NEW
Property
Syntax
Description
Example
container-type
size | inline-size | normal
Define element as query container
container-type: inline-size;
container-name
name
Name container for targeted queries
container-name: sidebar;
container
name / type
Shorthand for name and type
container: card / inline-size;
@container
@container (condition) { }
Query container dimensions
@container (min-width: 400px)
cqw
Container Query Width
1% of container's width
font-size: 5cqw;
cqh
Container Query Height
1% of container's height
padding: 2cqh;
cqi
Container Query Inline
1% of inline axis (width in LTR)
margin: 3cqi;
cqb
Container Query Block
1% of block axis (height in LTR)
gap: 2cqb;
cqmin, cqmax
Container Query Min/Max
1% of smaller/larger dimension
width: 50cqmin;
Example: Container queries for component-based responsive design
/* Define container */
.card-grid {
container-type : inline-size;
container-name : card-container;
display : grid ;
grid-template-columns : repeat ( auto-fit , minmax ( 250 px , 1 fr ));
gap : 1 rem ;
}
/* Query container, not viewport */
.card {
padding : 1 rem ;
}
@container (min-width: 400px) {
.card {
display : grid ;
grid-template-columns : 150 px 1 fr ;
gap : 1 rem ;
}
.card-image {
height : 150 px ;
}
}
@container (min-width: 600px) {
.card {
grid-template-columns : 200 px 1 fr ;
}
.card-title {
font-size : 1.5 rem ;
}
}
/* Named container queries */
.sidebar {
container : sidebar / inline-size;
}
@container sidebar (min-width: 300px) {
.sidebar-widget {
display : block ;
}
}
@container sidebar (min-width: 500px) {
.sidebar-widget {
display : grid ;
grid-template-columns : 1 fr 1 fr ;
}
}
Example: Container query units for intrinsic responsive design
/* Responsive typography with container units */
.container {
container-type : inline-size;
}
.headline {
font-size : clamp ( 1 rem , 5 cqi , 3 rem );
/* Scales with container, not viewport */
}
/* Container-relative spacing */
.card {
padding : 3 cqi 4 cqi ;
gap : 2 cqi ;
}
/* Grid with container units */
@container (min-width: 500px) {
.grid {
display : grid ;
grid-template-columns : 30 cqi 1 fr ;
gap : 3 cqi ;
}
}
/* Aspect ratio with container units */
.media {
width : 100 cqi ;
height : 56 cqi ; /* 16:9 aspect ratio based on container */
}
/* Fluid icon sizing */
.icon {
width : 8 cqi ;
height : 8 cqi ;
max-width : 48 px ; /* Cap size */
}
/* Container-relative transforms */
.floating-element {
transform : translateX ( 10 cqi );
}
/* Responsive grid tracks */
.responsive-grid {
display : grid ;
grid-template-columns : repeat ( auto-fill , minmax ( 25 cqi , 1 fr ));
gap : 2 cqi ;
}
Note: Container queries enable true component-based responsive
design . Components adapt to their container size, not viewport. Use inline-size for
width-only queries (most common). Browser support: Chrome 105+, Safari 16+, Firefox 110+.
4. Responsive Typography with clamp()
Function
Syntax
Description
Use Case
clamp()
clamp(min, preferred, max)
Value between min and max bounds
Fluid typography that scales with viewport
min()
min(value1, value2, ...)
Smallest of provided values
Ensure element doesn't exceed size
max()
max(value1, value2, ...)
Largest of provided values
Ensure minimum size is maintained
calc()
calc(expression)
Mathematical calculations
Combine units, create fluid scales
Example: Fluid typography with clamp()
/* Fluid font-size that scales between bounds */
h1 {
font-size : clamp ( 2 rem , 5 vw , 4 rem );
/* Min: 2rem (32px)
Preferred: 5vw (grows with viewport)
Max: 4rem (64px) */
}
h2 {
font-size : clamp ( 1.5 rem , 3 vw + 1 rem , 3 rem );
}
p {
font-size : clamp ( 1 rem , 0.9 rem + 0.5 vw , 1.25 rem );
}
/* Fluid spacing */
.section {
padding : clamp ( 1 rem , 5 vw , 4 rem ) clamp ( 1 rem , 5 vw , 2 rem );
margin-bottom : clamp ( 2 rem , 8 vh , 6 rem );
}
/* Fluid line-height */
.article {
line-height : clamp ( 1.4 , 1.2 + 0.5 vw , 1.8 );
}
/* Type scale with clamp() */
:root {
--fs-xs : clamp ( 0.75 rem , 0.7 rem + 0.25 vw , 0.875 rem );
--fs-sm : clamp ( 0.875 rem , 0.8 rem + 0.4 vw , 1 rem );
--fs-base : clamp ( 1 rem , 0.9 rem + 0.5 vw , 1.125 rem );
--fs-lg : clamp ( 1.125 rem , 1 rem + 0.6 vw , 1.5 rem );
--fs-xl : clamp ( 1.5 rem , 1.2 rem + 1.5 vw , 2.5 rem );
--fs-2xl : clamp ( 2 rem , 1.5 rem + 2.5 vw , 4 rem );
}
.text-xs { font-size : var ( --fs-xs ); }
.text-sm { font-size : var ( --fs-sm ); }
.text-base { font-size : var ( --fs-base ); }
.text-lg { font-size : var ( --fs-lg ); }
.text-xl { font-size : var ( --fs-xl ); }
.text-2xl { font-size : var ( --fs-2xl ); }
Example: Responsive layout with min/max/clamp
/* Fluid container width */
.container {
width : min ( 100 % - 2 rem , 1200 px );
/* Never exceeds 1200px, has 1rem padding on mobile */
margin : 0 auto ;
}
/* Responsive grid columns */
.grid {
display : grid ;
grid-template-columns : repeat ( auto-fit , minmax ( min ( 250 px , 100 % ), 1 fr ));
/* Columns min 250px but won't break on narrow screens */
gap : clamp ( 1 rem , 3 vw , 2 rem );
}
/* Fluid gap sizing */
.flex-container {
display : flex ;
gap : clamp ( 0.5 rem , 2 vw , 2 rem );
}
/* Responsive padding without media queries */
.card {
padding : clamp ( 1 rem , 4 vw , 3 rem );
}
/* Optimal reading width */
.article {
max-width : min ( 65 ch , 100 % - 4 rem );
/* Max 65 characters but leaves margin on narrow screens */
}
/* Fluid border-radius */
.button {
border-radius : clamp ( 4 px , 0.5 vw , 8 px );
}
/* Height constraints */
.hero {
min-height : max ( 400 px , 50 vh );
/* At least 400px, but grows on tall screens */
}
/* Aspect ratio with bounds */
.video-container {
height : clamp ( 300 px , 56.25 vw , 720 px );
/* Maintains ~16:9 ratio with min/max */
}
Example: Advanced fluid typography calculation
/* Calculate fluid typography slope */
/*
Formula: clamp(minSize, minSize + (maxSize - minSize) * ((100vw - minVw) / (maxVw - minVw)), maxSize)
Example calculation for h1:
- Viewport range: 320px to 1200px
- Font size range: 24px to 64px
*/
h1 {
/* Simple version */
font-size : clamp ( 1.5 rem , 2 vw + 1 rem , 4 rem );
/* Precise calculation */
font-size : clamp (
1.5 rem ,
1.5 rem + (4 - 1.5 ) * (( 100 vw - 20 rem ) / (75 - 20)),
4 rem
);
}
/* Fluid type scale generator */
:root {
/* Base settings */
--fluid-min-width : 320 ;
--fluid-max-width : 1200 ;
--fluid-min-size : 16 ;
--fluid-max-size : 20 ;
/* Calculate slope */
--fluid-min-ratio : 1.2 ;
--fluid-max-ratio : 1.333 ;
/* Apply to scale */
--step-0 : clamp (
calc ( var ( --fluid-min-size ) * 1 px ),
calc (( var ( --fluid-min-size ) * 1 px ) + (var(--fluid-max-size ) - var ( --fluid-min-size )) * ((100 vw - ( var ( --fluid-min-width ) * 1 px )) / ( var ( --fluid-max-width ) - var ( --fluid-min-width )))),
calc ( var ( --fluid-max-size ) * 1 px )
);
}
/* Container query-based fluid typography */
.card-container {
container-type : inline-size;
}
.card-title {
font-size : clamp ( 1 rem , 5 cqi , 2.5 rem );
/* Scales with container, not viewport */
}
Note: clamp() eliminates most responsive typography media queries. Formula:
clamp(min, base + scaleFactor, max). Use viewport units (vw, vh) or container units (cqi, cqb) for
fluid scaling. Tools:
utopia.fyi for fluid type scale
generation.
5. Responsive Images and Picture Element
Feature
Syntax
Description
Use Case
srcset
srcset="url 1x, url 2x"
Multiple resolution image sources
Serve higher resolution for Retina displays
sizes
sizes="(query) width"
Define image display width at breakpoints
Let browser choose optimal image size
picture
<picture><source><img>
Art direction for different layouts
Different crops/images per breakpoint
source type
<source type="image/webp">
Serve modern image formats
WebP, AVIF with fallback to JPEG
loading
loading="lazy"
Native lazy loading
Defer offscreen images, improve performance
decoding
decoding="async"
Asynchronous image decoding
Non-blocking image loading
fetchpriority
fetchpriority="high"
Hint browser about image priority
Prioritize hero images, defer others
aspect-ratio
aspect-ratio: 16/9
Reserve space before image loads
Prevent layout shift (CLS)
object-fit
cover | contain | fill
Control image sizing in container
Maintain aspect ratio while fitting
object-position
top | center | 20% 40%
Position image within container
Focus on specific area when cropped
Example: Responsive images with srcset and sizes
<!-- Resolution switching (1x, 2x, 3x) -->
< img
src = "image-1x.jpg"
srcset = "image-1x.jpg 1x,
image-2x.jpg 2x,
image-3x.jpg 3x"
alt = "Description"
/>
<!-- Width-based selection -->
< img
src = "image-800w.jpg"
srcset = "image-400w.jpg 400w,
image-800w.jpg 800w,
image-1200w.jpg 1200w,
image-1600w.jpg 1600w"
sizes = "(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px"
alt = "Description"
/>
<!-- Browser selects best image based on:
- Screen width and DPR
- sizes attribute hints -->
<!-- Complex sizes attribute -->
< img
src = "fallback.jpg"
srcset = "small.jpg 400w,
medium.jpg 800w,
large.jpg 1200w"
sizes = "(max-width: 400px) 100vw,
(max-width: 800px) 80vw,
(max-width: 1200px) 60vw,
800px"
alt = "Responsive image"
loading = "lazy"
decoding = "async"
/>
Example: Picture element for art direction
<!-- Different images for different layouts -->
< picture >
<!-- Mobile: portrait crop -->
< source
media = "(max-width: 600px)"
srcset = "portrait-400w.jpg 400w,
portrait-800w.jpg 800w"
sizes = "100vw"
/>
<!-- Tablet: square crop -->
< source
media = "(max-width: 1200px)"
srcset = "square-600w.jpg 600w,
square-1200w.jpg 1200w"
sizes = "50vw"
/>
<!-- Desktop: landscape crop -->
< source
media = "(min-width: 1201px)"
srcset = "landscape-800w.jpg 800w,
landscape-1600w.jpg 1600w"
sizes = "800px"
/>
<!-- Fallback -->
< img src = "landscape-800w.jpg" alt = "Hero image" />
</ picture >
<!-- Modern format with fallback -->
< picture >
<!-- AVIF (best compression) -->
< source
type = "image/avif"
srcset = "image.avif"
/>
<!-- WebP (good compression) -->
< source
type = "image/webp"
srcset = "image.webp"
/>
<!-- JPEG fallback -->
< img src = "image.jpg" alt = "Description" />
</ picture >
<!-- Combine format and responsive sizing -->
< picture >
< source
type = "image/avif"
srcset = "image-400w.avif 400w,
image-800w.avif 800w"
sizes = "(max-width: 600px) 100vw, 50vw"
/>
< source
type = "image/webp"
srcset = "image-400w.webp 400w,
image-800w.webp 800w"
sizes = "(max-width: 600px) 100vw, 50vw"
/>
< img
src = "image-800w.jpg"
srcset = "image-400w.jpg 400w,
image-800w.jpg 800w"
sizes = "(max-width: 600px) 100vw, 50vw"
alt = "Description"
loading = "lazy"
/>
</ picture >
Example: CSS for responsive images
/* Responsive image container */
.image-container {
width : 100 % ;
aspect-ratio : 16 / 9 ; /* Prevent layout shift */
overflow : hidden ;
background : #f0f0f0 ; /* Placeholder */
}
.image-container img {
width : 100 % ;
height : 100 % ;
object-fit : cover ; /* Fill container, crop if needed */
object-position : center ;
}
/* Art-directed positioning */
.hero-image {
object-position : top center ; /* Keep top of image visible */
}
@media ( max-width : 600 px ) {
.hero-image {
object-position : center center ; /* Center on mobile */
}
}
/* Aspect ratio boxes */
.aspect-16-9 {
aspect-ratio : 16 / 9 ;
}
.aspect-4-3 {
aspect-ratio : 4 / 3 ;
}
.aspect-1-1 {
aspect-ratio : 1 / 1 ;
}
/* Lazy load placeholder */
img [ loading = "lazy" ] {
background : linear-gradient ( 110 deg , #ececec 8 % , #f5f5f5 18 % , #ececec 33 % );
background-size : 200 % 100 % ;
animation : shimmer 1.5 s linear infinite ;
}
@keyframes shimmer {
to {
background-position : -200 % 0 ;
}
}
/* High priority hero image */
.hero img {
/* fetchpriority="high" in HTML */
content-visibility : visible ;
}
/* Lazy images below fold */
.content img {
/* loading="lazy" in HTML */
content-visibility : auto ;
}
/* Responsive background images */
.bg-image {
background-size : cover ;
background-position : center ;
}
@media ( max-width : 600 px ) {
.bg-image {
background-image : url ( 'mobile.jpg' );
}
}
@media ( min-width : 601 px ) and ( max-width : 1200 px ) {
.bg-image {
background-image : url ( 'tablet.jpg' );
}
}
@media ( min-width : 1201 px ) {
.bg-image {
background-image : url ( 'desktop.jpg' );
}
}
/* High-resolution background */
@media ( resolution >= 2 dppx ) {
.bg-image {
background-image : url ( 'desktop@2x.jpg' );
}
}
Note: Use srcset for resolution switching, <picture> for art
direction. Always include alt text. Set aspect-ratio to prevent CLS. Use
loading="lazy" for images below fold. Serve modern formats (AVIF, WebP) with fallbacks.
6. Mobile-first vs Desktop-first Strategies
Strategy
Approach
Pros
Cons
Mobile-first
Base styles for mobile, use min-width to enhance for larger screens
Progressive enhancement, better performance on mobile, simpler CSS
May require more rework for desktop-heavy sites
Desktop-first
Base styles for desktop, use max-width to adapt for smaller screens
Easier for existing desktop sites, familiar workflow
Mobile devices load unnecessary desktop CSS, harder to simplify
Hybrid
Container queries + viewport queries
Component adapts to container, layout adapts to viewport
More complex, newer browser support
Example: Mobile-first approach (recommended)
/* Base styles: Mobile (320px+) */
.container {
width : 100 % ;
padding : 1 rem ;
}
.nav {
display : flex ;
flex-direction : column ;
gap : 0.5 rem ;
}
.nav-link {
padding : 0.75 rem ;
font-size : 1 rem ;
}
.grid {
display : grid ;
grid-template-columns : 1 fr ;
gap : 1 rem ;
}
.hero {
padding : 2 rem 1 rem ;
}
.hero h1 {
font-size : 1.75 rem ;
}
/* Tablet: 768px+ */
@media ( min-width : 768 px ) {
.container {
padding : 2 rem ;
max-width : 720 px ;
margin : 0 auto ;
}
.nav {
flex-direction : row ;
justify-content : space-between ;
}
.grid {
grid-template-columns : repeat ( 2 , 1 fr );
gap : 2 rem ;
}
.hero {
padding : 4 rem 2 rem ;
}
.hero h1 {
font-size : 2.5 rem ;
}
}
/* Desktop: 1024px+ */
@media ( min-width : 1024 px ) {
.container {
max-width : 960 px ;
}
.grid {
grid-template-columns : repeat ( 3 , 1 fr );
gap : 3 rem ;
}
.hero {
padding : 6 rem 3 rem ;
}
.hero h1 {
font-size : 3.5 rem ;
}
}
/* Large Desktop: 1280px+ */
@media ( min-width : 1280 px ) {
.container {
max-width : 1200 px ;
}
.grid {
grid-template-columns : repeat ( 4 , 1 fr );
}
}
Example: Desktop-first approach
/* Base styles: Desktop */
.container {
max-width : 1200 px ;
margin : 0 auto ;
padding : 3 rem ;
}
.nav {
display : flex ;
justify-content : space-between ;
gap : 2 rem ;
}
.grid {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr );
gap : 3 rem ;
}
.hero h1 {
font-size : 3.5 rem ;
}
/* Tablet: Below 1024px */
@media ( max-width : 1023 px ) {
.container {
max-width : 960 px ;
padding : 2 rem ;
}
.grid {
grid-template-columns : repeat ( 3 , 1 fr );
gap : 2 rem ;
}
.hero h1 {
font-size : 2.5 rem ;
}
}
/* Mobile: Below 768px */
@media ( max-width : 767 px ) {
.container {
padding : 1 rem ;
}
.nav {
flex-direction : column ;
gap : 0.5 rem ;
}
.grid {
grid-template-columns : 1 fr ;
gap : 1 rem ;
}
.hero h1 {
font-size : 1.75 rem ;
}
}
/* Small mobile: Below 480px */
@media ( max-width : 479 px ) {
.container {
padding : 0.5 rem ;
}
.hero h1 {
font-size : 1.5 rem ;
}
}
Example: Hybrid approach with container queries
/* Global layout: Viewport-based (mobile-first) */
.page-container {
padding : 1 rem ;
}
@media ( min-width : 768 px ) {
.page-container {
padding : 2 rem ;
}
}
@media ( min-width : 1024 px ) {
.page-container {
display : grid ;
grid-template-columns : 250 px 1 fr 300 px ;
gap : 2 rem ;
max-width : 1400 px ;
margin : 0 auto ;
}
}
/* Components: Container-based (intrinsic responsive) */
.card-grid {
container-type : inline-size;
display : grid ;
grid-template-columns : repeat ( auto-fit , minmax ( min ( 300 px , 100 % ), 1 fr ));
gap : 1 rem ;
}
.card {
/* Adapts to container, not viewport */
}
@container (min-width: 400px) {
.card {
display : grid ;
grid-template-columns : 120 px 1 fr ;
}
}
@container (min-width: 600px) {
.card {
grid-template-columns : 180 px 1 fr ;
}
}
/* Typography: Fluid (no breakpoints needed) */
h1 {
font-size : clamp ( 1.75 rem , 4 vw , 3.5 rem );
}
p {
font-size : clamp ( 1 rem , 0.9 rem + 0.5 vw , 1.125 rem );
}
/* Spacing: Fluid */
.section {
padding : clamp ( 2 rem , 5 vw , 6 rem ) clamp ( 1 rem , 3 vw , 3 rem );
}
/* Best of all approaches */
.hybrid-component {
/* Mobile-first base */
padding : 1 rem ;
/* Fluid scaling */
gap : clamp ( 0.5 rem , 2 vw , 2 rem );
/* Container query for component */
container-type : inline-size;
}
@container (min-width: 500px) {
.hybrid-component {
display : grid ;
grid-template-columns : 1 fr 1 fr ;
}
}
/* Viewport query for global layout */
@media ( min-width : 1024 px ) {
.hybrid-component {
padding : 2 rem ;
}
}
Example: Common responsive breakpoints
/* Standard breakpoint system */
/* Extra small devices (phones) */
/* Default styles, no media query needed */
/* Small devices (large phones, 600px+) */
@media ( min-width : 600 px ) {
/* ... */
}
/* Medium devices (tablets, 768px+) */
@media ( min-width : 768 px ) {
/* ... */
}
/* Large devices (desktops, 1024px+) */
@media ( min-width : 1024 px ) {
/* ... */
}
/* Extra large devices (large desktops, 1280px+) */
@media ( min-width : 1280 px ) {
/* ... */
}
/* 2K screens (1440px+) */
@media ( min-width : 1440 px ) {
/* ... */
}
/* 4K screens (2560px+) */
@media ( min-width : 2560 px ) {
/* ... */
}
/* Tailwind-style breakpoints */
/* sm: 640px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px */
/* Bootstrap-style breakpoints */
/* xs: <576px, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px */
/* Material Design breakpoints */
/* xs: 0-599px, sm: 600-1023px, md: 1024-1439px, lg: 1440-1919px, xl: 1920px+ */
/* Between breakpoints (range queries) */
@media ( min-width : 768 px ) and ( max-width : 1023 px ) {
/* Tablet only */
}
/* Level 4 syntax (cleaner) */
@media ( 768 px <= width < 1024 px ) {
/* Tablet only */
}
/* Orientation-specific */
@media ( min-width : 768 px ) and ( orientation : portrait ) {
/* Tablet portrait */
}
@media ( min-width : 768 px ) and ( orientation : landscape ) {
/* Tablet landscape */
}
Responsive Design Best Practices
Mobile-first is recommended: progressive enhancement, better performance
Use min-width for mobile-first, max-width for desktop-first
Combine viewport queries (layout) + container queries (components)
Use clamp() for fluid typography and spacing (reduces breakpoints)
Standard breakpoints: 640px, 768px, 1024px, 1280px, 1536px
Test on real devices, not just browser DevTools
Use srcset and <picture> for responsive images
Respect prefers-reduced-motion and accessibility preferences
Touch devices: (hover: none) and (pointer: coarse)
Use 100dvh instead of 100vh for mobile full-height