Responsive Design

Responsive Web Design

Building for Every Device

CSCI 4513 - Advanced Web Programming

Week 9, Lecture 17

Today's Learning Objectives

Norse Mythology Connection

Skíðblaðnir - The Folding Ship

"Skíðblaðnir could expand to carry all the gods or fold to fit in Freyr's pocket, just as responsive sites adapt from mobile to desktop while maintaining all capabilities."

Among the legendary treasures created by the sons of Ivaldi was Skíðblaðnir, a magnificent ship crafted for the god Freyr. This vessel was large enough to carry all the Aesir gods with their weapons, yet when not needed, it could fold itself small enough to fit in Freyr's pocket. The transformation was seamless—nothing was lost in the folding, and nothing was compromised in the expansion.

The Ship's Adaptive Magic

/* Skíðblaðnir folded (mobile) */
.container {
    width: 100%;
    flex-direction: column;
}

/* Skíðblaðnir expanded (desktop) */
@media (min-width: 768px) {
    .container {
        max-width: 1200px;
        flex-direction: row;
    }
}

Reflection: Skíðblaðnir maintained all capabilities whether folded or expanded. What functionality do websites often sacrifice on mobile that shouldn't be?

Note on Web Accessibility

We're Skipping the Accessibility Section

Two reasons:

  1. We bake it in everywhere - You've been learning accessibility best practices throughout this course (semantic HTML, proper contrast, keyboard navigation, etc.)
  2. Ongoing learning - Accessibility is content you should review on your own and revisit regularly to stay current with best practices

Accessibility isn't a one-time lesson—it's a continuous commitment to inclusive design.

What is Responsive Design?

Creating websites that respond to changes in browser size to work on any device

📱

Mobile

320px - 500px

💻

Tablet

500px - 1000px

🖥️

Desktop

1000px+

Why Responsive Design?

📅 2007: First iPhone released

📊 Today: Mobile traffic exceeds desktop

Requirement: Sites must work on all screen sizes

Reality Check: Your simple HTML-only recipe project probably worked fine on phones, but complex layouts require responsive techniques

Screen Size Support

Minimum Width

320px

Smallest phones in common use

If it works at 320px, it works on any small device

Maximum Width

???

Ultra-wide monitors exist!

Solution: Set max-width and center content

Natural Responsiveness

HTML is Responsive by Default

Mind-blowing fact: Plain HTML with no CSS is completely responsive!

Most elements are responsive until you change that with CSS

Approach: Start with natural responsiveness and maintain it as you add styles

The Viewport Meta Tag

Essential for every project:

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

What it does:

  • Sets initial width to actual screen width
  • Prevents mobile browser zoom-out behavior
  • Without it: phones show desktop version zoomed out
  • With it: phones show mobile-optimized version

Good news: Emmet includes this automatically! (! + Enter)

Avoid Fixed Width

The #1 Enemy of Flexibility

❌ Bad

.container {
  width: 600px;
}

Can never shrink below 600px!

✅ Good

.container {
  max-width: 600px;
}

Won't exceed 600px but will shrink!

Rule: Use max-width instead of width for containers

Avoid Fixed Height

❌ Bad

.box {
  height: 300px;
}

Content overflow on small screens!

✅ Good

.box {
  min-height: 300px;
}

Grows if content needs space!

Even better: Avoid height altogether! Use padding and margin to control spacing

When Fixed Widths Are OK

Small elements: 32px icon doesn't need to shrink

Sidebars: A 250px sidebar might need to stay 250px

Rule of thumb: Smaller widths = more acceptable to fix

Consider your options: Think about whether each element truly needs a fixed size

Use Flex and Grid

These were designed for responsive layouts!

/* Responsive with flex-wrap */
.container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.item {
  flex: 1 1 300px; /* Grow, shrink, basis */
}

/* Responsive with grid auto-fill */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

Responsive Images

The Aspect Ratio Problem

