Skip to main content

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:

KeyMin WidthTypical Device
base0pxMobile phones
sm640pxLarge phones
md768pxTablets
lg1024pxLaptops
xl1280pxDesktops
2xl1536pxLarge 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:

CategoryProps
Spacingp, px, py, pt, pr, pb, pl, m, mx, my, mt, mr, mb, ml, gap, gapRow, gapColumn
Sizingw, h, minW, maxW, minH, maxH
Layoutdisplay, position, overflow, overflowX, overflowY, zIndex
FlexboxflexDirection, justifyContent, alignItems, alignSelf, flexWrap, flex, flexGrow, flexShrink, flexBasis
GridgridTemplateColumns, gridTemplateRows, justifySelf
TypographyfontSize, fontFamily, fontWeight, lineHeight
Colorscolor, bg, borderColor
Bordersborder, borderTop, borderRight, borderBottom, borderLeft, borderX, borderY, borderStyle
Roundnessrounded, roundedTop, roundedBottom, roundedLeft, roundedRight, roundedTopLeft, roundedTopRight, roundedBottomLeft, roundedBottomRight
Effectsshadow, opacity
Interactionscursor, pointerEvents, userSelect
TexttextAlign, whiteSpace
Insettop, 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>
  • Stackdirection, align, justify, wrap, gap
  • HStack / VStackalign, justify, wrap, gap
  • Flexdirection, align, justify, wrap, alignSelf, gap
  • Gridcolumns, 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

  1. Design mobile-first: Start with base values, then add larger breakpoints
  2. Minimize breakpoints: Only add breakpoints where the layout actually needs to change
  3. Use semantic breakpoints: Think "tablet and up" (md), not "768px"
  4. Test all sizes: Verify layouts at each breakpoint you use
  5. Prefer design tokens: Use spacing multipliers (p={4}) over raw values (p="16px") when possible