Understanding Media Queries
Media queries are the technical backbone of responsive design. They allow us to apply different CSS styles based on characteristics of the device, such as width, height, or orientation.
Think of media queries as conditional statements for your CSS. They essentially say, "If the user's device matches these conditions, then apply these styles."
Media Query Syntax
Basic Structure
A media query consists of:
- The
@mediarule - A media type (optional)
- One or more expressions that check for specific conditions
- A block of CSS to apply when conditions are met
Example Syntax
@media media-type and (media-feature-rule) {
/* CSS rules to apply when conditions are true */
}
Common Media Types
all- For all media types (default if not specified)screen- For computer screens, tablets, smartphonesprint- For printers and print previews
Common Media Features
width,min-width,max-width- Viewport widthheight,min-height,max-height- Viewport heightorientation- Portrait or landscapeaspect-ratio- Width-to-height ratioresolution- Pixel density (e.g., for high-DPI displays)hover- Whether the device supports hover interactionspointer- Type of pointing device (coarse like touch or fine like mouse)
Real-World Media Query Examples
Width-Based Media Query
/* Apply these styles when viewport width is 768px or less */
@media (max-width: 768px) {
.container {
width: 100%;
padding: 0 20px;
}
.sidebar {
display: none;
}
}
This is like a clothing store that reorganizes its racks when space gets limited, removing less essential displays to focus on core inventory.
Combined Conditions
/* Apply when viewport is 768px or less AND in landscape orientation */
@media (max-width: 768px) and (orientation: landscape) {
.hero-image {
height: 80vh;
}
.nav-menu {
flex-direction: row;
}
}
This resembles how a restaurant might rearrange tables differently depending on both how busy they are and whether customers are requesting indoor or outdoor seating.
Feature Detection
/* Apply different styles based on pointer precision */
@media (pointer: fine) {
/* Styles for devices with precise pointer (mouse) */
.button {
padding: 5px 10px;
}
}
@media (pointer: coarse) {
/* Styles for devices with less precise pointer (touch) */
.button {
padding: 12px 20px; /* Larger touch target */
}
}
This is like how a museum might provide different types of informational labels—detailed small print for close-up viewing versus larger, simpler signs for viewing from a distance.
Print Media Query
/* Apply these styles when printing the page */
@media print {
nav, footer, .comments-section {
display: none; /* Hide non-essential elements */
}
body {
font-size: 12pt;
color: black;
}
a[href]:after {
content: " (" attr(href) ")"; /* Show URLs after links */
}
}
This is similar to how you might prepare a document differently depending on whether it's for digital presentation or printed handouts—removing interactive elements and ensuring text is readable in black and white.
Understanding Breakpoints
Breakpoints are the viewport widths at which we apply different styles using media queries. They represent the points where our design "breaks" and needs to adapt.
The Evolution of Breakpoints
Device-Based Breakpoints (Old Approach)
Initially, designers set breakpoints based on common device dimensions:
- 320px - 480px: Mobile phones
- 768px - 1024px: Tablets
- 1024px+: Desktops
This approach is like tailoring clothes for "small," "medium," and "large" sizes without accounting for the infinite variety of actual human body shapes.
Content-Based Breakpoints (Modern Approach)
The better approach is to set breakpoints based on where your content and layout naturally need to adapt:
- Start with a base design (usually mobile)
- Gradually resize the browser window
- Identify points where the layout starts to look stretched, cramped, or unbalanced
- Place breakpoints at these natural transition points
This content-based approach is like a flowing river that naturally finds the best path around obstacles, rather than trying to force it into predefined channels.
Common Breakpoint Approaches
Major Breakpoints (Simplified)
For simpler projects, you might use just a few primary breakpoints:
/* Small devices (phones) */
@media (max-width: 767px) { ... }
/* Medium devices (tablets) */
@media (min-width: 768px) and (max-width: 991px) { ... }
/* Large devices (desktops) */
@media (min-width: 992px) { ... }
Bootstrap-Inspired Breakpoints
Bootstrap 5 uses these breakpoints, which work well for many projects:
- Extra small: <576px (default, no media query needed)
- Small: ≥576px
@media (min-width: 576px) { ... } - Medium: ≥768px
@media (min-width: 768px) { ... } - Large: ≥992px
@media (min-width: 992px) { ... } - Extra large: ≥1200px
@media (min-width: 1200px) { ... } - XXL: ≥1400px
@media (min-width: 1400px) { ... }
Custom, Content-Driven Breakpoints
For a more tailored approach, your breakpoints might be specific to your design:
/* When our sidebar starts to feel cramped */
@media (max-width: 1100px) { ... }
/* When our two-column layout gets too narrow */
@media (max-width: 850px) { ... }
/* When our navigation needs to switch to mobile menu */
@media (max-width: 720px) { ... }
/* When our typography needs size adjustments */
@media (max-width: 480px) { ... }
Implementing Media Queries
In your CSS file
The most common approach is to include media queries directly in your main CSS file:
/* Base styles for all devices */
.container {
width: 100%;
margin: 0 auto;
}
/* Styles for tablets and up */
@media (min-width: 768px) {
.container {
width: 750px;
}
}
/* Styles for desktops and up */
@media (min-width: 992px) {
.container {
width: 970px;
}
}
In the HTML <head>
You can also use the media attribute to conditionally load different stylesheets:
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="tablet.css" media="(min-width: 768px)">
<link rel="stylesheet" href="desktop.css" media="(min-width: 992px)">
This approach can improve performance by allowing browsers to avoid downloading stylesheets that aren't needed. It's like having different instruction manuals for different models of the same product—users only get what's relevant to their device.
Using the viewport meta tag
For proper responsive behavior on mobile devices, always include the viewport meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
This tells mobile browsers to set the viewport width to the device width and scale the page to 1.0 (no automatic zooming). Without this tag, mobile devices might render the page at a desktop viewport width and then scale it down, defeating the purpose of your responsive design.
This is like telling a map to show your current location at the right scale, rather than showing the entire country and making you zoom in manually.
Common Media Query Patterns
The "Mobile First" Pattern
Write base styles for mobile devices, then use min-width queries to enhance for larger screens:
/* Base styles for mobile */
.navigation {
display: flex;
flex-direction: column;
}
/* Enhance for larger screens */
@media (min-width: 768px) {
.navigation {
flex-direction: row;
}
}
The "Desktop First" Pattern
Write base styles for desktop, then use max-width queries to adapt for smaller screens:
/* Base styles for desktop */
.navigation {
display: flex;
flex-direction: row;
}
/* Adapt for smaller screens */
@media (max-width: 767px) {
.navigation {
flex-direction: column;
}
}
The "Element Query" Pattern (Conceptual)
Sometimes, you want components to respond to their container size rather than the viewport size. While CSS doesn't natively support this yet, there are JavaScript solutions or CSS techniques like container queries (recently added to CSS).
This is like having furniture that automatically reconfigures based on the room it's in, rather than the size of the entire house.
Common Responsive Design Patterns
Layout Patterns
Multi-column to Single-column
.container {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.container {
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: 992px) {
.container {
grid-template-columns: 1fr 1fr 1fr;
}
}
Hiding/Showing Elements
/* Hidden by default on mobile */
.sidebar {
display: none;
}
/* Show on larger screens */
@media (min-width: 992px) {
.sidebar {
display: block;
width: 25%;
}
.main-content {
width: 75%;
}
}
Reordering Content
.container {
display: flex;
flex-direction: column;
}
.main-content {
order: 1;
}
.sidebar {
order: 2;
}
@media (min-width: 992px) {
.container {
flex-direction: row;
}
.sidebar {
order: 1;
width: 25%;
}
.main-content {
order: 2;
width: 75%;
}
}
Navigation Patterns
Hamburger Menu
/* Mobile: Hamburger icon */
.nav-toggle {
display: block;
}
.nav-menu {
display: none;
}
.nav-toggle.active + .nav-menu {
display: block;
}
/* Desktop: Horizontal menu */
@media (min-width: 768px) {
.nav-toggle {
display: none;
}
.nav-menu {
display: flex;
}
}
Priority+ Navigation
Show the most important navigation items, with the rest in a "more" dropdown. This adapts based on available space.
Typography Patterns
/* Base font size */
html {
font-size: 16px;
}
h1 {
font-size: 1.8rem; /* 28.8px */
}
/* Larger font sizes on bigger screens */
@media (min-width: 768px) {
html {
font-size: 17px;
}
h1 {
font-size: 2.2rem; /* 37.4px */
}
}
@media (min-width: 1200px) {
html {
font-size: 18px;
}
h1 {
font-size: 2.5rem; /* 45px */
}
}
Media Query Best Practices
Use Relative Units
Combine media queries with relative units (ems, rems, percentages) for truly fluid designs. This allows elements to scale proportionally within each breakpoint range.
Focus on Ranges, Not Exact Device Sizes
Design for ranges of screen sizes rather than targeting specific devices. This makes your design more future-proof.
Limit the Number of Breakpoints
Too many breakpoints can make your CSS complex and hard to maintain. Use only as many as your content needs.
Test Across Devices
Always test your responsive designs on actual devices when possible, not just browser resizing or device emulators.
Use Modern Layout Methods
Flexbox and Grid provide intrinsic responsiveness that can reduce the need for media queries. Sometimes, a well-designed flexible layout needs fewer breakpoints.
Debugging Media Queries
Browser Developer Tools
Modern browsers have built-in tools for testing responsive designs:
- Device emulation modes that simulate different screen sizes
- Media query inspectors that show active breakpoints
- Responsive design mode that lets you see multiple viewports simultaneously
Visual Indicators
During development, you can add visual indicators to see which breakpoint is active:
body:before {
content: "Mobile View";
position: fixed;
top: 0;
right: 0;
background: red;
color: white;
padding: 5px;
z-index: 1000;
}
@media (min-width: 768px) {
body:before {
content: "Tablet View";
background: blue;
}
}
@media (min-width: 992px) {
body:before {
content: "Desktop View";
background: green;
}
}
Remember to remove this code before production!
Emerging Trends and Technologies
Container Queries
Container queries allow components to respond to their parent container's size rather than the viewport size. This is a game-changer for truly modular responsive components.
/* Example of container queries (now supported in many browsers) */
.container {
container-type: inline-size;
}
@container (min-width: 400px) {
.component {
display: flex;
}
}
Feature Queries with @supports
Use feature queries to provide enhanced experiences for browsers that support newer CSS features:
/* Base styles for all browsers */
.layout {
display: block;
}
/* Enhanced layout for browsers that support Grid */
@supports (display: grid) {
.layout {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
}
Responsive Design Mode Preferences
Media queries can now respond to user preferences:
/* Adapt to preferred color scheme */
@media (prefers-color-scheme: dark) {
body {
background-color: #121212;
color: #f0f0f0;
}
}
/* Respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
Practice Activity: Building Responsive Layouts with Media Queries
Activity Instructions:
-
Create a simple HTML page with the following elements:
- A header with a logo and navigation menu
- A main content area with three columns of content
- A sidebar with additional information
- A footer with contact information
-
Implement CSS with media queries to create a responsive layout:
- Desktop (992px and above): Show all elements in a multi-column layout
- Tablet (768px to 991px): Adjust to a two-column layout with the sidebar below the main content
- Mobile (below 768px): Convert to a single-column layout with hamburger navigation
- Add at least one additional media query feature beyond width (e.g., print styles, orientation changes, etc.)
Starter Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Layout</title>
<style>
/* Your CSS here */
</style>
</head>
<body>
<header>
<div class="logo">Site Logo</div>
<button class="nav-toggle">☰</button>
<nav class="main-nav">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</header>
<div class="container">
<main class="content">
<article class="column">
<h2>First Column</h2>
<p>Lorem ipsum dolor sit amet...</p>
</article>
<article class="column">
<h2>Second Column</h2>
<p>Lorem ipsum dolor sit amet...</p>
</article>
<article class="column">
<h2>Third Column</h2>
<p>Lorem ipsum dolor sit amet...</p>
</article>
</main>
<aside class="sidebar">
<h2>Sidebar</h2>
<p>Additional information here...</p>
</aside>
</div>
<footer>
<p>Contact: info@example.com | © 2025</p>
</footer>
</body>
</html>
Bonus Challenge:
Implement a navigation that shows the most important items on smaller screens, with additional items appearing as the screen size increases.
Conclusion
Media queries and breakpoints are essential tools for creating responsive web designs that adapt to different devices and contexts. By understanding how to use these tools effectively, you can create experiences that work well for all users, regardless of their device.
In our next lesson, we'll explore the mobile-first design approach, which builds on these concepts by starting with the mobile experience and progressively enhancing for larger devices.