# Components

> Learn how and why we build nearly all our components responsively and with base and modifier classes.

## Base classes

CoreUI's components are largely built with a base-modifier nomenclature. We group as many shared properties as possible into a base class, like `.btn`, and then group individual styles for each variant into modifier classes, like `.btn-primary` or `.btn-success`.

To build our modifier classes, we use Sass's `@each` loops to iterate over a Sass map. This is especially helpful for generating variants of a component by our `$theme-colors` and creating responsive variants for each breakpoint. As you customize these Sass maps and recompile, you'll automatically see your changes reflected in these loops.

Check out [our Sass maps and loops docs](https://coreui.io/react/docs/customize/sass/#maps-and-loops) for how to customize these loops and extend CoreUI's base-modifier approach to your own code.

## Modifiers

_Deprecated in 6.0.0._

Components used to be built with a base-modifier class approach: the bulk of the styling in a base class (e.g., `.btn`) and each color in its own modifier (e.g., `.btn-danger`), generated by looping over `$theme-colors`. Those classes still ship, in the opt-in [`coreui-legacy.css`](https://coreui.io/react/docs/customize/optimize/#v5-compatibility-css) rather than in `coreui.css` — but a component is themed with a [theme variant](#theme-variants) now, so one family of classes recolors every component instead of one family per component.

Here are two examples of the loops that still generate them, for `.alert` and `.list-group`.

```scss
@each $state in map.keys($theme-colors) {
  .alert-#{$state} {
    @include theme-tokens($state);
  }
}
```

```scss
// List group contextual variants
//
// Add modifier classes to change text and background color on individual items.
@each $state in map.keys($theme-colors) {
  .list-group-item-#{$state} {
    @include theme-tokens($state);
  }
}
```

## Theme variants

Themeable components also support a single family of composable `.theme-*` classes that recolor a component without a per-component color class. A themeable component reads a shared set of generic `--cui-theme-*` tokens for its background, foreground, border, and focus styles — each with a fallback to the component's own default token. When no theme class is present, the fallback applies. Add a `.theme-*` class to the component, to an ancestor, or to one of its parts, and it picks up that theme's colors instead.

| Token | Description |
| --- | --- |
| `--cui-theme-bg` | The theme color itself, e.g. a solid badge or button background |
| `--cui-theme-contrast` | Contrasting color for text and icons sitting on the solid base |
| `--cui-theme-fg` | The theme's readable text color |
| `--cui-theme-fg-emphasis` | High-contrast foreground, one step darker |
| `--cui-theme-bg-subtle` | Subtle background tint for low-emphasis surfaces |
| `--cui-theme-bg-muted` | Muted background, between subtle and solid |
| `--cui-theme-border` | Border color |
| `--cui-theme-hover` | The theme color shifted for a hover state: lightness times `--cui-theme-hover-lightness`, chroma times `--cui-theme-hover-chroma` |
| `--cui-theme-active` | The same, one step further, for a pressed state, from the `--cui-theme-active-*` pair |
| `--cui-theme-focus-ring` | Focus ring color, translucent at `$focus-ring-opacity` |

The `.theme-{name}` classes mirror the keys of the `$theme-colors` map in `scss/_theme.scss` — `.theme-primary`, `.theme-success`, `.theme-danger`, and so on — so adding or renaming a theme color automatically produces a matching class. Each entry defines the tokens for both light and dark mode via `light-dark()`. Themeable React components render the class through their `theme` prop — see [the Theme page](https://coreui.io/react/docs/customize/theme/#theme-classes).

To see how a component consumes these tokens, here's the badge in `scss/_badge.scss`. Its color and background each read a theme token first, falling back to the badge's own default:

```scss
// the token map carries only the badge's own default
--#{$prefix}badge-color: inherit,
--#{$prefix}badge-bg: var(--#{$prefix}bg-2),

// the theme is read at the property, with the token as the fallback
color: var(--#{$prefix}theme-contrast, var(--#{$prefix}badge-color));
background-color: var(--#{$prefix}theme-bg, var(--#{$prefix}badge-bg));
```

With no theme class the badge stays neutral; add `.theme-success` and the very same element resolves the success tokens — no `.badge-success` selector required. Structural variants compose with any theme:

```html
<span className="badge">Default</span>
<span className="badge theme-success">Success</span>
<span className="badge badge-subtle theme-success">Success</span>
<span className="badge badge-outline theme-success">Success</span>
```

Because the theme tokens are plain CSS variables, you can also scope a theme to a container and let everything inside inherit it, or define a brand of your own without recompiling:

```css
.my-brand {
  --cui-theme-bg: #6f42c1;
  --cui-theme-contrast: #fff;
}
```

Where a classic color class still exists — `.btn-primary`, `.alert-success` — it is generated from the same theme tokens, so both APIs stay pixel-identical. The badge is the exception: it has no `.badge-{color}` spelling, and `.theme-{color}` is the only way to color it.

### Building a themeable component

Read the theme slot **at the property**, wrapping the component's own token. Slots inherit, so one form covers every case — the class works on the component, on an ancestor, or on any part of it:

```scss
--#{$prefix}badge-bg: var(--#{$prefix}bg-2),
// …
background-color: var(--#{$prefix}theme-bg, var(--#{$prefix}badge-bg));
```

A structural variant maps the token to a slot of its own, and then **re-declares the property with a plain read** so it wins over the base rule:

```scss
.badge-subtle {
  --#{$prefix}badge-bg: var(--#{$prefix}theme-bg-subtle);

  background-color: var(--#{$prefix}badge-bg);
}
```

The second line is the part that is easy to miss. Set the token alone and the base rule still applies its own slot, so `.badge-subtle` and `.badge-outline` collapse into the solid theme color.

A validation state works the same way: `.is-invalid` sets the checkbox's tokens and re-declares `background-color` and `border-color` on `:checked`, so a red invalid checkbox stays red inside a themed form.

While no theme class is present the token behaves as an override point; under one, the theme wins. That keeps a token set for the whole page (`.alert { --cui-alert-bg: … }` in your stylesheet, or `$alert-tokens` in Sass) from switching the themes off. To recolor a single themed component, set the slot instead of the component token:

```jsx
<CAlert theme="danger" style={{ '--cui-theme-bg-subtle': '#fde2e4' }}>…</CAlert>
```

On an element with a variant class it works the other way. `.btn-solid` and the other button variants, `.alert-solid`, `.badge-subtle`, `.badge-outline`, `.avatar-subtle` and `.chip-outline` map the component tokens to their own slots and paint from the tokens, so there a component token set on the element, or for the whole page in your stylesheet, wins over the theme.

## Backdrop

Every overlay that dims the page — the dialog and the drawer through their native `::backdrop` — paints that layer from three tokens on `:root`:

```scss
--cui-backdrop-color: var(--cui-black),
--cui-backdrop-opacity: 50%,
--cui-backdrop-blur: 8px,
```

The colour and the opacity are mixed on the element (`color-mix(in oklch, var(--cui-backdrop-color) var(--cui-backdrop-opacity), transparent)`), so either can be changed alone, globally on `:root` or on one overlay. The dialog keeps the defaults, a dark scrim that deepens in the dark scheme; the drawer sets its own tint of the page (`--cui-bg-body` at 25%). The [backdrop helper](https://coreui.io/react/docs/helpers/backdrop/) picks either look — or no backdrop at all — from the markup.

## Translucent

The `*-translucent` variants — `.navbar-translucent`, `.toast-translucent`, `.card-translucent`, `.drawer-translucent` and `.menu-translucent` — let the page show through a blurred, saturated surface. All five mix the component's own background with one opacity and apply one filter, both tokens on `:root`:

```scss
--cui-translucent-opacity: 80%,
--cui-translucent-backdrop-filter: blur(5px) saturate(180%),
```

Set them on `:root` to retune every translucent surface at once, or on one element to change just that one — `style={{ '--cui-translucent-opacity': '60%' }}` on a card leaves the navbar alone.

## Responsive

These Sass loops aren't limited to color maps, either. You can also generate responsive variations of your components. Take for example the v5 responsive alignment classes of the dropdown, kept in `coreui-legacy.css`, where we mix an `@each` loop for the `$breakpoints` Sass map with a media query include.

```scss
@each $breakpoint in map.keys($breakpoints) {
  @include media-breakpoint-up($breakpoint) {
    $infix: breakpoint-infix($breakpoint, $breakpoints);

    .dropdown-menu#{$infix}-start {
      --cui-position: start;

      &[data-coreui-popper] {
        inset-inline-start: 0;
        inset-inline-end: auto;
      }
    }

    .dropdown-menu#{$infix}-end {
      --cui-position: end;

      &[data-coreui-popper] {
        inset-inline-start: auto;
        inset-inline-end: 0;
      }
    }
  }
}
```

Should you modify your `$breakpoints`, your changes will apply to all the loops iterating over that map.

```scss
$breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 1024px,
  xl: 1280px,
  2xl: 1536px
) !default;
```

For more information and examples on how to modify our Sass maps and variables, please refer to [the Sass section of the Grid documentation](https://coreui.io/react/docs/layout/grid/#customizing-the-grid).

## Creating your own

We encourage you to adopt these guidelines when building with CoreUI to create your own components. We've extended this approach ourselves to the custom components in our documentation and examples. Components like our callouts are built just like our provided components with base and modifier classes.

```html
<div className="callout">...</div>
```

In your CSS, you'd have something like the following where the bulk of the styling is done via `.callout`. Then, the unique styles between each variant is controlled via modifier class.

```scss
// Base class
.callout {}

// Modifier classes
.callout-info {}
.callout-warning {}
.callout-danger {}
```

For the callouts, that unique styling is just a `border-left-color`. When you combine that base class with one of those modifier classes, you get your complete component family:

> **This is an info callout.** Example text to show it in action.

> **This is a warning callout.** Example text to show it in action.

> **This is a danger callout.** Example text to show it in action.
