styled()
Extend and build custom and optimizable components
styled() extends a component with base styles and typed variants while
preserving Tamagui’s compiler optimizations.
For the full list of accepted style properties, see the Styles page.
Start from View or Text for new components. styled() adds base styles and
typed variants, and the compiler still optimizes the result:
styled() wraps any Tamagui component, including the
HTML elements such as html.article.
Usage:
You can pass any prop that is supported by the component you are wrapping in styled.
Variants
With variants:
Please use as const for the variants definition until Typescript gains the ability to
infer generics as const.
Usage:
To learn more, see the docs on variants.
Non-working React Native views
React Native utility views like Pressable and TouchableOpacity are not supported targets for styled(). Their event handling logic conflicts with Tamagui. Tamagui components provide press handling and interaction states internally, or you can render Pressable directly when needed.
Using on the web
The styled() function supports Tamagui views, React Native views, and any other React component that accepts a style prop. If you wrap an external component that Tamagui doesn’t recognize, Tamagui will assume it only supports the style prop and not optimize it.
If it does accept className, you can opt-in to className, CSS media queries, and compile-time optimization by adding acceptsClassName:
render
The render prop lets you control which element or component is rendered. It accepts three forms:
String (HTML element)
Render as a specific HTML element on web while maintaining native View on mobile:
This is the recommended approach for semantic HTML and accessibility. String render props are optimized by the Tamagui compiler.
JSX element
Pass a JSX element to clone with Tamagui’s computed props:
The JSX element’s props are merged with Tamagui’s computed styles, classNames, and event handlers. This is useful when you need to pass element-specific props like href or target.
JSX element render props are not optimized by the compiler and will cause a deopt.
Function
For full control, pass a render function that receives props and component state:
The state object includes:
hover: true when hovered (web)press: true when pressedfocus: true when focuseddisabled: true when disabled
Function render props are not optimized by the compiler and will cause a deopt.
Runtime override
You can also override the render prop at runtime:
createStyledHOC
If a functional component that renders a Tamagui-styled component should itself accept styled(), wrap it with createStyledHOC. Example:
Without the wrapper, Tamagui resolves the style props before passing them down, so the inner component merges variants differently than you’d expect.
The way to fix this is to wrap your HigherOrderStyledText with createStyledHOC. You’ll also want to forward the ref, which is forwarded for you:
Now your component will handle everything properly, even if a theme is changed on HigherOrderStyledText, it will be applied.
Pass all Tamagui style props given to HigherOrderStyledText down to a single StyledText for everything to work correctly.
And if you’d like to add new props on top of the existing props, annotate the render function’s props parameter. The annotated props merge over the wrapped component’s props:
Component resolvers (.resolve)
The .resolve method attaches a dynamic style resolver to a styled component. It receives the component’s complete resolved props and the style environment:
Complete props and environment
The resolver callback receives two arguments:
props: the complete styled component prop type, including base props and all declared variants.env: an object containing{ theme, tokens, fonts, font, fontFamily }.
Because props includes the component’s full prop types, .resolve replaces compound variants and sibling-prop inspection logic.
Immutable chaining
Calling .resolve returns a new component. It never mutates the original component:
Each styled layer may attach one resolver. When extending a component with styled(), child components inherit their parent’s resolver chain.
Parent-first execution
The resolver chain executes in parent-first order. The child resolver runs after its parent resolver and overrides conflicting keys:
For <Child tone="critical" />, width is 200 (child resolver wins) and backgroundColor is env.theme['red-10'] (parent resolver lands).
Precedence tiers
Component resolvers sit at layer 2 in Tamagui’s precedence hierarchy:
Rules for resolution:
- A resolver beats base styles and variants for the same property.
- A callsite style prop (such as
<AlertBox width={50} />) beats the resolver. - The
styleprop beats everything. - Setting a property to
undefinedin resolver output means absent. The value falls through to lower tiers (variants or base styles).
Static shape rule
For compiler extraction, write resolver return objects with static keys and scalar expressions. Return undefined for inactive branches instead of spreading objects into the return literal: