tailwindcss-mobile-first

Mobile-first responsive design patterns with 2025/2026 best practices for Tailwind CSS v4. Covers six breakpoint strategy, fluid typography and spacing using CSS clamp, and container queries for component-level responsiveness independent of viewport size Includes WCAG 2.2 compliant touch targets (44–48px minimum), safe area handling for notched devices, and practical layout patterns for grids, flexbox, and sidebars Provides mobile navigation patterns, responsive image and video techniques with aspect ratio containers to prevent layout shift, and performance optimization strategies Details responsive typography hierarchy, lazy loading, content visibility, and a comprehensive testing checklist covering 320px to 1920px viewports

INSTALLATION
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill tailwindcss-mobile-first
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2a

Key Principle: Unprefixed utilities apply to ALL screen sizes. Breakpoint prefixes apply at that size AND ABOVE.

2025/2026 Breakpoint Strategy

Tailwind's Default Breakpoints

Prefix

Min-width

Target Devices

(none)

0px

All mobile phones (base)

sm:

640px (40rem)

Large phones, small tablets

md:

768px (48rem)

Tablets (portrait)

lg:

1024px (64rem)

Tablets (landscape), laptops

xl:

1280px (80rem)

Desktops

2xl:

1536px (96rem)

Large desktops

Content-Driven Breakpoints

Best Practice 2025/2026: Let content determine breakpoints, not device dimensions.

@theme {

  /* Override defaults based on YOUR content needs */

  --breakpoint-sm: 36rem;  /* 576px - when your content needs more space */

  --breakpoint-md: 48rem;  /* 768px */

  --breakpoint-lg: 62rem;  /* 992px - common content width */

  --breakpoint-xl: 75rem;  /* 1200px */

  --breakpoint-2xl: 90rem; /* 1440px */



  /* Add custom breakpoints for specific content needs */

  --breakpoint-xs: 20rem;  /* 320px - very small devices */

  --breakpoint-3xl: 120rem; /* 1920px - ultra-wide */

}

Screen Coverage Strategy

<!-- Cover the most common device ranges (2025/2026 data) -->



<!-- 375px-430px: ~50% of mobile devices (iPhone, modern Android) -->

<div class="px-4">Mobile base</div>



<!-- 768px+: Tablets and small laptops -->

<div class="px-4 md:px-6">Tablet enhancement</div>



<!-- 1024px+: Desktop experience -->

<div class="px-4 md:px-6 lg:px-8">Desktop enhancement</div>



<!-- 1440px+: Wide desktop experience -->

<div class="px-4 md:px-6 lg:px-8 xl:px-12">Wide desktop</div>

Fluid Typography System

CSS Clamp for Smooth Scaling

Fluid typography eliminates jarring size jumps between breakpoints:

@theme {

  /* Fluid typography scale */

  --text-fluid-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);

  --text-fluid-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem);

  --text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);

  --text-fluid-lg: clamp(1.125rem, 1rem + 0.625vw, 1.25rem);

  --text-fluid-xl: clamp(1.25rem, 1rem + 1.25vw, 1.5rem);

  --text-fluid-2xl: clamp(1.5rem, 1.1rem + 2vw, 2rem);

  --text-fluid-3xl: clamp(1.875rem, 1.2rem + 3.375vw, 2.5rem);

  --text-fluid-4xl: clamp(2.25rem, 1rem + 6.25vw, 3.5rem);

  --text-fluid-5xl: clamp(3rem, 1rem + 10vw, 5rem);

}

Important for Accessibility: Always combine vw with rem to respect user zoom preferences (WCAG compliance).

Using Fluid Typography

<!-- Fluid heading that scales smoothly -->

<h1 class="text-fluid-4xl font-bold leading-tight">

  Responsive Heading

</h1>



<!-- Fluid body text -->

<p class="text-fluid-base leading-relaxed max-w-prose">

  Body text that scales proportionally with the viewport

  while respecting user's font size preferences.

</p>



<!-- Fluid with breakpoint overrides for fine control -->

<h2 class="text-fluid-2xl lg:text-fluid-3xl font-semibold">

  Section Title

</h2>

Fluid Spacing System

Clamp-Based Spacing

