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 Customization#

The 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 Provider#

For 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 Inheritance#

The theming system follows this resolution order:

  1. Component-specific clearTheme prop
  2. Component-specific theme prop
  3. Nearest parent ThemeProvider theme
  4. 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 Themes#

import { 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 Inheritance#

import { 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 Strategy#

The theme system uses the following merging strategy:

  1. Props Merging: Component props from parent and child ThemeProviders are deep merged
  2. Theme Merging: Theme values are merged using tailwind-merge for intelligent Tailwind CSS class handling
  3. Clear Theme Merging: clearTheme values are deep merged between providers
  4. 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 Tools#

The combination of theme, clearTheme, and applyTheme props provides granular control over component styling. Here are examples showing different levels of customization:

Component Level Control#

import { 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 Control#

import { 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 Control#

import { 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 Values#

The 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 Usage#

import { 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 Clearing#

You 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 Values#

The 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 Replacing#

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>  ); } 

Inheritance Control#

The 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 Order#

When both clearTheme and applyTheme are used, the resolution follows this order:

  1. Apply clearTheme to remove specified values
  2. Apply component-specific theme prop
  3. Apply applyTheme rules to control how new values are merged
  4. Inherit from parent ThemeProvider (unless root={true})
  5. Fall back to default component theme

This system provides complete control over theme inheritance and application while maintaining a predictable behavior.

Provider-Level Props#

The 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:

  1. Component-specific props
  2. Nearest parent ThemeProvider props
  3. Default component props

Like themes, provider props are deep merged between parent and child providers unless root={true} is specified.

Component-Specific Theme#

You 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 IntelliSense#

The 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.