useMedia

Respond to different screen sizes

useMedia reads the same named media rules that style props use for responsive conditions.

Define those rules in the media object of your tamagui.config.ts:

export default createTamagui({
media: {
xs: { maxWidth: 660 },
gtXs: { minWidth: 660 + 1 },
sm: { maxWidth: 860 },
gtSm: { minWidth: 860 + 1 },
md: { maxWidth: 980 },
gtMd: { minWidth: 980 + 1 },
lg: { maxWidth: 1120 },
gtLg: { minWidth: 1120 + 1 },
short: { maxHeight: 820 },
tall: { minHeight: 820 },
hoverNone: { hover: 'none' },
touch: { pointer: 'coarse' },
},
})

Name them as you like. We use sm, md, lg, and gtSm, where gt means “greater than”.

Order matters: items defined further down override items before them. Here xs is the weakest and each entry overrides the ones above it.

Tamagui converts each entry to a media query, turning camelCase into hyphen-case and wrapping it in @media().

Inline props

Use media names as typed object keys or string modifiers on the style prop:

import { useState } from 'react'
import { Button, XStack } from 'tamagui' // note: design system can use @tamagui/core
export default () => {
const [x, setX] = useState(0)
return (
<XStack backgroundColor={`red gtSm:blue gtMd:${x > 0.5 ? 'green' : 'yellow'}`} >
<Button onPress={() => setX(Math.random())}>Hello</Button>
</XStack>
)
}

In this example we are doing mobile-first design, where clauses override the base as the viewport gets wider. The ternary payload in gtMd: is extractable with Tamagui and still outputs simple CSS.

Hooks

import { Button, XStack, useMedia } from 'tamagui' // note: design system can use @tamagui/core
export default () => {
const media = useMedia()
return (
<XStack // can be used as a ternary backgroundColor={media.sm ? 'red' : 'blue'} // can be used as a spread {...(media.lg && { x: 10, y: 10, })} >
<Button>Hello</Button>
</XStack>
)
}

As long as all of your usages of useMedia are extractable, Tamagui will actually generate your CSS and then fully remove the hook from the output code. You can check this by adding // debug to the top of your component.

You can also use useMedia for logic outside of styles. If an expression cannot be extracted, Tamagui falls back to runtime execution.

Tamagui tracks which keys are accessed, and only updates if the media query matching that key changes.

Limitations

The useMedia hook uses proxies so it can track which keys you are accessing and only re-render components that need re-rendering based on those keys. The Tamagui compiler also understands straightforward uses of the hook during compile-time and can remove it entirely when targeting the web, in favor of CSS.

  • The proxied object returned by useMedia is not iterable, and does not support in checks or Object.keys.
  • Write const media = useMedia() and access keys directly, like media.sm, for best results with the compiler. The compiler supports destructuring without renaming.