@theme {

  /* Fluid spacing scale */

  --spacing-fluid-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);

  --spacing-fluid-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem);

  --spacing-fluid-md: clamp(1rem, 0.75rem + 1.25vw, 2rem);

  --spacing-fluid-lg: clamp(1.5rem, 1rem + 2.5vw, 3rem);

  --spacing-fluid-xl: clamp(2rem, 1.25rem + 3.75vw, 4rem);

  --spacing-fluid-2xl: clamp(3rem, 1.5rem + 7.5vw, 6rem);

  --spacing-fluid-section: clamp(4rem, 2rem + 10vw, 8rem);

}

Using Fluid Spacing

<!-- Fluid section padding -->

<section class="py-fluid-section px-fluid-md">

  <div class="max-w-7xl mx-auto">

    <h2 class="mb-fluid-lg">Section Title</h2>

    <div class="grid gap-fluid-md grid-cols-1 md:grid-cols-2 lg:grid-cols-3">

      <!-- Cards -->

    </div>

  </div>

</section>



<!-- Hero section with fluid spacing -->

<header class="min-h-screen flex items-center py-fluid-2xl px-fluid-md">

  <div class="max-w-4xl">

    <h1 class="text-fluid-5xl mb-fluid-md">Hero Title</h1>

    <p class="text-fluid-lg mb-fluid-lg">Hero description</p>

    <button class="px-fluid-md py-fluid-sm">Get Started</button>

  </div>

</header>

Touch-Friendly Interactive Elements

WCAG 2.2 Touch Target Requirements

Minimum sizes (2025 standards):

  • WCAG 2.2 Level AA: 24x24 CSS pixels minimum
  • Recommended: 44x44 CSS pixels (Apple, Google, Microsoft guidelines)
  • Optimal: 48x48 CSS pixels for critical actions
<!-- WCAG 2.2 compliant touch targets -->



<!-- Minimum AA compliant (24px) -->

<button class="min-h-6 min-w-6 p-1">

  <svg class="h-4 w-4">...</svg>

</button>



<!-- Recommended size (44px) -->

<button class="min-h-11 min-w-11 p-2.5">

  <svg class="h-6 w-6">...</svg>

  <span class="sr-only">Action</span>

</button>



<!-- Optimal for primary actions (48px) -->

<button class="min-h-12 min-w-12 px-6 py-3 text-base">

  Primary Action

</button>

Extended Touch Targets

<!-- Extend touch target beyond visible element -->

<a href="/link" class="relative inline-block text-sm">

  Small visible link

  <!-- Invisible extended touch area -->

  <span class="absolute -inset-3" aria-hidden="true"></span>

</a>



<!-- Icon button with extended target -->

<button class="relative p-2 -m-2 rounded-lg hover:bg-gray-100">

  <svg class="h-5 w-5" aria-hidden="true">...</svg>

  <span class="sr-only">Close</span>

</button>

Touch Target Spacing

<!-- Adequate spacing between touch targets (minimum 8px gap) -->

<nav class="flex gap-3">

  <a href="#" class="min-h-11 px-4 py-2.5">Home</a>

  <a href="#" class="min-h-11 px-4 py-2.5">About</a>

  <a href="#" class="min-h-11 px-4 py-2.5">Contact</a>

</nav>



<!-- Stacked navigation with adequate spacing -->

<nav class="flex flex-col">

  <a href="#" class="py-3 px-4 min-h-11 border-b border-gray-100">Link 1</a>

  <a href="#" class="py-3 px-4 min-h-11 border-b border-gray-100">Link 2</a>

  <a href="#" class="py-3 px-4 min-h-11">Link 3</a>

</nav>



<!-- Button group with safe spacing -->

<div class="flex flex-wrap gap-3">

  <button class="min-h-11 px-4 py-2">Cancel</button>

  <button class="min-h-11 px-4 py-2 bg-blue-600 text-white">Confirm</button>

</div>

Container Queries (2025 Game-Changer)

Container queries enable component-level responsiveness, independent of viewport size.

Setup

@import "tailwindcss";

@plugin "@tailwindcss/container-queries";

Container Query Breakpoints

Class

Min-width

@xs

20rem (320px)

@sm

24rem (384px)

@md

28rem (448px)

@lg

32rem (512px)

@xl

36rem (576px)

@2xl

42rem (672px)

