responsive-design

Master modern responsive design techniques to create interfaces that adapt seamlessly across all screen sizes and device contexts.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "responsive-design" with this command: npx skills add wshobson/agents/wshobson-agents-responsive-design

Responsive Design

Master modern responsive design techniques to create interfaces that adapt seamlessly across all screen sizes and device contexts.

When to Use This Skill

  • Implementing mobile-first responsive layouts

  • Using container queries for component-based responsiveness

  • Creating fluid typography and spacing scales

  • Building complex layouts with CSS Grid and Flexbox

  • Designing breakpoint strategies for design systems

  • Implementing responsive images and media

  • Creating adaptive navigation patterns

  • Building responsive tables and data displays

Core Capabilities

  1. Container Queries
  • Component-level responsiveness independent of viewport

  • Container query units (cqi, cqw, cqh)

  • Style queries for conditional styling

  • Fallbacks for browser support

  1. Fluid Typography & Spacing
  • CSS clamp() for fluid scaling

  • Viewport-relative units (vw, vh, dvh)

  • Fluid type scales with min/max bounds

  • Responsive spacing systems

  1. Layout Patterns
  • CSS Grid for 2D layouts

  • Flexbox for 1D distribution

  • Intrinsic layouts (content-based sizing)

  • Subgrid for nested grid alignment

  1. Breakpoint Strategy
  • Mobile-first media queries

  • Content-based breakpoints

  • Design token integration

  • Feature queries (@supports)

Quick Reference

Modern Breakpoint Scale

/* Mobile-first breakpoints / / Base: Mobile (< 640px) / @media (min-width: 640px) { / sm: Landscape phones, small tablets / } @media (min-width: 768px) { / md: Tablets / } @media (min-width: 1024px) { / lg: Laptops, small desktops / } @media (min-width: 1280px) { / xl: Desktops / } @media (min-width: 1536px) { / 2xl: Large desktops */ }

/* Tailwind CSS equivalent / / sm: @media (min-width: 640px) / / md: @media (min-width: 768px) / / lg: @media (min-width: 1024px) / / xl: @media (min-width: 1280px) / / 2xl: @media (min-width: 1536px) */

Key Patterns

Pattern 1: Container Queries

/* Define a containment context */ .card-container { container-type: inline-size; container-name: card; }

/* Query the container, not the viewport */ @container card (min-width: 400px) { .card { display: grid; grid-template-columns: 200px 1fr; gap: 1rem; }

.card-image { aspect-ratio: 1; } }

@container card (min-width: 600px) { .card { grid-template-columns: 250px 1fr; }

.card-title { font-size: 1.5rem; } }

/* Container query units / .card-title { / 5% of container width, clamped between 1rem and 2rem */ font-size: clamp(1rem, 5cqi, 2rem); }

// React component with container queries function ResponsiveCard({ title, image, description }) { return ( <div className="@container"> <article className="flex flex-col @md:flex-row @md:gap-4"> <img src={image} alt="" className="w-full @md:w-48 @lg:w-64 aspect-video @md:aspect-square object-cover" /> <div className="p-4 @md:p-0"> <h2 className="text-lg @md:text-xl @lg:text-2xl font-semibold"> {title} </h2> <p className="mt-2 text-muted-foreground @md:line-clamp-3"> {description} </p> </div> </article> </div> ); }

Pattern 2: Fluid Typography

/* Fluid type scale using clamp() / :root { / Min size, preferred (fluid), max size */ --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); --text-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem); --text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); --text-lg: clamp(1.125rem, 1rem + 0.625vw, 1.25rem); --text-xl: clamp(1.25rem, 1rem + 1.25vw, 1.5rem); --text-2xl: clamp(1.5rem, 1.25rem + 1.25vw, 2rem); --text-3xl: clamp(1.875rem, 1.5rem + 1.875vw, 2.5rem); --text-4xl: clamp(2.25rem, 1.75rem + 2.5vw, 3.5rem); }

