Responsive design
Adapt layouts across screen sizes with Reva's breakpoint scale, mobile-first utilities, and the responsive-prop API on layout primitives.
Reva is mobile-first. Unprefixed utilities apply at every width; breakpoint
prefixes (md:, lg:, …) layer overrides on from that width up. Design the
base case for the smallest screen, then add breakpoints to adapt as the viewport
grows.
// Stacks on phones, switches to a row from md (1024px) up.
<div className="flex flex-col md:flex-row">…</div>The breakpoints are a single, token-driven scale — defined once in
@reva/design-tokens (core/foundation/breakpoint.json →
--breakpoint-*) and shared by every web app and Figma. There is no separate
per-app breakpoint set.
The breakpoints
| Prefix | Min-width | Token | Typical target |
|---|---|---|---|
xs: | 480px | 30rem | Large phones in landscape |
sm: | 768px | 48rem | Tablets in portrait |
md: | 1024px | 64rem | Tablets in landscape, small laptops |
lg: | 1280px | 80rem | Laptops and desktops |
xl: | 1536px | 96rem | Large desktops |
2xl: | 1920px | 120rem | Full HD displays |
3xl: | 2560px | 160rem | Ultra-wide / QHD+ |
The scale aligns with Tailwind's defaults — Reva's sm–xl carry Tailwind's
md–2xl pixel values (768 / 1024 / 1280 / 1536) — extended with an xs step
below for finer small-screen control and 2xl / 3xl above for large and
ultra-wide displays. Reach for 2xl for typical large-desktop layouts; reserve
3xl for genuinely ultra-wide canvases. See the design-tokens
Breakpoints page for the live token values.
Working mobile-first
Every responsive utility is a min-width rule. Style the base (unprefixed) for small screens, then override upward:
import { Container, Grid } from "@reva/ui";
// 1 column on phones → 2 from sm → 3 from lg.
<Container>
<Grid columns={{ default: 1, sm: 2, lg: 3 }} gap={4}>
{cards}
</Grid>
</Container>Container already applies responsive gutters (px-6 sm:px-8 xl:px-10), so page
content gets breakpoint-aware padding without any extra classes.
Responsive props
The layout primitives accept responsive values directly — pass an object
keyed by breakpoint instead of a static value. The default key is the base
(unprefixed) case; every other key is a breakpoint from the scale above.
import { Stack, Flex, Grid } from "@reva/ui";
// Vertical on phones, horizontal from md up; tighter gap below lg.
<Stack direction={{ default: "vertical", md: "horizontal" }} gap={{ default: 2, lg: 4 }} />
// Flex direction flips at a breakpoint.
<Flex direction={{ default: "column", lg: "row" }} />
// Grid grows its column count as the viewport widens.
<Grid columns={{ default: 1, sm: 2, xl: 4 }} gap={6} />Which primitives expose responsive props:
| Component | Responsive props |
|---|---|
Stack / HStack / VStack | direction, gap |
Flex | direction, gap |
Grid | columns, rows, gap |
The same props also accept container-query keys (@sm, @md, …) to respond
to the width of a containing element rather than the viewport — see
Container queries for when to reach for those.
Typography stays static
Heading and Text size is not responsive by design — a single value, not
a per-breakpoint object. For fluid hero type, pair a base size with a CSS
clamp() rather than stacking breakpoint text utilities:
// Fluid headline that scales smoothly between 2rem and 3rem.
<Heading size="5xl" style={{ fontSize: "clamp(2rem, 1.5rem + 2.5vw, 3rem)" }}>
Intelligent orchestration for modern wealth
</Heading>The static size props on other components (Button, Input, Badge, …) are
likewise fixed per instance — choose the size that fits each context rather than
varying it by breakpoint.