Skip to content

Tailwind Responsive Patterns

Beyond basic breakpoint prefixes, Tailwind supports more advanced responsive strategies like container queries and range-based breakpoints. This lesson covers patterns for handling more complex, real-world responsive requirements.

What Are Advanced Responsive Patterns?

Viewport-based breakpoints (md:, lg:) work well for page-level layout, but component-level responsiveness, where a component should adapt based on its own container's width, not the whole viewport, requires container queries instead.

Tailwind also supports max-* breakpoint variants and range combinations, letting you apply styles only between two specific breakpoints instead of "this breakpoint and up".

<div class="@container">
  <div class="flex flex-col @md:flex-row">
    Adapts based on the container's width, not the viewport.
  </div>
</div>

@container marks the wrapper as a query container; @md:flex-row responds to that container's width, not the page's.

Advanced Responsive Syntax

class="@container"
class="@md:flex-row"
class="max-md:hidden"
class="md:max-lg:block"
  • @container on a parent enables container query variants for its descendants.
  • @md:, @lg:, etc. respond to the nearest container's width, not the viewport.
  • max-{breakpoint}: applies a utility only below that breakpoint.
  • Combine md:max-lg: to apply a utility only within a specific breakpoint range.

Responsive Patterns Cheatsheet

Advanced responsive techniques beyond basic breakpoint prefixes.

Pattern Example Use Case
Container query @container + @md:flex-row Component adapts to its own container, not the viewport
Max-width variant max-md:hidden Hides an element only below the md breakpoint
Breakpoint range md:max-lg:block Applies only between md and lg
Named container @container/sidebar + @sm/sidebar:block Target a specific named container ancestor
Arbitrary breakpoint min-[900px]:flex One-off custom viewport breakpoint
Print styles print:hidden Hides an element only when printing
Orientation landscape:flex-row Responds to device orientation
Reduced motion motion-reduce:transition-none Respects the user's reduced motion preference

Why Container Queries Matter

A component embedded in both a wide main content area and a narrow sidebar can't respond correctly using viewport breakpoints alone, since the viewport size is the same in both places. Container queries let the exact same component adapt based on the space it actually has.

<div class="@container">
  <div class="grid @sm:grid-cols-2 @lg:grid-cols-3 gap-4">
    <!-- Card items -->
  </div>
</div>

This same card grid component automatically shows more columns only when its own container, not the page, is wide enough.

max-* and Range-Based Variants

Sometimes you need a style to apply only up to a certain breakpoint, or only within a narrow range between two breakpoints, rather than "this size and up", which is what unprefixed and min-width-based prefixes normally express.

<div class="max-lg:hidden">
  Only visible at lg breakpoint and above.
</div>

<div class="md:max-lg:flex hidden">
  Only visible between md and lg (exclusive of lg and up).
</div>

Other Media Feature Variants

Tailwind includes variants for media features beyond simple width, like print styles, orientation, and the user's reduced-motion accessibility preference.

<div class="print:hidden">Hidden when printing this page.</div>
<div class="motion-reduce:transition-none transition-transform">
  Skips the transform transition for users who prefer reduced motion.
</div>

Respecting Reduced Motion Preferences

Some users experience discomfort from animated motion. The motion-reduce: variant lets you disable or simplify animations for users who've set that preference at the OS level.

  • Use motion-reduce:transition-none or motion-reduce:animate-none on decorative animations.
  • Keep essential state-change feedback even when disabling motion, just make it instant instead of animated.
  • Test your site with "reduce motion" enabled in your OS accessibility settings.

Common Mistakes

  • Using viewport breakpoints for a component that's reused in containers of very different widths, instead of container queries.
  • Forgetting @container on the ancestor, which silently makes @md: variants do nothing.
  • Overcomplicating a layout with range-based variants when a simpler mobile-first approach would work fine.
  • Ignoring motion-reduce: entirely, even for sites with prominent animated transitions.
  • Not testing print styles (print:hidden) for pages that are commonly printed, like invoices or receipts.

Key Takeaways

  • Container queries (@container, @md:) let components respond to their own container's width, not the viewport.
  • max-{breakpoint}: and combined range variants apply styles only below or between specific breakpoints.
  • Tailwind also supports variants for print, orientation, and reduced motion preferences.
  • Container queries solve responsiveness for reusable components placed in varying layout contexts.
  • Always test animation-heavy interfaces with motion-reduce: and real reduced-motion settings enabled.

Pro Tip

Reach for container queries specifically for reusable components (cards, widgets) that get placed in different-width contexts across your app; for whole-page layout, viewport breakpoints are still usually the simpler, correct choice.