/* Usage */ h1 { font-size: var(--text-4xl); } h2 { font-size: var(--text-3xl); } h3 { font-size: var(--text-2xl); } p { font-size: var(--text-base); }

/* Fluid spacing scale */ :root { --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem); --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem); --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem); --space-lg: clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem); --space-xl: clamp(2rem, 1.5rem + 2.5vw, 4rem); }

// Utility function for fluid values function fluidValue( minSize: number, maxSize: number, minWidth = 320, maxWidth = 1280, ) { const slope = (maxSize - minSize) / (maxWidth - minWidth); const yAxisIntersection = -minWidth * slope + minSize;

return clamp(${minSize}rem, ${yAxisIntersection.toFixed(4)}rem + ${(slope * 100).toFixed(4)}vw, ${maxSize}rem); }

// Generate fluid type scale const fluidTypeScale = { sm: fluidValue(0.875, 1), base: fluidValue(1, 1.125), lg: fluidValue(1.25, 1.5), xl: fluidValue(1.5, 2), "2xl": fluidValue(2, 3), };

Pattern 3: CSS Grid Responsive Layout

/* Auto-fit grid - items wrap automatically */ .grid-auto { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 1.5rem; }

/* Auto-fill grid - maintains empty columns */ .grid-auto-fill { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1rem; }

/* Responsive grid with named areas */ .page-layout { display: grid; grid-template-areas: "header" "main" "sidebar" "footer"; gap: 1rem; }

@media (min-width: 768px) { .page-layout { grid-template-columns: 1fr 300px; grid-template-areas: "header header" "main sidebar" "footer footer"; } }

@media (min-width: 1024px) { .page-layout { grid-template-columns: 250px 1fr 300px; grid-template-areas: "header header header" "nav main sidebar" "footer footer footer"; } }

.header { grid-area: header; } .main { grid-area: main; } .sidebar { grid-area: sidebar; } .footer { grid-area: footer; }

// Responsive grid component function ResponsiveGrid({ children, minItemWidth = "250px", gap = "1.5rem" }) { return ( <div className="grid" style={{ gridTemplateColumns: repeat(auto-fit, minmax(min(${minItemWidth}, 100%), 1fr)), gap, }} > {children} </div> ); }

// Usage with Tailwind function ProductGrid({ products }) { return ( <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 md:gap-6"> {products.map((product) => ( <ProductCard key={product.id} product={product} /> ))} </div> ); }

Pattern 4: Responsive Navigation

function ResponsiveNav({ items }) { const [isOpen, setIsOpen] = useState(false);

return ( <nav className="relative"> {/* Mobile menu button */} <button className="lg:hidden p-2" onClick={() => setIsOpen(!isOpen)} aria-expanded={isOpen} aria-controls="nav-menu" > <span className="sr-only">Toggle navigation</span> {isOpen ? <X /> : <Menu />} </button>

  {/* Navigation links */}
  &#x3C;ul
    id="nav-menu"
    className={cn(
      // Base: hidden on mobile
      "absolute top-full left-0 right-0 bg-background border-b",
      "flex flex-col",
      // Mobile: slide down
      isOpen ? "flex" : "hidden",
      // Desktop: always visible, horizontal
      "lg:static lg:flex lg:flex-row lg:border-0 lg:bg-transparent",
    )}
  >
    {items.map((item) => (
      &#x3C;li key={item.href}>
        &#x3C;a
          href={item.href}
          className={cn(
            "block px-4 py-3",
            "lg:px-3 lg:py-2",
            "hover:bg-muted lg:hover:bg-transparent lg:hover:text-primary",
          )}
        >
          {item.label}
        &#x3C;/a>
      &#x3C;/li>
    ))}
  &#x3C;/ul>
&#x3C;/nav>

); }

Pattern 5: Responsive Images