Problem: Shrinking width without adjusting height = distorted images!

❌ Distorted

img {
  width: 200px;
  height: 400px;
}

✅ Preserved

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

background-size & background-position

For background images (not <img> tags)

.hero {
  background-image: url('hero.jpg');
  background-size: cover;      /* Fill container */
  background-position: center; /* Keep centered */
  height: 400px;
}

/* Other options */
background-size: contain;  /* Fit inside, might not fill */
background-size: 100% 100%; /* Stretch (usually bad) */

cover: Fills entire container, may crop edges

contain: Entire image visible, may have empty space

object-fit Property

For <img> tags (works like background-size)

img {
  width: 300px;
  height: 200px;
  object-fit: cover;  /* Fill dimensions, maintain aspect */
  object-position: center; /* Center the image */
}

/* Other object-fit values */
object-fit: fill;      /* Default - stretches */
object-fit: contain;   /* Fit inside, letterbox */
object-fit: cover;     /* Fill, crop if needed */
object-fit: none;      /* Use original size */
object-fit: scale-down; /* Smaller of none or contain */

The <picture> Element

Serve different images for different screen sizes

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

Why? Send smaller files to mobile devices, cropped versions for better composition, or high-res images for retina displays

srcset Attribute

Let the browser choose the best image

<img
  src="small.jpg"
  srcset="small.jpg 500w,
          medium.jpg 1000w,
          large.jpg 2000w"
  sizes="(max-width: 600px) 500px,
         (max-width: 1200px) 1000px,
         2000px"
  alt="Responsive image"
>

Browser: "I'm 800px wide, screen is 2x density, I'll grab medium.jpg"

Media Queries

Conditional Styles Based on Screen Size

body {
  margin: 24px;
}

@media (max-width: 600px) {
  body {
    margin: 8px;
  }
}

How it works:

  • Screens ≤ 600px: margin is 8px
  • Screens > 600px: margin is 24px

Media Query Syntax

/* Max-width: applies UP TO this size */
@media (max-width: 768px) {
  /* Mobile styles */
}

/* Min-width: applies FROM this size and up */
@media (min-width: 768px) {
  /* Desktop styles */
}

/* Combining conditions */
@media (min-width: 600px) and (max-width: 1200px) {
  /* Tablet styles */
}

/* Multiple queries */
.nav {
  display: flex;
}

@media (max-width: 768px) {
  .nav {
    flex-direction: column;
  }
}

max-width vs min-width

max-width

@media (max-width: 600px) {
  /* Applies when
     screen is
     600px or less */
}

Think: "up to this size"

min-width

@media (min-width: 600px) {
  /* Applies when
     screen is
     600px or more */
}

Think: "from this size up"

Common Breakpoints

📱 Mobile: 320px - 500px

📲 Large Mobile / Small Tablet: 500px - 768px

💻 Tablet: 768px - 1024px

🖥️ Desktop: 1024px - 1200px

🖥️ Large Desktop: 1200px+

Important: These are guidelines, not rules! Choose breakpoints based on YOUR design, not arbitrary device sizes

Limit Your Media Queries

Best Practice: Use as few breakpoints as possible

Simple layouts: One breakpoint around 600px

Complex layouts: Maybe 2-3 breakpoints

Avoid: Breakpoints for every device size

Why? Rely on natural flexibility of flexbox/grid first, then add media queries only where needed

Mobile-First Approach

/* Base styles for mobile */
.container {
  width: 100%;
  padding: 10px;
}

.sidebar {
  display: none; /* Hidden on mobile */
}

/* Progressive enhancement for larger screens */
@media (min-width: 768px) {
  .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
  }

  .sidebar {
    display: block; /* Show on desktop */
  }
}

Strategy: Start with mobile, enhance for desktop with min-width queries

Practical Media Query Example

