Styling
Style props, conditional values, and the modifiers that control them
Tamagui uses style props across all components. Every element accepts React Native and web styles, with unified support for responsive, theme, and pseudo-state conditions.
padding, borderRadius, and backgroundColor are style props. "4" and
"lg" are tokens, background is a theme key, and md: and hover: are
modifiers. That is the whole grammar. The same props go on View, Text,
every other component, and the second argument of
styled().
Every style prop takes its value as a string or an object. Strings fit the base value and its conditions into one short read:
Objects spell the same thing with keys, and stay fully typed:
Use strings for short, mostly static values — a prop with one or two
conditions, written inline. They exist so the common case stays terse and
readable. Use objects when the value is a number (numbers skip token lookup,
so padding={16} is always 16 pixels), when conditions stack up, or when you
build the value in code from variables and spreads — objects are real values,
so TypeScript checks every token and modifier as you type. Both spellings take
the same values and modifiers and render identically, so mix them per prop as
needed. The Conditional values section below details each spelling.
Values
A style value is one of:
| Value | Example | Resolves to |
|---|---|---|
| Number | padding={16} | 16 pixels on every platform |
| Pixel string | padding="16px" | An exact pixel value, even when a token has the same name |
| Token | padding="4", borderRadius="lg" | The token from that prop’s category |
| Theme key | color="color-11" | The active theme’s value, updating when the theme changes |
| CSS value | display="flex", boxShadow="0 2px 8px shadow-3" | Passed through on web and converted on native |
rem | padding="1rem" | Scaled by the user’s font size on native |
- Value
- Number
- Example
padding={16}- Resolves to
- 16 pixels on every platform
- Value
- Pixel string
- Example
padding="16px"- Resolves to
- An exact pixel value, even when a token has the same name
- Value
- Token
- Example
padding="4",borderRadius="lg"- Resolves to
- The token from that prop’s category
- Value
- Theme key
- Example
color="color-11"- Resolves to
- The active theme’s value, updating when the theme changes
- Value
- CSS value
- Example
display="flex",boxShadow="0 2px 8px shadow-3"- Resolves to
- Passed through on web and converted on native
- Value
rem- Example
padding="1rem"- Resolves to
- Scaled by the user’s font size on native
Design system covers where tokens and theme keys come from. Style props lists every prop, including the ones that only render on web.
Conditional values
Every style prop takes conditions in two spellings, a string of clauses or a flat object. These render the same thing:
String
Typed
The object keys are the same modifiers the string uses, with default for the
base value. There is no mode to pick, and you can mix them per prop in one
component:
Strings are shorter for one or two conditions. Objects work better when the values are numbers, when the conditions stack up, or when you build the value in code. Both compile to identical CSS.
An object only counts as conditional when it has a default key or its first
key is a valid modifier. A plain value object like
shadowOffset={{ width: 0, height: 2 }} is left alone.
Font size and line height values
Numeric lineHeight authored in Tamagui styles is a font-size ratio on web and
native. A numeric string has the same ratio meaning when it is not a configured
font-token name. An explicit px string stays absolute. Values are never inferred
from magnitude, so lineHeight={24} means 24 times the effective font size and
lineHeight="24px" means 24 pixels.
Font configuration keeps a separate compatibility contract. Numeric
lineHeight entries remain absolute pixels. Use a numeric string for a relative
font token and a px string for an explicit absolute token:
On native, Tamagui can resolve a ratio from the effective font size inherited through Tamagui text. This inheritance continues through intervening Tamagui Views, as it does on web. When a Tamagui text boundary sits below a raw React Native or third-party text parent, pass the effective font size at that boundary because Tamagui cannot inspect typography held only by the native host tree.
If a native ratio has no known font size, Tamagui explicitly sets fontSize={14}
and calculates the line height from 14. This also applies below a raw native text
parent, so pass its font size at the Tamagui boundary to preserve the glyph size.
Modifiers
Every modifier applies to just the property carrying it. They fall into five groups:
| Group | Modifiers | Example |
|---|---|---|
| State | hover:, press:, focus:, focus-visible:, focus-within:, disabled: | scale="press:0.98" |
| Screen size | any media name from your config, such as sm: or max-md: | padding="4 md:8" |
| Theme | dark:, light:, or a top-level theme name | color="dark:white" |
| Platform | web:, native:, ios:, android: | paddingTop="ios:12" |
| Parent | group-hover:, group-press:, group-focus:, @sm: container queries | color="group-hover:white" |
- Group
- State
- Modifiers
hover:,press:,focus:,focus-visible:,focus-within:,disabled:- Example
scale="press:0.98"- Group
- Screen size
- Modifiers
- any media name from your config, such as
sm:ormax-md: - Example
padding="4 md:8"- Group
- Theme
- Modifiers
dark:,light:, or a top-level theme name- Example
color="dark:white"- Group
- Platform
- Modifiers
web:,native:,ios:,android:- Example
paddingTop="ios:12"- Group
- Parent
- Modifiers
group-hover:,group-press:,group-focus:,@sm:container queries- Example
color="group-hover:white"
Modifiers stack. sm:hover:purple applies on hover at the sm breakpoint.
When several clauses match, the most specific one wins.
Flat conditional values has the full precedence rules and
grammar.
States
Add state clauses directly to the property they change:
hover:: while hovering (web only, maps to CSS:hover)press:: while pressingfocus:: while focused (maps to CSS:focus)focus-visible:: while keyboard-focused (maps to CSS:focus-visible)focus-within:: while a child has focus (maps to CSS:focus-within)disabled:: whiledisabled={true}
hover: is web only. focus:, focus-visible:, and focus-within: map to the
matching CSS pseudo-classes on web.
Enter and exit
For mount and unmount animations, enter: is the value the property animates
from on mount, and exit: is the value it animates to on unmount:
See Animations.
Screen size
Media queries come from createTamagui({ media }). Each name is a modifier on
native and web:
Theme and platform
Theme modifiers target top-level themes. With light and light_subtle
defined, only light can be targeted. Platform modifiers cover ios,
android, web, and native:
Groups
Mark a parent with group and children can react to its state:
The states are hover (web only), press, and focus. Name a group to
target it from further down:
Inner turns blue when the card group is hovered. Sibling turns green
when its nearest group is hovered. For completion on named groups, declare
them next to your config types:
Container queries
Add container to a group and children can respond to the parent’s size,
using the same media names. Web outputs a CSS container query:
Named containers work the same way with @sm/card:.
On native the container’s size is only known after the first onLayout, so
children render once before the query applies. Set untilMeasured="hide" on
the container to keep it at opacity 0 until measured, or give the container an
explicit width and height so children can resolve the query on first
render.
Next
- Style props for every accepted property and how it renders per platform.
- styled() and Variants for reusable components.
- Flat conditional values for the complete value grammar and editor support.