CrackedRuby CrackedRuby

Responsive Design Principles

Overview

Responsive design represents an approach to web development where interfaces automatically adjust their layout, content, and functionality based on the device's screen size, orientation, and capabilities. This methodology addresses the fragmentation of web access across smartphones, tablets, desktops, and other devices by creating a single codebase that serves all platforms.

The concept emerged from the need to replace separate mobile and desktop websites with unified solutions. Traditional approaches maintained distinct codebases: one for m.example.com and another for www.example.com. Responsive design eliminates this duplication through CSS media queries, flexible grid systems, and adaptive images that reconfigure themselves based on viewport dimensions.

Three technical pillars support responsive design: fluid grids that use relative units instead of fixed pixels, flexible images that scale within their containers, and media queries that apply different styles at specific breakpoints. These components work together to create interfaces that function across the spectrum of screen sizes from 320-pixel smartphones to 4K desktop monitors.

/* Fluid grid example */
.container {
  width: 90%;
  max-width: 1200px;
  margin: 0 auto;
}

.column {
  width: 100%;
}

@media (min-width: 768px) {
  .column {
    width: 48%;
    float: left;
    margin: 1%;
  }
}

The viewport meta tag controls how browsers render pages on mobile devices. Without this tag, mobile browsers render pages at desktop widths and scale them down, creating tiny, unreadable text. The viewport tag instructs the browser to match the screen width and prevents unwanted zoom behavior.

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Responsive design differs from adaptive design, which serves distinct layouts at predetermined breakpoints rather than continuously adjusting. Adaptive design detects the device and serves pre-built layouts, while responsive design fluidly transforms as the viewport changes. Both approaches have valid use cases, but responsive design requires less maintenance since it works across any screen size, including devices that don't exist yet.

Key Principles

Fluid Grids

Fluid grids replace fixed-width layouts with proportional sizing using percentages, em, rem, or viewport units. Instead of defining a column as 960 pixels wide, it becomes 80% of the viewport or calculated using CSS Grid's fr units. This proportional approach allows layouts to scale naturally across different screen sizes.

The formula for converting fixed layouts to fluid grids: target / context = result. For a 300-pixel element in a 960-pixel container: 300 / 960 = 0.3125 or 31.25%. This calculation applies to all spatial relationships including margins, padding, and positioning.

/* Fixed layout */
.sidebar {
  width: 300px;
}

.content {
  width: 660px;
}

/* Fluid equivalent */
.sidebar {
  width: 31.25%; /* 300 / 960 */
}

.content {
  width: 68.75%; /* 660 / 960 */
}

Flexible Images and Media

Images pose challenges in responsive layouts because they have intrinsic dimensions. Setting max-width: 100% and height: auto allows images to scale down to fit their container while maintaining aspect ratio. This prevents images from overflowing their containers on small screens.

img, video, iframe {
  max-width: 100%;
  height: auto;
}

The picture element provides more control by serving different images at different breakpoints. This optimizes bandwidth and ensures appropriate image sizes for each device. A 2000-pixel image wastes bandwidth on a 375-pixel phone screen.

<picture>
  <source media="(min-width: 1200px)" srcset="large.jpg">
  <source media="(min-width: 768px)" srcset="medium.jpg">
  <img src="small.jpg" alt="Description">
</picture>

Media Queries

Media queries apply CSS rules conditionally based on device characteristics. The most common query tests viewport width, but queries can also check height, orientation, resolution, and color capabilities. Media queries form the foundation of breakpoint-based responsive design.

/* Base styles for mobile */
.navigation {
  display: block;
}

.nav-item {
  display: block;
  padding: 1rem;
}

/* Tablet and larger */
@media (min-width: 768px) {
  .navigation {
    display: flex;
  }
  
  .nav-item {
    display: inline-block;
    padding: 0 1rem;
  }
}

Breakpoints

Breakpoints define viewport widths where layouts change. Common breakpoints occur at 576px (small phones to large phones), 768px (tablets), 992px (small desktops), and 1200px (large desktops). These values originated from common device sizes but should be determined by content needs rather than specific devices.

