react-tailwind-media
v1.0.3
Published
Get the media size in a notation which matches Tailwind. SSR, zero CLS, one source of truth.
Maintainers
Readme
react-tailwind-media
Get the media size in a notation which matches Tailwind CSS. SSR-ready, zero CLS, one source of truth. 📱💻
A lightweight React hook that provides responsive breakpoint information matching Tailwind CSS's responsive design system. Perfect for conditional rendering based on screen size with full SSR support.
Features
- 🎯 Tailwind CSS Compatible - Breakpoints match Tailwind's responsive design system
- 🚀 Zero CLS - No layout shift during hydration
- 🔄 SSR Ready - Works perfectly with Next.js, Remix, and other SSR frameworks
- 📦 Tiny Bundle - Minimal footprint with tree-shaking support
- 🎣 React 18 Ready - Built with
useSyncExternalStorefor optimal performance - 📱 Real-time Updates - Automatically updates on window resize
Installation
npm install react-tailwind-mediaUsage
Basic Usage
import { useTailwindBreakpoints } from 'react-tailwind-media';
function MyComponent() {
const { sm, md, lg, xl, current } = useTailwindBreakpoints();
return (
<div>
<p>Current breakpoint: {current}</p>
{lg ? (
<div>Large screen content</div>
) : (
<div>Mobile content</div>
)}
</div>
);
}Conditional Rendering
import { useTailwindBreakpoints } from 'react-tailwind-media';
function ResponsiveLayout() {
const { mdUp, lgOnly, baseOnly } = useTailwindBreakpoints();
return (
<>
{baseOnly && <MobileOnlyComponent />}
{mdUp && <TabletAndDesktopComponent />}
{lgOnly && <DesktopOnlyComponent />}
</>
);
}Optional pre-hydrate hint
If you want to avoid a layout shift during hydration, set <html data-bp> + a cookie via beforeInteractive, so SSR → first paint → hydrate stay in sync. 🚀
// app/layout.tsx (Next.js App Router)
import Script from "next/script";
import { cookies } from "next/headers";
function pickBP() {
const c = cookies().get("bp")?.value as "base"|"sm"|"md"|"lg"|"xl"|"2xl"|undefined;
return c ?? "base"; // SSR default
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
const ssrBP = pickBP();
return (
<html lang="en" data-bp={ssrBP}>
<body>
{/* Runs BEFORE React hydrates */}
<Script id="bp-hint" strategy="beforeInteractive">
{`
(function(){
try{
var bp="base";
if (window.matchMedia("(min-width:1536px)").matches) bp="2xl";
else if (window.matchMedia("(min-width:1280px)").matches) bp="xl";
else if (window.matchMedia("(min-width:1024px)").matches) bp="lg";
else if (window.matchMedia("(min-width:768px)").matches) bp="md";
else if (window.matchMedia("(min-width:640px)").matches) bp="sm";
document.documentElement.setAttribute("data-bp", bp);
document.cookie = "bp="+bp+"; Path=/; Max-Age=600; SameSite=Lax";
}catch(_){}
})();
`}
</Script>
{children}
</body>
</html>
);
}API Reference
useTailwindBreakpoints()
Returns a state object with breakpoint information:
type State = {
// Current breakpoint
current: 'base' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
// Tailwind-style flags (min-width)
sm: boolean; // >= 640px
md: boolean; // >= 768px
lg: boolean; // >= 1024px
xl: boolean; // >= 1280px
'2xl': boolean; // >= 1536px
_2xlUp: boolean; // Alias for 2xl (valid JS identifier)
// Range flags (exact breakpoint only)
baseOnly: boolean; // < 640px
smOnly: boolean; // 640px - 767px
mdOnly: boolean; // 768px - 1023px
lgOnly: boolean; // 1024px - 1279px
xlOnly: boolean; // 1280px - 1535px
// Up flags (current breakpoint and larger)
mdUp: boolean; // >= 768px
lgUp: boolean; // >= 1024px
xlUp: boolean; // >= 1280px
};Breakpoints
Matches Tailwind CSS breakpoints:
| Breakpoint | Min Width | Description |
|------------|-----------|-------------|
| base | 0px | Mobile |
| sm | 640px | Small |
| md | 768px | Medium |
| lg | 1024px | Large |
| xl | 1280px | Extra Large |
| 2xl | 1536px | 2X Large |
SSR Support
This library is fully SSR-compatible. During server-side rendering, all breakpoints default to false and current defaults to 'base'. The state hydrates correctly on the client without causing layout shifts.
TypeScript
Full TypeScript support included with proper type definitions.
import type { BPs, State } from 'react-tailwind-media';