@3xl

48rem (768px)

@4xl

56rem (896px)

@5xl

64rem (1024px)

Practical Container Query Patterns

<!-- Card that responds to its container, not viewport -->

<article class="@container">

  <div class="

    flex flex-col @sm:flex-row

    gap-4 p-4

    bg-white rounded-xl shadow-sm

  ">

    <img

      src="..."

      class="

        w-full @sm:w-32 @lg:w-48

        aspect-video @sm:aspect-square

        object-cover rounded-lg

      "

    />

    <div class="flex-1 min-w-0">

      <h3 class="text-base @md:text-lg @lg:text-xl font-semibold truncate">

        Card Title

      </h3>

      <p class="

        text-sm @md:text-base

        text-gray-600

        line-clamp-2 @lg:line-clamp-3

        mt-2

      ">

        Description that adapts to available space...

      </p>

      <div class="mt-4 flex flex-wrap gap-2 @md:gap-3">

        <span class="text-xs @md:text-sm px-2 py-1 bg-gray-100 rounded">Tag</span>

      </div>

    </div>

  </div>

</article>

Named Containers

<div class="@container/sidebar w-64">

  <nav class="

    flex flex-col @lg/sidebar:flex-row

    @lg/sidebar:items-center

    gap-2 @lg/sidebar:gap-4

  ">

    <a href="#">Link 1</a>

    <a href="#">Link 2</a>

  </nav>

</div>



<main class="@container/main flex-1">

  <div class="

    grid grid-cols-1

    @md/main:grid-cols-2

    @xl/main:grid-cols-3

    gap-6

  ">

    <!-- Grid items respond to main container -->

  </div>

</main>

When to Use Container vs Viewport Queries

Use Container Queries

Use Viewport Queries

Reusable components

Page-level layouts

Sidebar widgets

Navigation bars

Card grids

Hero sections

Embedded content

Full-width sections

CMS/dynamic content

Fixed app shells

Responsive Layout Patterns

Mobile-First Grid System

<!-- Auto-responsive grid with minimum card width -->

<div class="

  grid gap-6

  grid-cols-1

  sm:grid-cols-2

  lg:grid-cols-3

  xl:grid-cols-4

">

  <!-- Cards automatically flow -->

</div>



<!-- CSS Grid auto-fit (no breakpoints needed) -->

<div class="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-6">

  <!-- Cards auto-fit with 280px minimum -->

</div>



<!-- CSS Grid auto-fill for fixed-size items -->

<div class="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-4">

  <!-- Fixed minimum size, grows to fill -->

</div>

Responsive Flexbox Patterns

<!-- Stack to row -->

<div class="flex flex-col md:flex-row gap-4">

  <div class="flex-1">Content 1</div>

  <div class="flex-1">Content 2</div>

</div>



<!-- Wrap with centered items -->

<div class="flex flex-wrap justify-center gap-4">

  <div class="w-full sm:w-auto">Item 1</div>

  <div class="w-full sm:w-auto">Item 2</div>

  <div class="w-full sm:w-auto">Item 3</div>

</div>



<!-- Mobile stack, desktop inline with push -->

<div class="flex flex-col sm:flex-row sm:items-center gap-4">

  <div class="flex-1">

    <h3>Title</h3>

    <p class="text-sm text-gray-600">Description</p>

  </div>

  <button class="sm:ml-auto min-h-11 px-4 py-2">Action</button>

</div>

Responsive Sidebar Layouts

<!-- Collapsible sidebar -->

<div class="flex min-h-screen">

  <!-- Sidebar: hidden on mobile, visible on desktop -->

  <aside class="

    hidden lg:flex lg:flex-col

    w-64 border-r bg-gray-50

  ">

    <nav class="flex-1 p-4">...</nav>

  </aside>



  <!-- Main content -->

  <main class="flex-1 p-4 lg:p-8">

    Content

  </main>

</div>



<!-- Mobile drawer + desktop sidebar -->

<div class="relative flex min-h-screen">

  <!-- Mobile drawer overlay -->

  <div class="

    fixed inset-0 z-40 lg:hidden

    bg-black/50

    data-[open=false]:hidden

  " data-open="false">

    <aside class="w-64 h-full bg-white">

      Mobile navigation

    </aside>

  </div>



  <!-- Desktop sidebar -->

  <aside class="hidden lg:block w-64 border-r">

    Desktop navigation

  </aside>



  <main class="flex-1">Content</main>