Content-based breakpoints prove more maintainable than device-based breakpoints. When text becomes too wide to read comfortably or layouts break, add a breakpoint. This approach remains valid as new devices with different dimensions enter the market.

Mobile-First vs Desktop-First

Mobile-first design writes base styles for small screens and uses min-width media queries to add complexity for larger screens. Desktop-first design writes base styles for large screens and uses max-width queries to simplify for smaller screens. Mobile-first forces progressive enhancement and often results in cleaner code.

/* Mobile-first approach */
.container {
  padding: 1rem;
}

@media (min-width: 768px) {
  .container {
    padding: 2rem;
  }
}

@media (min-width: 1200px) {
  .container {
    padding: 3rem;
  }
}

/* Desktop-first approach */
.container {
  padding: 3rem;
}

@media (max-width: 1199px) {
  .container {
    padding: 2rem;
  }
}

@media (max-width: 767px) {
  .container {
    padding: 1rem;
  }
}

Touch Targets

Interactive elements require larger hit areas on touchscreens than on desktop pointer devices. Buttons and links should measure at least 44×44 pixels to accommodate average finger sizes. Insufficient spacing between touch targets causes mis-taps and user frustration.

Viewport Units

Viewport units (vw, vh, vmin, vmax) size elements relative to the viewport dimensions. 1vw equals 1% of viewport width, 1vh equals 1% of viewport height. These units create truly responsive typography and layouts that scale with the viewport without media queries.

.hero-title {
  font-size: calc(2rem + 2vw);
}

Design Considerations

Mobile-First Strategy

Mobile-first design starts with the smallest screens and progressively enhances for larger viewports. This approach prioritizes essential content and functionality, reducing bloat and improving performance on constrained devices. The philosophy assumes limited screen real estate and bandwidth as the baseline.

Benefits include faster initial page loads since base styles are minimal, forced content prioritization, and graceful degradation when JavaScript fails. Mobile-first development identifies truly essential features since non-critical elements get added only for larger screens.

Drawbacks include more media queries in the final CSS since each breakpoint adds styles rather than overriding them. Desktop-centric teams may find the paradigm shift challenging when accustomed to designing for large screens first.

Desktop-First Strategy

Desktop-first design builds for large screens and simplifies progressively for smaller viewports. This approach suits applications where desktop users form the primary audience or where complex interfaces require significant screen real estate.

Benefits include simpler initial development for desktop-focused products and easier adaptation of existing desktop-only sites. Some design patterns, like multi-column layouts with extensive navigation, translate more naturally from desktop to mobile than vice versa.

Drawbacks include larger initial payloads since mobile devices download desktop styles first, tendency to hide rather than redesign content for mobile, and risk of delivering sub-optimal mobile experiences as an afterthought.

Breakpoint Selection

Breakpoints should reflect content needs rather than specific devices. Resize the browser and add breakpoints where layouts break or become uncomfortable to use. This content-first approach creates more maintainable designs that work on any device.

Common breakpoint ranges:

  • 0-575px: Extra small (phones)
  • 576-767px: Small (large phones)
  • 768-991px: Medium (tablets)
  • 992-1199px: Large (desktops)
  • 1200px+: Extra large (large desktops)

These values serve as guidelines, not requirements. An article-focused site might need fewer breakpoints than a complex dashboard application. Some designs function well with just two breakpoints, while others require five or more.

Content Choreography

Content choreography describes how content reflows at different breakpoints. On mobile, stacked vertical layouts work best. On tablets, two-column layouts become viable. On desktops, multi-column layouts with sidebars appear.

Priority determines which content appears first in the source order. Mobile users should encounter the most important content before scrolling. CSS Grid and Flexbox allow visual reordering without changing HTML structure, but source order still matters for accessibility and SEO.

Performance Trade-offs

Responsive design introduces performance considerations. Serving the same large images to all devices wastes bandwidth on mobile. Loading desktop CSS on mobile increases page weight. These issues require mitigation through responsive images, critical CSS, and lazy loading.

The decision between client-side and server-side responsiveness affects performance. Client-side approaches use media queries and JavaScript, downloading all assets and selectively displaying them. Server-side approaches detect the device and send only relevant code, reducing payload but requiring server logic.

