Responsive
Tosui supports responsive styling through breakpoint-aware props. All Box style props accept either a single value or a responsive object.
Breakpoints
Tosui uses a mobile-first breakpoint system:
| Key | Min Width | Typical Device |
|---|---|---|
base | 0px | Mobile phones |
sm | 640px | Large phones |
md | 768px | Tablets |
lg | 1024px | Laptops |
xl | 1280px | Desktops |
2xl | 1536px | Large displays |
Simple vs Responsive Values
All style props accept either a simple value or a responsive object:
// Simple - applies to all screen sizes
<Box p={4} />
// Responsive - changes at breakpoints
<Box p={{ base: 2, md: 4, lg: 6 }} />
The responsive version produces:
- Mobile (base): 8px padding
- Tablet (md): 16px padding
- Desktop (lg): 24px padding
Mobile-First Cascade
You only need to specify breakpoints where values change. Smaller breakpoints cascade up:
// Only specify base and lg
<Box p={{ base: 2, lg: 6 }} />
This produces:
- base: 8px (specified)
- sm: 8px (inherits from base)
- md: 8px (inherits from base)
- lg: 24px (specified)
- xl: 24px (inherits from lg)
- 2xl: 24px (inherits from lg)
Responsive Props
All Box style props support responsive values:
| Category | Props |
|---|---|
| Spacing | p, px, py, pt, pr, pb, pl, m, mx, my, mt, mr, mb, ml, gap, gapRow, gapColumn |
| Sizing | w, h, minW, maxW, minH, maxH |
| Layout | display, position, overflow, overflowX, overflowY, zIndex |
| Flexbox | flexDirection, justifyContent, alignItems, alignSelf, flexWrap, flex, flexGrow, flexShrink, flexBasis |
| Grid | gridTemplateColumns, gridTemplateRows, justifySelf |
| Typography | fontSize, fontFamily, fontWeight, lineHeight |
| Colors | color, bg, borderColor |
| Borders | border, borderTop, borderRight, borderBottom, borderLeft, borderX, borderY, borderStyle |
| Roundness | rounded, roundedTop, roundedBottom, roundedLeft, roundedRight, roundedTopLeft, roundedTopRight, roundedBottomLeft, roundedBottomRight |
| Effects | shadow, opacity |
| Interactions | cursor, pointerEvents, userSelect |
| Text | textAlign, whiteSpace |
| Inset | top, right, bottom, left, inset, insetX, insetY |
Common Patterns
Responsive Padding
<Box p={{ base: 4, md: 6, lg: 8 }}>
Content with increasing padding on larger screens
</Box>
Show/Hide Elements
// Hidden on mobile, visible on tablet+
<Box display={{ base: "none", md: "block" }}>
Desktop navigation
</Box>
// Visible on mobile, hidden on tablet+
<Box display={{ base: "block", md: "none" }}>
Mobile menu button
</Box>
Responsive Flex Direction
// Stack vertically on mobile, horizontally on tablet+
<Box
display="flex"
flexDirection={{ base: "column", md: "row" }}
gap={4}
>
<Box>First</Box>
<Box>Second</Box>
</Box>
Responsive Grid
<Box
display="grid"
gridTemplateColumns={{
base: "1fr",
md: "1fr 1fr",
lg: "1fr 1fr 1fr"
}}
gap={4}
>
<Box>Card 1</Box>
<Box>Card 2</Box>
<Box>Card 3</Box>
</Box>
Responsive Typography
<Heading size={{ base: "xl", md: "2xl", lg: "3xl" }}>
Scales with viewport
</Heading>
Responsive Width
// Using spacing multipliers (recommended)
<Box w={{ base: "100%", md: "50%", lg: "33%" }}>
Responsive width container
</Box>
// CSS values work for percentages and viewport units
<Box w={{ base: "100%", md: "400px" }}>
Full width on mobile, fixed on tablet+
</Box>
Layout Components
Layout components (Stack, HStack, VStack, Flex, Grid) accept responsive values on their convenience props — not just on inherited Box props.
Responsive Stack Direction
<Stack
direction={{ base: "column", md: "row" }}
gap={{ base: 4, lg: 8 }}
align={{ base: "stretch", md: "center" }}
>
<Box>Sidebar</Box>
<Box>Main Content</Box>
</Stack>
This is equivalent to using VStack on mobile and HStack on desktop.
Responsive Flex
<Flex
direction={{ base: "column", md: "row" }}
wrap={{ base: "nowrap", lg: "wrap" }}
justify={{ base: "center", md: "space-between" }}
gap={4}
>
<Box>Item 1</Box>
<Box>Item 2</Box>
</Flex>
Responsive Grid Alignment
<Grid
columns={{ base: "1fr", md: "repeat(3, 1fr)" }}
justify={{ base: "center", lg: "start" }}
gap={4}
>
<Box>Card 1</Box>
<Box>Card 2</Box>
<Box>Card 3</Box>
</Grid>
- Stack —
direction,align,justify,wrap,gap - HStack / VStack —
align,justify,wrap,gap - Flex —
direction,align,justify,wrap,alignSelf,gap - Grid —
columns,rows,justify,align,justifyContent,alignContent,gap
Responsive State Styling
State props (_hover, _focus, _active, _disabled) also accept responsive values:
<Box
bg="surface"
_hover={{
bg: { base: "primary-subtle", md: "primary-default" }
}}
>
Different hover effect by screen size
</Box>
See the State Styling guide for more details.
Best Practices
- Design mobile-first: Start with base values, then add larger breakpoints
- Minimize breakpoints: Only add breakpoints where the layout actually needs to change
- Use semantic breakpoints: Think "tablet and up" (
md), not "768px" - Test all sizes: Verify layouts at each breakpoint you use
- Prefer design tokens: Use spacing multipliers (
p={4}) over raw values (p="16px") when possible