</div>

Holy Grail Layout (2025)

<div class="min-h-screen grid grid-rows-[auto_1fr_auto]">

  <!-- Header -->

  <header class="sticky top-0 z-50 h-16 bg-white border-b shadow-sm">

    <nav class="h-full max-w-7xl mx-auto px-4 flex items-center justify-between">

      <Logo />

      <ul class="hidden md:flex gap-6">...</ul>

      <button class="md:hidden min-h-11 min-w-11">Menu</button>

    </nav>

  </header>



  <!-- Main content area with optional sidebars -->

  <div class="

    grid

    grid-cols-1

    md:grid-cols-[240px_1fr]

    lg:grid-cols-[240px_1fr_280px]

    gap-0

  ">

    <nav class="hidden md:block border-r p-4">Left Nav</nav>

    <main class="p-4 md:p-6 lg:p-8">Main Content</main>

    <aside class="hidden lg:block border-l p-4">Right Sidebar</aside>

  </div>



  <!-- Footer -->

  <footer class="bg-gray-900 text-white py-8 md:py-12">

    Footer content

  </footer>

</div>

Responsive Images

Aspect Ratio Containers

<!-- Maintain aspect ratio across all sizes -->

<div class="aspect-video overflow-hidden rounded-lg">

  <img src="..." class="w-full h-full object-cover" loading="lazy" />

</div>



<!-- Responsive aspect ratio -->

<div class="aspect-square sm:aspect-video lg:aspect-[4/3] overflow-hidden">

  <img src="..." class="w-full h-full object-cover" />

</div>

Responsive Image Sizes

<!-- Art direction with picture element -->

<picture>

  <source media="(min-width: 1024px)" srcset="large.jpg" />

  <source media="(min-width: 640px)" srcset="medium.jpg" />

  <img

    src="small.jpg"

    alt="Description"

    class="w-full h-auto rounded-lg"

    loading="lazy"

  />

</picture>



<!-- Responsive srcset -->

<img

  src="image-800.jpg"

  srcset="

    image-400.jpg 400w,

    image-800.jpg 800w,

    image-1200.jpg 1200w,

    image-1600.jpg 1600w

  "

  sizes="

    (min-width: 1280px) 1200px,

    (min-width: 768px) 80vw,

    100vw

  "

  alt="Responsive image"

  class="w-full h-auto"

  loading="lazy"

/>

Responsive Typography Patterns

Heading Hierarchy

<!-- Mobile-first heading scale -->

<h1 class="

  text-2xl sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl

  font-bold leading-tight tracking-tight

">

  Main Heading

</h1>



<h2 class="

  text-xl sm:text-2xl md:text-3xl lg:text-4xl

  font-semibold leading-snug

">

  Section Heading

</h2>



<h3 class="

  text-lg sm:text-xl md:text-2xl

  font-medium

">

  Subsection Heading

</h3>

Readable Body Text

<!-- Optimal line length and spacing -->

<article class="max-w-prose mx-auto">

  <p class="

    text-base md:text-lg

    leading-relaxed md:leading-loose

    text-gray-700 dark:text-gray-300

  ">

    Body text optimized for readability with 45-75 characters per line.

  </p>

</article>



<!-- Text that balances across lines -->

<h2 class="text-balance text-2xl md:text-3xl font-bold max-w-2xl">

  This heading will balance text across lines to avoid orphans

</h2>

Mobile Navigation Patterns

Hamburger to Full Nav