Progressive Enhancement vs Graceful Degradation

Progressive enhancement builds a baseline experience that works everywhere, then adds enhancements for capable devices. Start with semantic HTML that functions without CSS or JavaScript, add responsive styles, then layer interactive features.

Graceful degradation designs for modern browsers first, ensuring the experience degrades acceptably on older devices. This approach risks delivering broken experiences to users with JavaScript disabled or unsupported browsers.

Progressive enhancement aligns better with responsive design philosophy since both prioritize core functionality and progressively add complexity.

Ruby Implementation

Rails Asset Pipeline and Responsive CSS

Rails applications serve responsive CSS through the asset pipeline, which concatenates and minifies stylesheets. Place responsive styles in app/assets/stylesheets/ with organization reflecting the component structure.

# app/assets/stylesheets/application.css
/*
 *= require_tree .
 *= require_self
 */

The viewport meta tag belongs in the application layout:

<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <%= stylesheet_link_tag "application", media: "all" %>
  <%= javascript_include_tag "application" %>
</head>
<body>
  <%= yield %>
</body>
</html>

Device Detection in Rails

The browser gem identifies devices and capabilities, enabling server-side responsive decisions. Install it with gem 'browser' and use it in controllers or helpers.

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_device_type
  
  private
  
  def set_device_type
    @mobile = browser.device.mobile?
    @tablet = browser.device.tablet?
    @desktop = !@mobile && !@tablet
  end
end

# app/helpers/application_helper.rb
module ApplicationHelper
  def responsive_image_tag(image_path, options = {})
    if @mobile
      image_tag("#{image_path}-small.jpg", options)
    elsif @tablet
      image_tag("#{image_path}-medium.jpg", options)
    else
      image_tag("#{image_path}-large.jpg", options)
    end
  end
end

Responsive Images with Active Storage

Active Storage generates image variants at different sizes, delivering appropriate versions based on viewport. Define variants in the model and use them in views.

# app/models/article.rb
class Article < ApplicationRecord
  has_one_attached :hero_image
  
  def hero_image_variants
    {
      small: hero_image.variant(resize_to_limit: [640, 480]),
      medium: hero_image.variant(resize_to_limit: [1024, 768]),
      large: hero_image.variant(resize_to_limit: [1920, 1080])
    }
  end
end

# app/views/articles/show.html.erb
<picture>
  <source media="(min-width: 1200px)" 
          srcset="<%= url_for(@article.hero_image_variants[:large]) %>">
  <source media="(min-width: 768px)" 
          srcset="<%= url_for(@article.hero_image_variants[:medium]) %>">
  <img src="<%= url_for(@article.hero_image_variants[:small]) %>" 
       alt="<%= @article.title %>">
</picture>

Responsive Tables

Tables present challenges on small screens since they require horizontal space. Rails helpers can generate responsive table markup that transforms into a card-based layout on mobile.

# app/helpers/table_helper.rb
module TableHelper
  def responsive_table(&block)
    content_tag(:div, class: 'table-responsive') do
      content_tag(:table, class: 'table', &block)
    end
  end
end

# app/views/products/index.html.erb
<%= responsive_table do %>
  <thead>
    <tr>
      <th>Name</th>
      <th>Price</th>
      <th>Stock</th>
    </tr>
  </thead>
  <tbody>
    <% @products.each do |product| %>
      <tr>
        <td data-label="Name"><%= product.name %></td>
        <td data-label="Price"><%= number_to_currency(product.price) %></td>
        <td data-label="Stock"><%= product.stock %></td>
      </tr>
    <% end %>
  </tbody>
<% end %>

Corresponding CSS transforms the table on mobile:

@media (max-width: 767px) {
  .table-responsive table,
  .table-responsive thead,
  .table-responsive tbody,
  .table-responsive tr,
  .table-responsive td {
    display: block;
  }
  
  .table-responsive thead {
    display: none;
  }
  
  .table-responsive td {
    position: relative;
    padding-left: 40%;
  }
  
  .table-responsive td:before {
    content: attr(data-label);
    position: absolute;
    left: 0;
    width: 35%;
    padding-right: 10px;
    font-weight: bold;
  }
}

