Themes
Create themes and sub-themes
Themes map neatly to CSS variables: they are objects whose values you want to contextually change at any point in your React tree. Tamagui lets you define, nest, and read them on web and native.
Bare theme names are the first lookup for style values, and useTheme exposes
them directly. Themes nest both in the definition and at runtime, and values
resolve upward, ultimately all the way back to tokens.
For the recommended theme setup, see the Config v6 docs.
See the ThemeBuilder guide for generating custom theme suites.
To style bento or tamagui components, see
Styling tamagui UI components.
For a copy-paste custom palette and recipe tree, see the v6 Colors guide.
You define a theme like this:
If you use tokens, you can share values from tokens down to themes. Tokens act as fallback values for themes, like global CSS variables vs scoped ones:
Sub-themes
Tamagui supports theme nesting. Define sub-themes using the parentName_subName
format, where each segment resolves as a valid theme. Sub-themes can nest across
multiple levels:
dark_green_subtlelight_green_subtle
You can also access a specific sub-theme more specifically:
Inverse themes
In v3, inverse is a real sub-theme generated by the default theme setup. Use
it like any other sub-theme:
The old themeInverse prop and <Theme inverse> path are removed. Because
inverse is a named sub-theme, SSR can emit the right CSS variables without
client-only light/dark inversion. See the
theme creation guide for custom
theme generation details.
Forcing a scheme with black and white
inverse is relative: it flips whichever scheme its parent happened to be. When
you need a specific scheme instead, use black or white. They resolve to the
dark and light themes from any parent, including from inside a palette
sub-theme:
Reach for them when a subtree cannot know which scheme it is mounted under, such
as a menu that always reads as dark over a light page. Levels nest inside them
as usual, so <Theme name="black"><Theme name="level2"> steps within the dark
scheme rather than falling back to the parent’s.
Keep themes consistent in shape, sharing the same named keys and typed values.
Sub-themes can define subsets of parent themes. The useTheme hook and style
system resolve missing keys upward through parent themes and back to tokens.
Component themes
V3 does not select themes from styled component display names. The displayName
option sets React’s debugging identity and may add an is_Circle class, but it
does not make Tamagui search for light_Circle or affect style resolution.
Use a normal theme boundary when a component owns a theme operation:
This composes under light, dark, color, inverse, and existing level themes without a second component-specific lookup system.
Styling Tamagui Components
The tamagui component suite uses standard semantic theme keys across all
components:
background: component surface colorcolor: text and icon colorborder-color: border colorshadow-color: elevation and shadow colorplaceholder-color: placeholder text color
Each key supports interactive pseudo-states: background-hover,
background-press, and background-focus.
Defining these standard keys lets you re-theme both built-in UI components and your own components consistently across light and dark mode.
A minimal theme might look like this:
You can of course do all of this yourself in your own design system with
styled:
If you are building a component with more than one sub-component, you can follow this pattern:
The frame and text share the active theme. Wrap the composed component in an explicit named or relative level theme when it needs a different semantic surface.
Full Example
Let’s start with an example of inline styling with a subset of the configuration:
In this example we’ve set up darkRed and lightRed variables and a dark and light theme that use those variables. Tamagui will handle defining:
Which will automatically apply at runtime, or can be gathered for use in SSR
with config.getCSS().
Finally, the compiler on web will extract your views roughly as so:
Ensuring valid types
This structure keeps everything typed. Keep themes in a separate themes.ts
file, and structure it like this:
Dynamic Themes
Sometimes you want to defer loading themes, or change existing theme values at
runtime. Tamagui exports three helpers for this in the package @tamagui/theme
which exports addTheme, updateTheme, and replaceTheme.
addTheme
updateTheme
replaceTheme
Notes
- Dynamic themes only work on the client side and will be ignored on the server side.
- The difference between
updateThemeandreplaceThemeis thatreplaceThemewill replace the entire theme, whileupdateThemewill only update the values that are passed in.
Advanced Optimization
To omit theme objects from a server-rendered web app’s client bundle, follow Tree shaking themes. That section covers the CSS and bundler setup required before hydration.