// Responsive image with art direction function ResponsiveHero() { return ( <picture> {/* Art direction: different crops for different screens */} <source media="(min-width: 1024px)" srcSet="/hero-wide.webp" type="image/webp" /> <source media="(min-width: 768px)" srcSet="/hero-medium.webp" type="image/webp" /> <source srcSet="/hero-mobile.webp" type="image/webp" />

  {/* Fallback */}
  &#x3C;img
    src="/hero-mobile.jpg"
    alt="Hero image description"
    className="w-full h-auto"
    loading="eager"
    fetchpriority="high"
  />
&#x3C;/picture>

); }

// Responsive image with srcset for resolution switching function ProductImage({ product }) { return ( <img src={product.image} srcSet={ ${product.image}?w=400 400w, ${product.image}?w=800 800w, ${product.image}?w=1200 1200w } sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw" alt={product.name} className="w-full h-auto object-cover" loading="lazy" /> ); }

Pattern 6: Responsive Tables

// Responsive table with horizontal scroll function ResponsiveTable({ data, columns }) { return ( <div className="w-full overflow-x-auto"> <table className="w-full min-w-[600px]"> <thead> <tr> {columns.map((col) => ( <th key={col.key} className="text-left p-3"> {col.label} </th> ))} </tr> </thead> <tbody> {data.map((row, i) => ( <tr key={i} className="border-t"> {columns.map((col) => ( <td key={col.key} className="p-3"> {row[col.key]} </td> ))} </tr> ))} </tbody> </table> </div> ); }

// Card-based table for mobile function ResponsiveDataTable({ data, columns }) { return ( <> {/* Desktop table /} <table className="hidden md:table w-full"> {/ ... standard table */} </table>

  {/* Mobile cards */}
  &#x3C;div className="md:hidden space-y-4">
    {data.map((row, i) => (
      &#x3C;div key={i} className="border rounded-lg p-4 space-y-2">
        {columns.map((col) => (
          &#x3C;div key={col.key} className="flex justify-between">
            &#x3C;span className="font-medium text-muted-foreground">
              {col.label}
            &#x3C;/span>
            &#x3C;span>{row[col.key]}&#x3C;/span>
          &#x3C;/div>
        ))}
      &#x3C;/div>
    ))}
  &#x3C;/div>
&#x3C;/>

); }

Viewport Units

/* Standard viewport units / .full-height { height: 100vh; / May cause issues on mobile */ }

/* Dynamic viewport units (recommended for mobile) / .full-height-dynamic { height: 100dvh; / Accounts for mobile browser UI */ }

/* Small viewport (minimum) */ .min-full-height { min-height: 100svh; }

/* Large viewport (maximum) */ .max-full-height { max-height: 100lvh; }

/* Viewport-relative font sizing / .hero-title { / 5vw with min/max bounds */ font-size: clamp(2rem, 5vw, 4rem); }

Best Practices

  • Mobile-First: Start with mobile styles, enhance for larger screens

  • Content Breakpoints: Set breakpoints based on content, not devices

  • Fluid Over Fixed: Use fluid values for typography and spacing

  • Container Queries: Use for component-level responsiveness

  • Test Real Devices: Simulators don't catch all issues

  • Performance: Optimize images, lazy load off-screen content

  • Touch Targets: Maintain 44x44px minimum on mobile

  • Logical Properties: Use inline/block for internationalization

Common Issues

  • Horizontal Overflow: Content breaking out of viewport

  • Fixed Widths: Using px instead of relative units

  • Viewport Height: 100vh issues on mobile browsers

  • Font Size: Text too small on mobile

  • Touch Targets: Buttons too small to tap accurately

  • Aspect Ratio: Images squishing or stretching

  • Z-Index Stacking: Overlays breaking on different screens

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

typescript-advanced-types

TypeScript Advanced Types

Repository Source
14K31.3Kwshobson
Coding

python-performance-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-review-excellence

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

python-testing-patterns

No summary provided by upstream source.

Repository SourceNeeds Review