Viewport-Aware Navigation

Rails applications often require different navigation patterns for mobile and desktop. A helper method can generate appropriate markup.

# app/helpers/navigation_helper.rb
module NavigationHelper
  def responsive_navigation(items)
    content_tag(:nav, class: 'responsive-nav') do
      concat(mobile_nav_toggle)
      concat(nav_items(items))
    end
  end
  
  private
  
  def mobile_nav_toggle
    content_tag(:button, class: 'nav-toggle', 'aria-label': 'Toggle navigation') do
      content_tag(:span, class: 'hamburger') do
        3.times.map { content_tag(:span) }.join.html_safe
      end
    end
  end
  
  def nav_items(items)
    content_tag(:ul, class: 'nav-items') do
      items.map do |item|
        content_tag(:li, class: 'nav-item') do
          link_to item[:text], item[:path], class: 'nav-link'
        end
      end.join.html_safe
    end
  end
end

Form Optimization

Mobile forms benefit from appropriate input types and attributes that trigger device-specific keyboards.

<%= form_with model: @user, local: true do |f| %>
  <div class="form-group">
    <%= f.label :email %>
    <%= f.email_field :email, 
                      autocomplete: 'email',
                      class: 'form-control' %>
  </div>
  
  <div class="form-group">
    <%= f.label :phone %>
    <%= f.telephone_field :phone,
                          autocomplete: 'tel',
                          class: 'form-control' %>
  </div>
  
  <div class="form-group">
    <%= f.label :website %>
    <%= f.url_field :website,
                    autocomplete: 'url',
                    class: 'form-control' %>
  </div>
  
  <%= f.submit 'Save', class: 'btn btn-primary btn-block-mobile' %>
<% end %>

Practical Examples

Responsive Navigation Menu

A navigation menu that displays horizontally on desktop and converts to a hamburger menu on mobile demonstrates core responsive principles.

<nav class="main-nav">
  <div class="nav-container">
    <a href="/" class="logo">Logo</a>
    <button class="nav-toggle" aria-label="Toggle navigation">
      <span></span>
      <span></span>
      <span></span>
    </button>
    <ul class="nav-menu">
      <li><a href="/products">Products</a></li>
      <li><a href="/services">Services</a></li>
      <li><a href="/about">About</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
  </div>
</nav>
.nav-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
}

.nav-toggle {
  display: none;
  flex-direction: column;
  width: 30px;
  height: 24px;
  background: transparent;
  border: none;
  cursor: pointer;
}

.nav-toggle span {
  width: 100%;
  height: 3px;
  background: #333;
  margin: 3px 0;
  transition: 0.3s;
}

.nav-menu {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 2rem;
}

@media (max-width: 768px) {
  .nav-toggle {
    display: flex;
  }
  
  .nav-menu {
    display: none;
    flex-direction: column;
    position: absolute;
    top: 60px;
    left: 0;
    width: 100%;
    background: white;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    padding: 1rem 0;
  }
  
  .nav-menu.active {
    display: flex;
  }
  
  .nav-menu li {
    padding: 0.5rem 1rem;
  }
}

JavaScript toggles the menu visibility:

document.querySelector('.nav-toggle').addEventListener('click', function() {
  document.querySelector('.nav-menu').classList.toggle('active');
});

Responsive Grid Layout

A product grid demonstrates fluid layouts that adjust column count based on viewport width.

<div class="product-grid">
  <div class="product-card">
    <img src="product1.jpg" alt="Product 1">
    <h3>Product Name</h3>
    <p class="price">$99.99</p>
    <button class="btn">Add to Cart</button>
  </div>
  <!-- More product cards -->
</div>
.product-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  padding: 1rem;
}

