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.