/* Navigation: column on mobile, row on desktop */
.nav {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

@media (min-width: 768px) {
  .nav {
    flex-direction: row;
    gap: 30px;
  }
}

/* Grid: 1 column mobile, 2 tablet, 3 desktop */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
}

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

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

Zooming in Browsers

Important! Browser zoom affects effective resolution

🔍 Zoom in: 1000px window acts like smaller screen

🔍 Zoom out: Useful for testing large screens

⚠️ Watch out: Forgetting you're zoomed causes confusion!

DevTools tip: Use responsive design mode to test different sizes

Print Styles

Media queries aren't just for screen sizes!

/* Screen styles (default) */
@media screen {
  .nav { display: flex; }
}

/* Print styles */
@media print {
  /* Hide non-essential elements */
  .nav,
  .sidebar,
  button {
    display: none;
  }

  /* Optimize for print */
  body {
    color: black;
    background: white;
  }

  a::after {
    content: " (" attr(href) ")"; /* Show URLs */
  }
}

Container Queries

Style based on container size, not viewport size

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

.card h2 {
  font-size: 1.2em;
}

/* When container is 400px+, not viewport! */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }

  .card h2 {
    font-size: 2em;
  }
}

Use case: Reusable components that adapt to their container, not the whole page

Container vs Media Queries

Media Queries

Based on viewport/device

Good for:

  • Page layout
  • Navigation
  • Global changes

Container Queries

Based on container size

Good for:

  • Components
  • Cards
  • Reusable modules

Responsive Design Checklist

✅ Include viewport meta tag

✅ Use max-width instead of width

✅ Avoid fixed heights

✅ Make images responsive (max-width: 100%, height: auto)

✅ Use flexbox and grid with flexible properties

✅ Add media queries only where needed

✅ Test on actual devices or DevTools

✅ Support 320px minimum width

Testing Your Responsive Design

Browser DevTools

  • Toggle device toolbar (Cmd+Shift+M / Ctrl+Shift+M)
  • Test preset devices
  • Custom dimensions
  • Rotate to landscape

Real Devices

  • Test on actual phones/tablets
  • Different screen sizes
  • Different browsers
  • Portrait and landscape

Project: Responsive Homepage

Your Final HTML/CSS Project!

Goal: Create a responsive portfolio homepage

Requirements:

  • Match provided designs for desktop, tablet, and mobile
  • Work on any screen 320px - 1920px wide
  • Use your own fonts, colors, and images
  • Focus on layouts and responsive behavior

Project Steps

1. Setup:

  • Create HTML/CSS files
  • Download design files (desktop, tablet, mobile)

2. Gather Assets:

  • Choose fonts (Playfair Display & Roboto suggested)
  • Get icons from devicon.dev and materialdesignicons.com
  • Find or use placeholder images

3. Build:

  • Start with larger sections
  • Work top-to-bottom
  • Add responsiveness

Assignment Reading

📖 MDN - Using the viewport meta tag

📖 MDN - Responsive Images

📖 CSS Tricks - Responsive Images Syntax

📖 MDN - Using media queries

🔗 Read about background-size, background-position, object-fit

Knowledge Check

❓ What is responsive design and why is it important?

❓ What does natural responsiveness mean?

❓ Why should you avoid fixed width and height?

❓ What's the difference between object-fit and background-size?

❓ How do you define a media query for mobile layouts?

❓ What's the difference between max-width and min-width?

❓ When would you use a <picture> element vs srcset?

Today's Key Takeaways

Responsive design makes sites work on any screen size

Natural responsiveness: HTML is responsive by default

Avoid fixed sizes: Use max-width and min-height

Responsive images: max-width: 100%, height: auto

Media queries: Conditional styles based on screen size

Mobile-first: Start small, enhance for larger screens

Next Class

React - Environment Setup & Introduction

⚛️ What is React and why use it?

🛠️ Setting up your development environment

📦 Creating your first React app

🧩 Understanding components

See you next week!

Spring Break is coming up!