@media (min-width: 576px) {
  .product-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 992px) {
  .product-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 1200px) {
  .product-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.product-card {
  background: white;
  border-radius: 8px;
  padding: 1rem;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.product-card img {
  width: 100%;
  height: auto;
  border-radius: 4px;
}

.btn {
  width: 100%;
  padding: 0.75rem;
  margin-top: 1rem;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

Responsive Typography

Typography scales with viewport size using a combination of relative units and viewport units.

html {
  font-size: 16px;
}

body {
  font-size: 1rem;
  line-height: 1.6;
}

h1 {
  font-size: calc(1.5rem + 1.5vw);
  line-height: 1.2;
  margin-bottom: 1rem;
}

h2 {
  font-size: calc(1.25rem + 1vw);
  line-height: 1.3;
  margin-bottom: 0.875rem;
}

p {
  font-size: 1rem;
  margin-bottom: 1rem;
  max-width: 65ch;
}

@media (min-width: 768px) {
  html {
    font-size: 18px;
  }
}

@media (min-width: 1200px) {
  html {
    font-size: 20px;
  }
}

Responsive Hero Section

Hero sections require different layouts and image treatments across devices.

<section class="hero">
  <picture class="hero-image">
    <source media="(min-width: 1200px)" srcset="hero-large.jpg">
    <source media="(min-width: 768px)" srcset="hero-medium.jpg">
    <img src="hero-small.jpg" alt="Hero image">
  </picture>
  <div class="hero-content">
    <h1>Welcome to Our Site</h1>
    <p>Discover amazing products and services</p>
    <a href="/products" class="btn-primary">Shop Now</a>
  </div>
</section>
.hero {
  position: relative;
  min-height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero-image img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
}

.hero-content {
  text-align: center;
  color: white;
  padding: 2rem;
  background: rgba(0,0,0,0.5);
  border-radius: 8px;
}

.hero-content h1 {
  font-size: 2rem;
  margin-bottom: 1rem;
}

.hero-content p {
  font-size: 1.125rem;
  margin-bottom: 1.5rem;
}

@media (min-width: 768px) {
  .hero {
    min-height: 600px;
  }
  
  .hero-content h1 {
    font-size: 3rem;
  }
  
  .hero-content p {
    font-size: 1.5rem;
  }
}

Common Patterns

Container Query Pattern

Container queries allow components to respond to their container's size rather than the viewport. This enables truly modular components that adapt regardless of where they appear in the layout.

.card-container {
  container-type: inline-size;
  container-name: card;
}

.card {
  padding: 1rem;
}

@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 1rem;
  }
}

Mobile-First Media Query Pattern

Mobile-first patterns establish mobile styles as the baseline and progressively enhance for larger screens.

/* Mobile base styles */
.sidebar {
  width: 100%;
  padding: 1rem;
}

/* Tablet enhancement */
@media (min-width: 768px) {
  .sidebar {
    width: 33.33%;
    padding: 1.5rem;
  }
}

/* Desktop enhancement */
@media (min-width: 1200px) {
  .sidebar {
    width: 25%;
    padding: 2rem;
  }
}

Flexbox Responsive Pattern

Flexbox creates responsive layouts that wrap naturally without explicit breakpoints.

.flex-container {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.flex-item {
  flex: 1 1 300px;
  min-width: 0;
}

This pattern creates items that attempt to be 300 pixels wide but grow to fill available space and wrap to new rows when space constrains.

CSS Grid Auto-Fit Pattern

CSS Grid's auto-fit and minmax create responsive grids without media queries.

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.5rem;
}

This creates a grid where columns are at least 250 pixels wide, filling available space with as many columns as fit, and automatically wrapping to new rows.

Responsive Image Pattern

The picture element pattern serves different images at different breakpoints for optimal bandwidth usage.

<picture>
  <source media="(min-width: 1200px)" 
          srcset="image-large.jpg 1x, image-large-2x.jpg 2x">
  <source media="(min-width: 768px)" 
          srcset="image-medium.jpg 1x, image-medium-2x.jpg 2x">
  <img src="image-small.jpg" 
       srcset="image-small-2x.jpg 2x"
       alt="Descriptive text">
</picture>

Responsive Utility Classes Pattern

Utility classes control visibility and layout at different breakpoints without writing custom CSS.

.hide-mobile {
  display: none;
}

.hide-desktop {
  display: block;
}

@media (min-width: 768px) {
  .hide-mobile {
    display: block;
  }
  
  .hide-desktop {
    display: none;
  }
}

Touch-Friendly Spacing Pattern

Touch interfaces require larger hit areas and increased spacing between interactive elements.

.button {
  min-height: 44px;
  min-width: 44px;
  padding: 0.75rem 1.5rem;
  margin: 0.5rem;
}

@media (pointer: coarse) {
  .button {
    min-height: 48px;
    padding: 1rem 2rem;
    margin: 0.75rem;
  }
}

Performance Considerations

Image Optimization

Responsive images require careful optimization to avoid sending oversized assets to mobile devices. The srcset attribute enables browsers to select appropriate image sizes based on screen resolution and viewport width.

<img src="small.jpg"
     srcset="small.jpg 400w,
             medium.jpg 800w,
             large.jpg 1200w"
     sizes="(max-width: 768px) 100vw,
            (max-width: 1200px) 50vw,
            33vw"
     alt="Responsive image">

The sizes attribute tells the browser what size the image will be at different viewport widths. The browser uses this information along with the device pixel ratio to select the optimal image from srcset. A 400-pixel-wide phone with 2x pixel density may download the 800-pixel image to display sharp imagery.

WebP and AVIF formats provide superior compression compared to JPEG and PNG. Serve modern formats to supporting browsers while falling back to traditional formats:

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img src="image.jpg" alt="Fallback to JPEG">
</picture>

Lazy Loading

Lazy loading defers offscreen image loading until users scroll them into view, reducing initial page weight and improving perceived performance.

<img src="image.jpg" loading="lazy" alt="Description">

Native lazy loading works in modern browsers without JavaScript. For broader support or more control over loading behavior, use Intersection Observer:

const imageObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      img.classList.remove('lazy');
      observer.unobserve(img);
    }
  });
});