<nav class="relative">

  <!-- Desktop navigation -->

  <ul class="hidden md:flex items-center gap-6">

    <li><a href="#" class="py-2 hover:text-blue-600">Home</a></li>

    <li><a href="#" class="py-2 hover:text-blue-600">Products</a></li>

    <li><a href="#" class="py-2 hover:text-blue-600">About</a></li>

    <li><a href="#" class="py-2 hover:text-blue-600">Contact</a></li>

  </ul>



  <!-- Mobile menu button -->

  <button

    class="md:hidden min-h-11 min-w-11 p-2"

    aria-expanded="false"

    aria-controls="mobile-menu"

    aria-label="Toggle navigation menu"

  >

    <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">

      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>

    </svg>

  </button>



  <!-- Mobile menu (controlled via JS) -->

  <div

    id="mobile-menu"

    class="

      md:hidden

      absolute top-full left-0 right-0

      bg-white shadow-lg border-t

      hidden

    "

  >

    <ul class="py-2">

      <li><a href="#" class="block px-4 py-3 min-h-11 hover:bg-gray-50">Home</a></li>

      <li><a href="#" class="block px-4 py-3 min-h-11 hover:bg-gray-50">Products</a></li>

      <li><a href="#" class="block px-4 py-3 min-h-11 hover:bg-gray-50">About</a></li>

      <li><a href="#" class="block px-4 py-3 min-h-11 hover:bg-gray-50">Contact</a></li>

    </ul>

  </div>

</nav>

Bottom Navigation (Mobile App Style)

<!-- Fixed bottom navigation for mobile -->

<nav class="

  fixed bottom-0 inset-x-0 z-50

  md:hidden

  bg-white border-t shadow-lg

  safe-area-pb

">

  <ul class="flex justify-around">

    <li>

      <a href="#" class="

        flex flex-col items-center

        min-h-14 min-w-14 px-3 py-2

        text-xs

        text-gray-600 hover:text-blue-600

        aria-current:text-blue-600

      ">

        <svg class="h-6 w-6 mb-1">...</svg>

        Home

      </a>

    </li>

    <li>

      <a href="#" class="flex flex-col items-center min-h-14 min-w-14 px-3 py-2 text-xs">

        <svg class="h-6 w-6 mb-1">...</svg>

        Search

      </a>

    </li>

    <li>

      <a href="#" class="flex flex-col items-center min-h-14 min-w-14 px-3 py-2 text-xs">

        <svg class="h-6 w-6 mb-1">...</svg>

        Profile

      </a>

    </li>

  </ul>

</nav>



<!-- Add padding to main content to prevent overlap -->

<main class="pb-20 md:pb-0">

  Content

</main>

Safe Area Handling (Notched Devices)

@utility safe-area-pt {

  padding-top: env(safe-area-inset-top);

}



@utility safe-area-pb {

  padding-bottom: env(safe-area-inset-bottom);

}



@utility safe-area-pl {

  padding-left: env(safe-area-inset-left);

}



@utility safe-area-pr {

  padding-right: env(safe-area-inset-right);

}



@utility safe-area-p {

  padding-top: env(safe-area-inset-top);

  padding-right: env(safe-area-inset-right);

  padding-bottom: env(safe-area-inset-bottom);

  padding-left: env(safe-area-inset-left);

}
<!-- Header that respects notch -->

<header class="sticky top-0 safe-area-pt bg-white">

  <div class="h-16 flex items-center px-4">

    Navigation

  </div>

</header>



<!-- Bottom navigation with safe area -->

<nav class="fixed bottom-0 inset-x-0 safe-area-pb bg-white border-t">

  Bottom nav

</nav>

Performance Optimization for Mobile

Lazy Loading

<!-- Native lazy loading for images -->

<img src="image.jpg" alt="..." loading="lazy" class="w-full h-auto" />



<!-- Lazy load below-fold content -->

<div class="contents" data-lazy-load>

  Heavy component loaded on demand

</div>

Content Visibility

@utility content-auto {

  content-visibility: auto;

  contain-intrinsic-size: auto 500px;

}
<!-- Skip rendering off-screen content -->

<section class="content-auto">

  Large section that may be off-screen

</section>

Reduced Data Usage

<!-- Show simpler version on slow connections -->

<picture>

  <source

    srcset="video-poster.jpg"

    media="(prefers-reduced-data: reduce)"

  />

  <img src="animated.gif" alt="..." />

</picture>

Responsive Testing Checklist

Essential Tests

  • 320px - Smallest supported width (older iPhones)
  • 375px - Modern iPhone base
  • 414px - Large phones (iPhone Plus/Max)
  • 768px - iPad portrait
  • 1024px - iPad landscape / small laptop
  • 1280px - Standard laptop
  • 1440px - Large desktop
  • 1920px - Full HD desktop

