Theme - Flowbite React
Learn how to customize the appearance of Flowbite React components using the theming system
Flowbite React provides a flexible theming system that allows you to customize the appearance of components. The system is built on top of Tailwind CSS and supports multiple levels of customization.
#
Component-Level CustomizationThe simplest way to customize a component is by using the className
prop, which allows you to override or extend the default styles:
import { Button } from "flowbite-react"; function App() { return <Button className="bg-red-500 hover:bg-red-600">Custom Button</Button>; }
#
Theme ProviderFor application-wide customization, use the ThemeProvider
component. The createTheme
helper provides TypeScript and Tailwind CSS IntelliSense support:
import { Button, createTheme, ThemeProvider } from "flowbite-react"; const customTheme = createTheme({ button: { color: { primary: "bg-red-500 hover:bg-red-600", secondary: "bg-blue-500 hover:bg-blue-600", }, size: { lg: "px-6 py-3 text-lg", }, }, }); function App() { return ( <ThemeProvider theme={customTheme}> <Button color="primary">Red Button</Button> <Button color="secondary" size="lg"> Large Blue Button </Button> </ThemeProvider> ); }
#
Theme Resolution and InheritanceThe theming system follows this resolution order:
- Component-specific
clearTheme
prop - Component-specific
theme
prop - Nearest parent
ThemeProvider
theme - Default component theme
When using nested ThemeProvider
components, the following rules apply:
Unless root={true}
is specified:
- Child providers inherit and merge all theme values from their parent
- They only override the specific values they define
- Parent values for undefined properties are preserved
When root={true}
is specified:
- The theme provider ignores all parent theme values
- No merging occurs with parent themes
- Only the specified theme and default theme values are used
- This affects all theme-related props (
theme
,clearTheme
,applyTheme
) and component props
#
Nested Themesimport { Button, createTheme, ThemeProvider } from "flowbite-react"; const mainTheme = createTheme({ button: { color: { primary: "bg-blue-500 hover:bg-blue-600", }, size: { lg: "px-6 py-3", }, }, }); const sectionTheme = createTheme({ button: { color: { primary: "bg-green-500 hover:bg-green-600", // size.lg from mainTheme is preserved }, }, }); function App() { return ( <ThemeProvider theme={mainTheme}> <Button size="lg">Blue Large Button</Button> <ThemeProvider theme={sectionTheme}> {/* Inherits size.lg from mainTheme */} <Button size="lg">Green Large Button</Button> </ThemeProvider> </ThemeProvider> ); }
#
Preventing Theme Inheritanceimport { Button, createTheme, ThemeProvider } from "flowbite-react"; const mainTheme = createTheme({ button: { color: { primary: "bg-blue-500 hover:bg-blue-600", }, size: { lg: "px-6 py-3", }, }, }); const isolatedTheme = createTheme({ button: { color: { primary: "bg-green-500 hover:bg-green-600", }, // No size definitions }, }); function App() { return ( <ThemeProvider theme={mainTheme}> <Button size="lg">Large Blue Button</Button> {/* root={true} prevents merging with mainTheme */} <ThemeProvider theme={isolatedTheme} root> <Button size="lg"> {/* size="lg" will use default theme since isolatedTheme doesn't define sizes and parent theme is ignored */} </Button> </ThemeProvider> </ThemeProvider> ); }
#
Theme Merging StrategyThe theme system uses the following merging strategy:
- Props Merging: Component props from parent and child
ThemeProvider
s are deep merged - Theme Merging: Theme values are merged using tailwind-merge for intelligent Tailwind CSS class handling
- Clear Theme Merging:
clearTheme
values are deep merged between providers - Apply Theme Merging:
applyTheme
configurations are deep merged between providers
The use of tailwind-merge
ensures:
- Automatic conflict resolution between Tailwind CSS classes
- Support for both Tailwind CSS v3 and v4 (automatically detected)
- Proper handling of complex class combinations
- Efficient merging without duplicate utilities
For example:
import { Button, createTheme, ThemeProvider } from "flowbite-react"; const baseTheme = createTheme({ button: { base: "rounded-lg shadow-md", color: { primary: "bg-blue-500 text-white", }, }, }); const customTheme = createTheme({ button: { base: "border-2", color: { primary: "bg-red-500", }, }, }); function App() { return ( <ThemeProvider theme={baseTheme}> {/* Merges themes: rounded-lg shadow-md border-2 */} <Button theme={customTheme.button}>Merged Styles</Button> {/* Replaces base completely: only border-2 remains */} <Button theme={customTheme.button} applyTheme={{ base: "replace" }}> Replaced Base Style </Button> {/* Replaces color completely: loses text-white */} <Button theme={customTheme.button} applyTheme={{ color: { primary: "replace" } }}> Replaced Color </Button> </ThemeProvider> ); }
#
Theme Modification ToolsThe combination of theme
, clearTheme
, and applyTheme
props provides granular control over component styling. Here are examples showing different levels of customization:
#
Component Level Controlimport { Card, createTheme } from "flowbite-react"; const cardTheme = createTheme({ card: { root: { base: "rounded-xl bg-white shadow-md", children: "space-y-4 p-6", }, img: { base: "rounded-t-xl", horizontal: "h-full w-full rounded-l-xl", }, }, }); function App() { return ( <> {/* Basic theme override */} <Card theme={cardTheme.card}>Basic Theme Override</Card> {/* Clear specific nested properties */} <Card theme={cardTheme.card} clearTheme={{ root: { children: true }, // Clear only padding and spacing img: { horizontal: true }, // Clear horizontal image styles }} > Selective Clearing </Card> {/* Control how new styles are applied */} <Card theme={cardTheme.card} applyTheme={{ root: { base: "replace" }, // Replace entire base styles img: { base: "merge" }, // Merge with existing image styles }} > Controlled Style Application </Card> {/* Combining all three props */} <Card theme={cardTheme.card} clearTheme={{ root: { children: true } }} applyTheme={{ img: { base: "replace" } }}> Complex Style Control </Card> </> ); }
#
Nested Component Controlimport { createTheme, Navbar, NavbarCollapse, NavbarLink, ThemeProvider } from "flowbite-react"; const navTheme = createTheme({ navbar: { root: { base: "bg-white shadow-lg", }, collapse: { base: "w-full md:block md:w-auto", list: "mt-4 flex flex-col md:mt-0 md:flex-row md:space-x-8", }, link: { base: "block px-3 py-2", active: { on: "text-blue-600", off: "text-gray-900", }, }, }, }); function App() { return ( <ThemeProvider theme={navTheme}> <Navbar> {/* Control collapse styles */} <NavbarCollapse clearTheme={{ list: true }} // Remove default list styles applyTheme={{ base: "replace" }} // Replace base styles > {/* Control individual link styles */} <NavbarLink href="#" active theme={{ base: "font-medium", active: { on: "text-green-600", // Override active state }, }} applyTheme={{ active: { on: "merge" }, // Merge active state styles }} > Custom Link </NavbarLink> </NavbarCollapse> </Navbar> </ThemeProvider> ); }
#
Form Components Controlimport { createTheme, Label, TextInput } from "flowbite-react"; const formTheme = createTheme({ label: { root: { base: "text-sm font-medium", disabled: "opacity-50", colors: { default: "text-gray-900", error: "text-red-700", }, }, }, textInput: { base: "block w-full", field: { base: "rounded-lg border", input: { base: "px-3 py-2", sizes: { sm: "text-sm", md: "text-base", }, colors: { gray: "border-gray-300 bg-gray-50", error: "border-red-500 bg-red-50", }, }, }, }, }); function App() { return ( <form> {/* Label with error state */} <Label theme={formTheme.label} color="error" clearTheme={{ root: { disabled: true }, // Remove disabled styles }} > Email </Label> {/* Input with custom styling */} <TextInput theme={formTheme.textInput} color="error" size="sm" applyTheme={{ field: { input: { colors: { error: "replace" }, // Replace error styles sizes: { sm: "merge" }, // Merge size styles }, }, }} /> {/* Combining multiple controls */} <TextInput theme={formTheme.textInput} clearTheme={{ field: { input: { sizes: true }, // Remove all size variations }, }} applyTheme={{ base: "merge", // Merge base styles field: { base: "replace" }, // Replace field base styles }} /> </form> ); }
These examples demonstrate how to:
- Use nested theme properties for precise control
- Clear specific style categories while preserving others
- Control how new styles are merged or replaced
- Combine multiple theme controls for complex customization
- Handle component-specific theme variations
- Manage state-dependent styles (active, disabled, etc.)
#
Clearing Theme ValuesThe clearTheme
prop allows you to selectively or completely remove theme values, reverting them to their default styles. When a theme value is cleared, it's set to an empty string.
#
Basic Usageimport { Button, createTheme, ThemeProvider } from "flowbite-react"; const theme = createTheme({ button: { color: { primary: "bg-red-500 hover:bg-red-600", }, base: "rounded-lg", }, }); function App() { return ( <ThemeProvider theme={theme}> <Button>Red Rounded Button</Button> {/* Clear specific theme property */} <Button clearTheme={{ color: true }}>Default Color, Still Rounded</Button> {/* Clear all button theme values */} <Button clearTheme>Completely Default Button</Button> </ThemeProvider> ); }
#
Selective ClearingYou can clear specific nested properties while keeping others:
import { Card, createTheme, ThemeProvider } from "flowbite-react"; const theme = createTheme({ card: { root: { base: "rounded-xl shadow-lg", children: "space-y-4 p-6", }, }, }); function App() { return ( <ThemeProvider theme={theme}> <Card>Regular Card</Card> <Card clearTheme={{ root: { children: true } }}> {/* Keeps rounded-xl and shadow-lg, but clears padding and spacing */} </Card> </ThemeProvider> ); }
#
Applying Theme ValuesThe applyTheme
prop provides fine-grained control over how theme values are merged. It supports two modes:
"merge"
(default): Combines the new theme values with existing ones"replace"
: Completely replaces existing theme values
#
Merging vs Replacingimport { Button, createTheme, ThemeProvider } from "flowbite-react"; const baseTheme = createTheme({ button: { base: "rounded-lg shadow-md", color: { primary: "bg-blue-500 text-white", }, }, }); const customTheme = createTheme({ button: { base: "border-2", color: { primary: "bg-red-500", }, }, }); function App() { return ( <ThemeProvider theme={baseTheme}> {/* Merges themes: rounded-lg shadow-md border-2 */} <Button theme={customTheme.button}>Merged Styles</Button> {/* Replaces base completely: only border-2 remains */} <Button theme={customTheme.button} applyTheme={{ base: "replace" }}> Replaced Base Style </Button> {/* Replaces color completely: loses text-white */} <Button theme={customTheme.button} applyTheme={{ color: { primary: "replace" } }}> Replaced Color </Button> </ThemeProvider> ); }
#
Inheritance ControlThe applyTheme
prop is particularly useful when working with nested components:
import { createTheme, Navbar, NavbarCollapse, NavbarLink, ThemeProvider } from "flowbite-react"; const theme = createTheme({ navbar: { root: { base: "bg-white shadow-lg", }, collapse: { base: "w-full md:block md:w-auto", list: "mt-4 flex flex-col md:mt-0 md:flex-row md:space-x-8", }, }, }); function App() { return ( <ThemeProvider theme={theme}> <Navbar> <NavbarCollapse applyTheme={{ list: "replace", // Replace entire list styles }} > <NavbarLink href="#">Custom Layout</NavbarLink> </NavbarCollapse> </Navbar> </ThemeProvider> ); }
#
Theme Resolution OrderWhen both clearTheme
and applyTheme
are used, the resolution follows this order:
- Apply
clearTheme
to remove specified values - Apply component-specific
theme
prop - Apply
applyTheme
rules to control how new values are merged - Inherit from parent
ThemeProvider
(unlessroot={true}
) - Fall back to default component theme
This system provides complete control over theme inheritance and application while maintaining a predictable behavior.
#
Provider-Level PropsThe ThemeProvider
component accepts a props
prop that allows you to set default props for all components within its scope. These props are merged with any component-specific props, with component props taking precedence:
import { Button, ThemeProvider } from "flowbite-react"; function App() { return ( <ThemeProvider props={{ // Set default props for all buttons button: { color: "success", size: "lg", }, }} > {/* Will be large and green */} <Button>Inherits Provider Props</Button> {/* Will be large and red (color prop overrides provider) */} <Button color="error">Overrides Color Prop</Button> {/* Nested providers merge props by default */} <ThemeProvider props={{ button: { size: "sm", // Override size while keeping color from parent }, }} > {/* Will be small and green */} <Button>Inherits Merged Props</Button> </ThemeProvider> {/* root={true} prevents props inheritance */} <ThemeProvider root props={{ button: { size: "sm", }, }} > {/* Will be small with default color */} <Button>Independent Props</Button> </ThemeProvider> </ThemeProvider> ); }
Props are resolved in the following order:
- Component-specific props
- Nearest parent
ThemeProvider
props - Default component props
Like themes, provider props are deep merged between parent and child providers unless root={true}
is specified.
#
Component-Specific ThemeYou can also apply a custom theme to a specific component instance using the theme
prop:
import { Button, createTheme } from "flowbite-react"; const buttonTheme = createTheme({ button: { color: { custom: "bg-purple-500 text-white hover:bg-purple-600", }, }, }).button; function App() { return ( <Button theme={buttonTheme} color="custom"> Purple Button </Button> ); }
#
Type Safety and IntelliSenseThe createTheme
helper ensures type safety and enables Tailwind CSS IntelliSense in your IDE:
import { createTheme } from "flowbite-react"; // Full theme customization const theme = createTheme({ button: { color: { primary: "bg-blue-500 hover:bg-blue-600", // ✓ Tailwind CSS IntelliSense custom: 123, // ✗ Type error: expected string }, }, }); // Single component theme const buttonTheme = createTheme({ button: { size: { xl: "px-8 py-4 text-xl", // ✓ Tailwind CSS IntelliSense }, }, }).button;
This helps catch errors early and provides better development experience with auto-completion for Tailwind CSS classes.
For information on how to create your own themeable components that work with this system, see the Creating Custom Components guide.