document.querySelectorAll('img.lazy').forEach(img => {
  imageObserver.observe(img);
});

Critical CSS

Critical CSS inlines above-the-fold styles in the HTML document, allowing initial render without waiting for external stylesheets. Remaining styles load asynchronously.

<head>
  <style>
    /* Critical CSS for above-the-fold content */
    body { margin: 0; font-family: sans-serif; }
    .header { background: #333; color: white; padding: 1rem; }
  </style>
  <link rel="preload" href="main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="main.css"></noscript>
</head>

Tools like Critical or Penthouse extract critical CSS automatically by rendering pages and identifying above-the-fold styles.

Reducing CSS Payload

Media queries increase CSS file size since all breakpoint styles download regardless of device. Conditional loading serves only relevant CSS to each device:

<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="mobile.css" media="(max-width: 767px)">
<link rel="stylesheet" href="tablet.css" media="(min-width: 768px) and (max-width: 1199px)">
<link rel="stylesheet" href="desktop.css" media="(min-width: 1200px)">

Browsers download all stylesheets but apply only matching ones. For true conditional delivery, use JavaScript or server-side detection.

JavaScript Performance

Responsive JavaScript should execute efficiently across devices with varying CPU capabilities. Debounce resize event handlers to prevent excessive function calls:

function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

const handleResize = debounce(() => {
  console.log('Window resized');
}, 250);

window.addEventListener('resize', handleResize);

Network Optimization

Mobile networks exhibit higher latency and lower bandwidth than wired connections. Minimize HTTP requests by combining files, using CSS sprites, and implementing HTTP/2 server push. Compress text assets with gzip or Brotli compression.

Service workers cache assets for offline access and faster subsequent loads:

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('v1').then(cache => {
      return cache.addAll([
        '/',
        '/styles/main.css',
        '/scripts/main.js',
        '/images/logo.svg'
      ]);
    })
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Third-Party Resource Impact

Third-party scripts and embeds significantly impact performance. Load analytics, ads, and social widgets asynchronously and defer them until after critical content renders:

<script async src="analytics.js"></script>
<script defer src="non-critical.js"></script>

The async attribute loads scripts without blocking HTML parsing but executes them immediately upon download. The defer attribute delays execution until HTML parsing completes.

Reference

Media Query Breakpoints

Breakpoint Range Typical Devices Common Use
xs 0-575px Small phones Single column, vertical stack
sm 576-767px Large phones Single or two column
md 768-991px Tablets Two to three column
lg 992-1199px Small desktops Multi-column with sidebar
xl 1200-1399px Desktops Full multi-column layout
xxl 1400px+ Large desktops Wide multi-column layout

Viewport Meta Tag Options

Attribute Values Description
width device-width, number Sets viewport width in pixels
initial-scale 0.1 to 10.0 Initial zoom level
minimum-scale 0.1 to 10.0 Minimum allowed zoom
maximum-scale 0.1 to 10.0 Maximum allowed zoom
user-scalable yes, no Allow user pinch-to-zoom
viewport-fit auto, contain, cover Control safe area insets

CSS Units for Responsive Design

Unit Type Description Use Case
% Relative Percentage of parent Fluid widths
em Relative Relative to element font size Scalable spacing
rem Relative Relative to root font size Consistent scaling
vw Viewport 1% of viewport width Full-width elements
vh Viewport 1% of viewport height Full-height sections
vmin Viewport 1% of smaller viewport dimension Responsive typography
vmax Viewport 1% of larger viewport dimension Aspect ratio maintenance
ch Relative Width of the 0 character Text containers
fr Grid Flexible grid fraction CSS Grid layouts

Touch Target Sizes

Element Type Minimum Size Recommended Size Spacing
Primary buttons 44x44px 48x48px 8px
Secondary buttons 40x40px 44x44px 8px
Text links 44px height 48px height 8px vertical
Form inputs 44px height 48px height 16px vertical
Icon buttons 44x44px 48x48px 8px
Navigation items 44px height 48px height 8px between items

Image Format Comparison

Format Compression Transparency Animation Best For
JPEG Lossy No No Photos, complex images
PNG Lossless Yes No Graphics, transparency needed
WebP Both Yes Yes Modern web, general purpose
AVIF Both Yes Yes Next-gen, superior compression
SVG N/A Yes Yes Logos, icons, illustrations

Common Media Query Patterns

Pattern Code Example Use Case
Min-width @media (min-width: 768px) Mobile-first approach
Max-width @media (max-width: 767px) Desktop-first approach
Width range @media (min-width: 768px) and (max-width: 991px) Tablet-specific styles
Orientation @media (orientation: landscape) Layout changes for orientation
Pointer type @media (pointer: coarse) Touch vs mouse input
Resolution @media (min-resolution: 2dppx) High-DPI displays
Prefers color scheme @media (prefers-color-scheme: dark) Dark mode support
Reduced motion @media (prefers-reduced-motion: reduce) Accessibility consideration

Flexbox Responsive Properties

Property Values Responsive Application
flex-direction row, column Stack vertically on mobile
flex-wrap nowrap, wrap Allow items to wrap
flex-basis auto, length, percentage Base size before growing
flex-grow number Allow items to expand
flex-shrink number Allow items to contract
gap length Responsive spacing
justify-content flex-start, center, space-between Horizontal alignment
align-items flex-start, center, stretch Vertical alignment

Grid Responsive Properties

Property Values Responsive Application
grid-template-columns repeat, auto-fit, minmax Automatic column adjustment
grid-template-rows auto, fr, minmax Flexible row heights
grid-auto-flow row, column, dense Content flow direction
gap length Responsive gutters
grid-template-areas quoted strings Named layout areas
justify-items start, center, stretch Item horizontal alignment
align-items start, center, stretch Item vertical alignment

Performance Optimization Checklist

Optimization Implementation Impact
Responsive images srcset, picture element Reduces bandwidth 50-70%
Lazy loading loading=lazy attribute Faster initial load
Critical CSS Inline above-fold styles Eliminates render blocking
Compress images WebP, AVIF formats 30-50% smaller files
Minify CSS/JS Build tool minification 20-40% smaller files
Enable compression gzip, Brotli 70-80% smaller transfer
CDN delivery Content distribution network Reduced latency
Cache assets Service worker, HTTP cache Instant repeat visits