Quality Checks

  • Text remains readable at all sizes
  • Touch targets are minimum 44px on mobile
  • No horizontal scroll on any viewport
  • Images don't overflow containers
  • Navigation is accessible on all sizes
  • Forms are usable on mobile
  • Modals fit mobile screens
  • Tables have mobile alternatives
  • Performance under 3s LCP on 3G

Responsive Video Containers

Aspect Ratio Utilities for Video

Use Tailwind's aspect-* utilities to maintain correct video proportions across all screen sizes, preventing Cumulative Layout Shift (CLS):

<!-- Standard 16:9 video container -->

<div class="aspect-video overflow-hidden rounded-lg bg-black">

  <video class="w-full h-full object-cover" playsinline preload="metadata">

    <source src="video.mp4" type="video/mp4" />

  </video>

</div>



<!-- Vertical video (9:16) for mobile-first social content -->

<div class="aspect-[9/16] overflow-hidden rounded-lg bg-black max-w-sm mx-auto">

  <video class="w-full h-full object-cover" playsinline muted loop>

    <source src="reel.mp4" type="video/mp4" />

  </video>

</div>



<!-- Square video (1:1) common for social feeds -->

<div class="aspect-square overflow-hidden rounded-lg bg-black">

  <video class="w-full h-full object-cover" playsinline preload="metadata">

    <source src="square.mp4" type="video/mp4" />

  </video>

</div>



<!-- Responsive aspect ratio - vertical on mobile, widescreen on desktop -->

<div class="aspect-[9/16] sm:aspect-video overflow-hidden rounded-lg bg-black">

  <video class="w-full h-full object-contain" playsinline preload="metadata">

    <source src="video.mp4" type="video/mp4" />

  </video>

</div>

Preventing CLS with Video Placeholders

Videos without defined dimensions cause layout shift when they load. Use aspect ratio containers to reserve space:

<!-- CLS-safe video with poster and skeleton loader -->

<div class="relative aspect-video overflow-hidden rounded-lg bg-gray-900">

  <!-- Skeleton placeholder while video loads -->

  <div class="absolute inset-0 animate-pulse bg-gray-800" aria-hidden="true"></div>



  <video

    class="absolute inset-0 w-full h-full object-cover"

    poster="/thumbnails/video-poster.jpg"

    playsinline

    preload="metadata"

  >

    <source src="video.mp4" type="video/mp4" />

  </video>

</div>



<!-- Responsive grid of video thumbnails with zero CLS -->

<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">

  <div class="aspect-video overflow-hidden rounded-lg bg-gray-900">

    <video class="w-full h-full object-cover" poster="/thumb1.jpg" preload="none" playsinline></video>

  </div>

  <div class="aspect-video overflow-hidden rounded-lg bg-gray-900">

    <video class="w-full h-full object-cover" poster="/thumb2.jpg" preload="none" playsinline></video>

  </div>

  <div class="aspect-video overflow-hidden rounded-lg bg-gray-900">

    <video class="w-full h-full object-cover" poster="/thumb3.jpg" preload="none" playsinline></video>

  </div>

</div>

Full-Bleed Video on Mobile, Constrained on Desktop

<!-- Full-width on mobile, centered with max-width on desktop -->

<div class="w-full lg:max-w-4xl lg:mx-auto">

  <div class="aspect-video overflow-hidden lg:rounded-xl bg-black">

    <video class="w-full h-full object-cover" playsinline preload="metadata">

      <source src="hero.mp4" type="video/mp4" />

    </video>

  </div>

</div>



<!-- Full-bleed hero video background -->

<section class="relative w-full h-screen overflow-hidden">

  <video

    class="absolute inset-0 w-full h-full object-cover"

    autoplay muted loop playsinline

    preload="auto"

  >

    <source src="hero-bg.mp4" type="video/mp4" />

  </video>



  <!-- Content overlay with safe padding -->

  <div class="relative z-10 flex items-center justify-center h-full px-4 sm:px-8">

    <div class="text-center text-white max-w-2xl">

      <h1 class="text-3xl sm:text-4xl lg:text-6xl font-bold">Hero Title</h1>

      <p class="mt-4 text-lg sm:text-xl">Subtitle text</p>

    </div>

  </div>



  <!-- Dark overlay for text readability -->

  <div class="absolute inset-0 bg-black/40" aria-hidden="true"></div>

