useMedia

Designing for different size screens.

Define your media 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: { minWidth: 980 },
gtMd: { minWidth: 980 + 1 },
lg: { minWidth: 1120 },
gtLg: { minWidth: 1120 + 1 },
short: { maxHeight: 820 },
tall: { minHeight: 820 },
hoverNone: { hover: 'none' },
pointerCoarse: { pointer: 'coarse' },
},
});

Note: Choose the naming convention you prefer. We use sm, md, lg and gtSm etc.

Behind the scenes, we convert this object syntax into media query syntax with a simple loop over your object, turning camelCase into hyphen-case, and adding @media() around it. On native, we use the excellent @expo/match-media.

Usage

Now in any component you may import and use useMedia or $ prefixed media prop styles.

Inline props

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

In this example we are doing mobile-first design, where the base props will be overridden as the viewport gets wider. Notice the ternary logic in $gtMd: this is extractable with Tamagui, and will still output simple CSS with no leftover style props your component's render function.

Hooks

import { useMedia, XStack, Button } 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.

Of course, you may sometimes use useMedia for other purposes than styling. In fact, that's the nice part about Tamagui - if it can't extract, it always falls back to runtime gracefully.

Tamagui runtime useMedia usage will track which keys are accessed, and only update if the media query matching that key updates. This granular updating is nice for performance.