Responsive Design Skill
When to Use This Skill
Use this skill when you need to:
- Design and implement mobile-first responsive layouts
- Create fluid, adaptive interfaces that work across all device sizes
- Implement modern CSS layout techniques (Flexbox, Grid)
- Optimize images and media for different screen sizes
- Build accessible, touch-friendly interfaces
- Implement responsive typography and spacing systems
- Create container-based responsive components
- Optimize performance for mobile devices
- Ensure consistent user experience across devices
- Implement responsive navigation patterns
- Design responsive forms and data tables
- Create adaptive card layouts and galleries
- Build responsive dashboards and admin interfaces
Core Concepts
Mobile-First Philosophy
Mobile-first design means starting with mobile layout and progressively enhancing for larger screens.
Why Mobile-First?
- Forces focus on essential content and features
- Easier to scale up than scale down
- Better performance on mobile devices
- Aligns with modern usage patterns (mobile-first world)
- Simpler CSS with fewer overrides
Mobile-First Approach:
css
/* Base styles for mobile (320px+) */
.container {
padding: 1rem;
width: 100%;
}
/* Tablet (768px+) */
@media (min-width: 768px) {
.container {
padding: 2rem;
max-width: 720px;
margin: 0 auto;
}
}
/* Desktop (1024px+) */
@media (min-width: 1024px) {
.container {
max-width: 960px;
padding: 3rem;
}
}
/* Large Desktop (1280px+) */
@media (min-width: 1280px) {
.container {
max-width: 1200px;
}
}
Breakpoint Strategy
Standard breakpoints based on common device sizes:
css
/* Extra Small (Mobile) - Default */
/* No media query needed */
/* Small (Large Mobile) */
@media (min-width: 480px) { }
/* Medium (Tablet) */
@media (min-width: 768px) { }
/* Large (Desktop) */
@media (min-width: 1024px) { }
/* Extra Large (Wide Desktop) */
@media (min-width: 1280px) { }
/* XXL (Ultra-wide) */
@media (min-width: 1536px) { }
Custom Breakpoints:
css
/* Use custom breakpoints based on content, not devices */
/* When text becomes too long to read comfortably */
@media (min-width: 40em) { /* 640px */ }
/* When sidebar can fit alongside content */
@media (min-width: 60em) { /* 960px */ }
/* When multi-column layout makes sense */
@media (min-width: 75em) { /* 1200px */ }
Fluid Layouts
Create layouts that adapt smoothly to any screen size:
css
/* Fluid container with constraints */
.container {
width: 100%;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
padding-left: clamp(1rem, 5vw, 3rem);
padding-right: clamp(1rem, 5vw, 3rem);
}
/* Fluid grid */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: clamp(1rem, 3vw, 2rem);
}
/* Fluid typography */
.heading {
font-size: clamp(1.5rem, 4vw + 1rem, 3rem);
line-height: 1.2;
}
CSS Techniques
Flexbox for Responsive Layouts
Flexbox excels at one-dimensional layouts (row or column):
css
/* Responsive navigation */
.nav {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: space-between;
align-items: center;
}
.nav-links {
display: flex;
flex-wrap: wrap;
gap: 1rem;
list-style: none;
}
@media (max-width: 767px) {
.nav {
flex-direction: column;
align-items: stretch;
}
.nav-links {
flex-direction: column;
}
}
/* Flexible card layout */
.card-container {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card {
flex: 1 1 300px; /* grow, shrink, base width */
min-width: 0; /* Allow flex items to shrink below content size */
}
/* Responsive sidebar layout */
.layout {
display: flex;
flex-wrap: wrap;
gap: 2rem;
}
.sidebar {
flex: 1 1 250px;
}
.main-content {
flex: 3 1 500px;
}
CSS Grid for Complex Layouts
Grid is perfect for two-dimensional layouts:
css
/* Auto-responsive grid */
.grid-auto {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
/* Named grid areas for semantic layouts */
.page-layout {
display: grid;
grid-template-areas:
"header"
"nav"
"main"
"aside"
"footer";
gap: 1rem;
}
@media (min-width: 768px) {
.page-layout {
grid-template-areas:
"header header"
"nav nav"
"main aside"
"footer footer";
grid-template-columns: 2fr 1fr;
}
}
@media (min-width: 1024px) {
.page-layout {
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 250px;
}
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
/* Responsive grid with precise control */
.gallery {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
}
.gallery-item {
grid-column: span 12; /* Full width on mobile */
}
@media (min-width: 480px) {
.gallery-item {
grid-column: span 6; /* Half width on small screens */
}
}
@media (min-width: 768px) {
.gallery-item {
grid-column: span 4; /* Third width on tablets */
}
}
@media (min-width: 1024px) {
.gallery-item {
grid-column: span 3; /* Quarter width on desktop */
}
}
/* Featured item spans more columns */
.gallery-item.featured {
grid-column: span 12;
}
@media (min-width: 768px) {
.gallery-item.featured {
grid-column: span 8;
}
}
Media Queries Advanced Techniques
css
/* Orientation-based queries */
@media (orientation: portrait) {
.image-hero {
aspect-ratio: 3/4;
}
}
@media (orientation: landscape) {
.image-hero {
aspect-ratio: 16/9;
}
}
/* Hover capability detection */
@media (hover: hover) and (pointer: fine) {
/* Desktop with mouse */
.button:hover {
transform: scale(1.05);
}
}
@media (hover: none) and (pointer: coarse) {
/* Touch devices */
.button:active {
transform: scale(0.95);
}
}
/* Prefers reduced motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Prefers color scheme */
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #f0f0f0;
}
}
/* Combining media queries */
@media (min-width: 768px) and (max-width: 1023px) {
/* Tablet only styles */
.container {
padding: 2rem;
}
}
/* Print styles */
@media print {
.no-print {
display: none;
}
body {
font-size: 12pt;
color: black;
background: white;
}
}
Container Queries
Modern alternative to viewport-based media queries:
css
/* Define container */
.card-container {
container-type: inline-size;
container-name: card;
}
/* Query based on container size */
.card {
display: flex;
flex-direction: column;
gap: 1rem;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
}
.card-image {
width: 40%;
}
.card-content {
width: 60%;
}
}
@container card (min-width: 600px) {
.card-title {
font-size: 1.5rem;
}
}
/* Multiple containers */
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
.main-content {
container-type: inline-size;
container-name: main;
}
@container sidebar (min-width: 300px) {
.widget {
padding: 1.5rem;
}
}
@container main (min-width: 600px) {
.article {
column-count: 2;
}
}
Responsive Images
Srcset and Sizes
Provide different image sizes for different viewport widths:
html
<!-- Responsive image with srcset -->
<img
src="image-800.jpg"
srcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1200.jpg 1200w,
image-1600.jpg 1600w
"
sizes="
(max-width: 480px) 100vw,
(max-width: 768px) 90vw,
(max-width: 1024px) 700px,
1000px
"
alt="Responsive image"
loading="lazy"
/>
css
/* Ensure images are responsive by default */
img {
max-width: 100%;
height: auto;
display: block;
}
/* Maintain aspect ratio */
.image-container {
position: relative;
aspect-ratio: 16 / 9;
overflow: hidden;
}
.image-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
Picture Element for Art Direction
Different images for different screen sizes:
html
<!-- Art direction with picture -->
<picture>
<!-- Mobile: portrait crop -->
<source
media="(max-width: 767px)"
srcset="
mobile-400.jpg 400w,
mobile-800.jpg 800w
"
sizes="100vw"
/>
<!-- Tablet: square crop -->
<source
media="(max-width: 1023px)"
srcset="
tablet-600.jpg 600w,
tablet-1200.jpg 1200w
"
sizes="90vw"
/>
<!-- Desktop: landscape crop -->
<source
media="(min-width: 1024px)"
srcset="
desktop-800.jpg 800w,
desktop-1600.jpg 1600w,
desktop-2400.jpg 2400w
"
sizes="(max-width: 1280px) 900px, 1200px"
/>
<!-- Fallback -->
<img src="desktop-800.jpg" alt="Art directed image" />
</picture>
<!-- WebP with fallback -->
<picture>
<source type="image/webp" srcset="image.webp" />
<source type="image/jpeg" srcset="image.jpg" />
<img src="image.jpg" alt="Image with format fallback" />
</picture>
Background Images
css
/* Responsive background images */
.hero {
background-image: url('hero-mobile.jpg');
background-size: cover;
background-position: center;
min-height: 300px;
}
@media (min-width: 768px) {
.hero {
background-image: url('hero-tablet.jpg');
min-height: 500px;
}
}
@media (min-width: 1024px) {
.hero {
background-image: url('hero-desktop.jpg');
min-height: 600px;
}
}
/* High-density displays */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.hero {
background-image: url('hero-mobile@2x.jpg');
}
@media (min-width: 768px) {
.hero {
background-image: url('hero-tablet@2x.jpg');
}
}
@media (min-width: 1024px) {
.hero {
background-image: url('hero-desktop@2x.jpg');
}
}
}
Viewport Units
Understanding Viewport Units
css
/* Viewport Width (vw) - 1vw = 1% of viewport width */
.full-width-text {
font-size: 5vw; /* Scales with viewport */
}
/* Viewport Height (vh) - 1vh = 1% of viewport height */
.full-screen-section {
min-height: 100vh;
}
/* Viewport Minimum (vmin) - 1vmin = 1% of smaller dimension */
.responsive-square {
width: 50vmin;
height: 50vmin;
}
/* Viewport Maximum (vmax) - 1vmax = 1% of larger dimension */
.diagonal-element {
width: 70vmax;
}
/* Combining units for fluid sizing */
.fluid-padding {
padding: clamp(1rem, 5vw, 4rem);
}
.fluid-heading {
font-size: clamp(1.5rem, 3vw + 1rem, 3.5rem);
}
/* Dynamic viewport units (dvh, svh, lvh) */
/* Small Viewport Height - smallest possible viewport */
.mobile-header {
height: 10svh;
}
/* Large Viewport Height - largest possible viewport */
.mobile-footer {
height: 10lvh;
}
/* Dynamic Viewport Height - adjusts to current state */
.modal {
height: 100dvh; /* Better for mobile with hiding address bars */
}
Practical Viewport Applications
css
/* Hero section that adapts to screen */
.hero-section {
min-height: clamp(400px, 80vh, 800px);
padding: clamp(2rem, 5vh, 4rem) clamp(1rem, 5vw, 3rem);
}
/* Responsive spacing system */
:root {
--spacing-xs: clamp(0.25rem, 1vw, 0.5rem);
--spacing-sm: clamp(0.5rem, 2vw, 1rem);
--spacing-md: clamp(1rem, 3vw, 2rem);
--spacing-lg: clamp(2rem, 5vw, 4rem);
--spacing-xl: clamp(3rem, 8vw, 6rem);
}
/* Responsive card grid with viewport-based gaps */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(1rem, 3vw, 2.5rem);
}
Modern CSS Functions
Clamp() for Fluid Sizing