</section>

Safe Zone Overlays for Video UI

Video player controls and UI elements need touch-friendly sizing and proper placement:

<!-- Custom video player with touch-safe controls -->

<div class="@container relative aspect-video overflow-hidden rounded-lg bg-black group">

  <video class="w-full h-full object-cover" playsinline preload="metadata">

    <source src="video.mp4" type="video/mp4" />

  </video>



  <!-- Play/Pause overlay - centered, touch-friendly -->

  <button class="

    absolute inset-0 flex items-center justify-center

    bg-black/0 group-hover:bg-black/20 transition-colors

  ">

    <span class="

      w-16 h-16 sm:w-20 sm:h-20

      flex items-center justify-center

      rounded-full bg-white/90

      shadow-lg

    ">

      <svg class="w-8 h-8 sm:w-10 sm:h-10 text-gray-900 ml-1" viewBox="0 0 24 24" fill="currentColor">

        <path d="M8 5v14l11-7z"/>

      </svg>

    </span>

  </button>



  <!-- Bottom controls bar - respects touch targets -->

  <div class="

    absolute bottom-0 inset-x-0

    bg-gradient-to-t from-black/80 to-transparent

    p-3 sm:p-4

    flex items-center gap-3

    opacity-0 group-hover:opacity-100 transition-opacity

  ">

    <!-- Progress bar - tall enough for touch -->

    <div class="flex-1 h-1 bg-white/30 rounded-full cursor-pointer">

      <div class="h-full w-1/3 bg-white rounded-full relative">

        <span class="absolute right-0 top-1/2 -translate-y-1/2 w-4 h-4 bg-white rounded-full -mr-2"></span>

      </div>

    </div>



    <!-- Time display -->

    <span class="text-white text-xs sm:text-sm tabular-nums shrink-0">1:23 / 4:56</span>



    <!-- Fullscreen button - touch-friendly minimum size -->

    <button class="min-h-11 min-w-11 flex items-center justify-center text-white">

      <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">

        <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>

      </svg>

    </button>

  </div>

</div>

Container Queries for Adaptive Video Players

Video player components that adapt their layout based on container size --- useful when the same player appears in a sidebar, main content area, or modal:

<!-- Video player that adapts to its container -->

<div class="@container">

  <div class="

    flex flex-col @lg:flex-row

    gap-4 @lg:gap-6

    bg-gray-950 rounded-xl overflow-hidden

  ">

    <!-- Video area -->

    <div class="

      w-full @lg:flex-1

      aspect-video

      overflow-hidden

    ">

      <video class="w-full h-full object-cover" playsinline preload="metadata">

        <source src="video.mp4" type="video/mp4" />

      </video>

    </div>



    <!-- Info panel - below video on narrow, beside on wide -->

    <div class="

      p-4 @lg:p-6

      @lg:w-80 @lg:overflow-y-auto

      text-white

    ">

      <h3 class="text-base @lg:text-lg font-semibold">Video Title</h3>

      <p class="text-sm text-gray-400 mt-2 line-clamp-2 @lg:line-clamp-none">

        Video description that shows more text when the container is wider...

      </p>



      <!-- Related videos - hidden in narrow containers -->

      <div class="hidden @xl:block mt-6 space-y-3">

        <h4 class="text-sm font-medium text-gray-300">Related</h4>

        <div class="space-y-2">

          <div class="flex gap-3">

            <div class="w-28 aspect-video bg-gray-800 rounded shrink-0"></div>

            <div class="text-xs text-gray-400">Related Video 1</div>

          </div>

        </div>

      </div>

    </div>

  </div>

</div>

Best Practices Summary

Practice

Implementation

Mobile-first utilities

Unprefixed first, then sm:, md:, lg:

Touch targets

min-h-11 min-w-11 (44px minimum)

Fluid typography

clamp(min, preferred, max) with rem + vw

Fluid spacing

clamp() for padding and margins

Container queries

@container for component responsiveness

Safe areas

env(safe-area-inset-*) for notched devices

Readable text

max-w-prose (65ch) and leading-relaxed

Lazy loading

loading="lazy" on below-fold images

Touch spacing

gap-3 (12px) minimum between targets

Viewport meta

width=device-width, initial-scale=1

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card