Media Queries
Toned supports responsive styling through breakpoints defined in your system configuration. Token values can be overridden at specific breakpoints, and the system handles media query generation automatically.
Using Breakpoints in Stylesheets
Use an @media key that names a breakpoint to create a responsive override block inside any element definition:
const layoutStyles = stylesheet({
Root: {
paddingX: 2,
flexLayout: 'column',
'@media md': {
paddingX: 4,
flexLayout: 'row',
},
'@media lg': {
paddingX: 6,
},
},
})Breakpoint blocks support the same token properties and $style escape hatch as the base element definition. Properties set inside a breakpoint block override the base values when the viewport matches.
'@media md' can also be written as the builder call [q.media('md')], and the compatibility short key '@md' declares the same rule. Container and platform conditions follow the same pattern. See Conditions and selectors for every form.
Root-Level Breakpoints
Breakpoints can be declared at the root level of a stylesheet to apply overrides across multiple elements at once. This is useful when a layout change at a given viewport affects several elements simultaneously:
const cardStyles = stylesheet({
Root: {
paddingX: 2,
flexLayout: 'column',
},
Title: {
$kind: 'text',
typography: 'heading-3',
},
Sidebar: {
display: 'none',
},
// At medium viewports, adjust multiple elements together
'@media md': {
Root: { paddingX: 4, flexLayout: 'row' },
Title: { typography: 'heading-2' },
Sidebar: { display: 'flex' },
},
'@media lg': {
Root: { paddingX: 6 },
},
})Root-level and element-level breakpoints can be mixed freely. They produce the same result — root-level is shorthand for applying overrides to several elements under the same breakpoint.
Breakpoints in Variants
Responsive overrides work inside variant blocks too, letting you combine conditional and responsive styling. Breakpoints can be set on individual elements within a variant:
import type { Variants } from '@toned/core'
const styles = stylesheet({
Root: { paddingX: 2, flexLayout: 'column', gap: 2 },
}).variants(($: Variants<{ layout: 'grid' | 'list' }>) => ({
[$.layout('grid')]: {
Root: {
'@media md': {
flexLayout: 'row',
flexWrap: 'wrap',
},
'@media lg': {
gap: 4,
},
},
},
}))Using Breakpoints Inline
The t utility accepts the same @media blocks, so a one-off style can be responsive without defining a stylesheet:
import { t } from '@toned/systems/base'
function Panel() {
return <div {...t({ paddingX: 2, '@media md': { paddingX: 4 } })} />
}t is the compatibility inline helper: it reads the installed configuration, and its blocks compile to CSS custom properties, so they apply only to web output with CSS media enabled. They are also one level deep, so the root-level and variant forms shown above apply to stylesheets only.
Give the property a base value, as paddingX: 2 does above. A block with no base compiles to a fallback-less chain, so below the breakpoint the property resolves to its initial value rather than to whatever a class or an inherited rule set.
Declaring Breakpoints
The examples above use the base system's breakpoints. In your own system, declare named viewport thresholds in logical pixels:
import { defineSystem } from '@toned/core'
export const ui = defineSystem({
id: 'responsive',
tokens: {},
conditions: {
media: {
xs: 0, // mobile-first default
sm: 480, // small phones landscape
md: 768, // tablets
lg: 992, // small desktops
xl: 1200, // large desktops
},
},
})How Breakpoints Apply
The renderer given to TonedProvider decides how a breakpoint is evaluated; the stylesheet is the same everywhere.
Web
A web renderer uses the CSS generated at build time, where each breakpoint is a real @media rule. Matching happens in the browser, with no JavaScript listener or React render:
import 'virtual:toned.css'
import manifest from 'virtual:toned.manifest'
import { createWebRenderer } from '@toned/core/server'
import { TonedProvider } from '@toned/react'
import { webHost } from '@toned/react/hosts/web'
import { ui } from './system.ts'
const renderer = createWebRenderer(ui, { manifest })
export function App({ children }: { children: React.ReactNode }) {
return (
<TonedProvider renderer={renderer} host={webHost}>
{children}
</TonedProvider>
)
}React Native
A native renderer evaluates a stylesheet's breakpoints against the viewport width the native host reports, and patches the mounted hosts when it changes. See the React Native guide for the host capabilities this needs.
Inline t blocks have no native equivalent: they compile to CSS custom properties, which only a browser reads. Without CSS media an inline @ block is dropped, the base token value still applies, and a development-only warning explains why. Where you need responsive styling on React Native, use stylesheet with useStyles instead.