Responsive Design
Media queries, mobile-first, and fluid layouts
What is Responsive Design?
Responsive design is an approach that ensures your website looks great and functions well on any device—from phones to tablets to large desktop monitors. Instead of creating separate mobile and desktop versions, you build one flexible layout that adapts to different screen sizes.
The three pillars of responsive design are: fluid grids (flexible layouts), flexible images (that scale appropriately), and media queries (CSS that applies different styles at different screen sizes).
The Viewport Meta Tag
This essential HTML tag tells mobile browsers how to scale your page:
❌ Without Viewport Tag
Mobile browsers assume desktop width (980px), page appears tiny and zoomed out
✓ With Viewport Tag
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
Page uses actual device width, perfect starting zoom
Media Queries
Media queries apply styles based on screen characteristics like width, height, or orientation:
Basic Media Query Syntax
/* Apply these styles when screen is at least 768px wide */
@media (min-width: 768px) {
.container {
max-width: 720px;
padding: 32px;
}
}
/* Max-width (less common with mobile-first) */
@media (max-width: 767px) {
.sidebar {
display: none;
}
}
/* Orientation */
@media (orientation: landscape) {
.hero {
height: 50vh;
}
}
Common Breakpoints
Mobile-First Approach
Start with mobile styles, then enhance for larger screens. This is better for performance and forces you to prioritize content.
❌ Desktop-First (Not Recommended)
/* Desktop styles first */
.nav {
display: flex;
gap: 24px;
}
/* Override for mobile */
@media (max-width: 768px) {
.nav {
display: block;
gap: 0;
}
}
Mobile inherits desktop CSS, then overrides it
✓ Mobile-First (Recommended)
/* Mobile styles first */
.nav {
display: block;
}
/* Enhance for desktop */
@media (min-width: 768px) {
.nav {
display: flex;
gap: 24px;
}
}
Start simple, progressively enhance
Fluid Typography
Make text scale smoothly across screen sizes using modern CSS functions:
Using clamp() - The Modern Way
This heading scales fluidly
Resize your browser to see it adapt
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
/* min: 1.5rem, preferred: 4vw, max: 3rem */
/* Smoothly scales between min and max */
}
p {
font-size: clamp(1rem, 2.5vw, 1.125rem);
}
/* Fluid spacing too! */
.section {
padding: clamp(1rem, 5vw, 3rem);
}
Media Query Approach (Traditional)
/* Mobile */
h1 { font-size: 24px; }
/* Tablet */
@media (min-width: 768px) {
h1 { font-size: 32px; }
}
/* Desktop */
@media (min-width: 1024px) {
h1 { font-size: 40px; }
}
Responsive Images
Images need special attention to look good and load efficiently on all devices:
Basic Responsive Image
img {
max-width: 100%; /* Never exceed container */
height: auto; /* Maintain aspect ratio */
display: block; /* Remove bottom space */
}
Object-fit for Cropping
object-fit: cover
object-fit: contain
object-fit: fill
.hero-image {
width: 100%;
height: 400px;
object-fit: cover; /* Crop to fill */
object-position: center; /* Focus point */
}
Responsive Images with srcset
<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="Description"
/>
/* Browser picks best image based on screen size */
Responsive Layout Patterns
Stack to Row
Mobile (stacked):
Desktop (row):
.container {
display: flex;
flex-direction: column;
gap: 16px;
}
@media (min-width: 768px) {
.container {
flex-direction: row;
}
}
Responsive Grid (No Media Queries!)
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
/* Automatically adjusts columns based on available space! */
Hide/Show Elements
/* Hide on mobile, show on desktop */
.desktop-only {
display: none;
}
@media (min-width: 1024px) {
.desktop-only {
display: block;
}
}
/* Show on mobile, hide on desktop */
.mobile-only {
display: block;
}
@media (min-width: 1024px) {
.mobile-only {
display: none;
}
}
Container Queries (Modern CSS)
The future of responsive design—style elements based on their container size, not the viewport:
.card-container {
container-type: inline-size;
container-name: card;
}
/* Style based on container width, not viewport */
@container card (min-width: 400px) {
.card {
display: flex;
gap: 20px;
}
}
@container card (min-width: 600px) {
.card {
font-size: 1.125rem;
}
}
⚡ Supported in all modern browsers (2023+)
⚠️ Common Responsive Pitfalls
- Fixed widths: Avoid
width: 600px. Usemax-width: 600pxor percentages - px for everything: Use relative units (rem, em, %, vw) for better scaling
- Ignoring touch targets: Buttons should be at least 44×44px for mobile
- Horizontal scrolling: Ensure content never forces horizontal scroll on mobile
- Not testing on real devices: Simulators don't catch everything
Learn More
✓ Responsive Design Checklist
- ✓ Include viewport meta tag
- ✓ Use mobile-first approach with min-width media queries
- ✓ Make all images responsive (
max-width: 100%) - ✓ Use relative units (rem, em, %) instead of px
- ✓ Test on actual mobile devices, not just browser resize
- ✓ Ensure touch targets are large enough (44×44px minimum)
- ✓ Consider using CSS Grid with auto-fit for responsive layouts
- ✓ Optimize images for different screen sizes (use srcset)