Skip to main content Skip to docs navigation
Agregado en v5.3 Ver en GitHub

Modos de color

Bootstrap ahora es compatible con modos de color, o temas, a partir de la v5.3.0. Explora nuestro modo de color claro predeterminado y el nuevo modo oscuro, o crea el tuyo propio utilizando nuestros estilos como plantilla.

¡Pruébalo tú mismo! Descarga el código fuente y la demostración de trabajo para usar Bootstrap con Stylelint, y los modos de color del repositorio twbs/examples. También puedes abrir el ejemplo en StackBlitz.

Modo oscuro

¡Bootstrap ahora es compatible con modos de color, comenzando con el modo oscuro! Con la v5.3.0 puedes implementar tu propio alternador de modo de color (mira a continuación un ejemplo de la documentación de Bootstrap) y aplicar los diferentes modos de color según creas conveniente. Admitimos un modo claro (predeterminado) y ahora el modo oscuro. Los modos de color se pueden alternar globalmente en el elemento <html>, o en componentes y elementos específicos, gracias al atributo data-bs-theme.

Alternativamente, también puedes cambiar a una implementación de consulta de medios (media query) gracias a nuestro mixin de modo de color; consulta la sección de uso para obtener más detalles. Sin embargo, ten en cuenta que esto elimina tu capacidad de cambiar los temas por componente como se muestra a continuación.

Ejemplo

Por ejemplo, para cambiar el modo de color de un menú desplegable, agrega data-bs-theme="light" o data-bs-theme="dark" al .dropdown padre. Ahora, sin importar el modo de color global, estos menús desplegables se mostrarán con el valor de tema especificado.

html
<div class="dropdown" data-bs-theme="light">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButtonLight" data-bs-toggle="dropdown" aria-expanded="false">
    Menú desplegable predeterminado
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonLight">
    <li><a class="dropdown-item active" href="#">Acción</a></li>
    <li><a class="dropdown-item" href="#">Acción</a></li>
    <li><a class="dropdown-item" href="#">Otra acción</a></li>
    <li><a class="dropdown-item" href="#">Algo más aquí</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Enlace separado</a></li>
  </ul>
</div>

<div class="dropdown" data-bs-theme="dark">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButtonDark" data-bs-toggle="dropdown" aria-expanded="false">
    Menú desplegable oscuro
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonDark">
    <li><a class="dropdown-item active" href="#">Acción</a></li>
    <li><a class="dropdown-item" href="#">Acción</a></li>
    <li><a class="dropdown-item" href="#">Otra acción</a></li>
    <li><a class="dropdown-item" href="#">Algo más aquí</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Enlace separado</a></li>
  </ul>
</div>

Cómo funciona

  • Como se muestra arriba, los estilos del modo de color están controlados por el atributo data-bs-theme. Este atributo se puede aplicar al elemento <html> o a cualquier otro elemento o componente de Bootstrap. Si se aplica al elemento <html>, se aplicará a todo. Si se aplica a un componente o elemento, se limitará a ese componente o elemento específico.

  • Para cada modo de color que desees admitir, deberás agregar nuevas anulaciones para las variables CSS globales compartidas. Ya hacemos esto en nuestra hoja de estilo _root.scss para el modo oscuro, siendo el modo claro los valores predeterminados. Al escribir estilos específicos del modo de color, usa el mixin:

    // Variables de modo de color en _root.scss
    @include color-mode(dark) {
      // Anulaciones de variables CSS aquí...
    }
    
  • Usamos un archivo _variables-dark.scss personalizado para potenciar esas anulaciones de variables CSS globales compartidas para el modo oscuro. Este archivo no es necesario para tus propios modos de color personalizados, pero es necesario para nuestro modo oscuro por dos razones. Primero, es mejor tener un único lugar para restablecer los colores globales. Segundo, algunas variables de Sass tuvieron que anularse para las imágenes de fondo integradas en nuestro CSS para acordeones, componentes de formulario y más.

Uso

Habilitar el modo oscuro

Habilita el modo de color oscuro integrado en todo tu proyecto agregando el atributo data-bs-theme="dark" al elemento <html>. Esto aplicará el modo de color oscuro a todos los componentes y elementos, excepto a aquellos que tengan aplicado un atributo data-bs-theme específico. Basándonos en la plantilla de inicio rápido:

<!doctype html>
<html lang="es" data-bs-theme="dark">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Demostración de Bootstrap</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
  </head>
  <body>
    <h1>¡Hola, mundo!</h1>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
  </body>
</html>

Bootstrap aún no viene con un selector de modo de color incorporado, pero puedes usar el de nuestra propia documentación si lo deseas. Obtén más información en la sección de JavaScript.

Construyendo con Sass

Nuestra nueva opción de modo oscuro está disponible para todos los usuarios de Bootstrap, pero se controla a través de atributos de datos en lugar de consultas de medios y no cambia automáticamente el modo de color de tu proyecto. Puedes desactivar nuestro modo oscuro por completo a través de Sass cambiando $enable-dark-mode a false.

Usamos un mixin de Sass personalizado, color-mode(), para ayudarte a controlar cómo se aplican los modos de color. De forma predeterminada, utilizamos un enfoque de atributo data, lo que te permite crear experiencias más fáciles de usar donde tus visitantes pueden elegir tener un modo oscuro automático o controlar su preferencia (como en nuestros propios documentos aquí). Esta también es una forma fácil y escalable de agregar diferentes temas y más modos de color personalizados más allá del claro y el oscuro.

En caso de que quieras usar consultas de medios y solo hacer que los modos de color sean automáticos, puedes cambiar el tipo predeterminado del mixin a través de la variable Sass. Considera el siguiente fragmento y su salida CSS compilada.

$color-mode-type: data;

@include color-mode(dark) {
  .element {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
  }
}

Salida:

[data-bs-theme=dark] .element {
  color: var(--bs-primary-text-emphasis);
  background-color: var(--bs-primary-bg-subtle);
}

Y al configurarlo en media-query:

$color-mode-type: media-query;

@include color-mode(dark) {
  .element {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
  }
}

Salida:

@media (prefers-color-scheme: dark) {
  .element {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
  }
}

Modos de color personalizados

Si bien el caso de uso principal para los modos de color es el modo claro y oscuro, también son posibles modos de color personalizados. Crea tu propio selector data-bs-theme con un valor personalizado como el nombre de tu modo de color, luego modifica nuestras variables Sass y CSS según sea necesario. Optamos por crear una hoja de estilo _variables-dark.scss separada para albergar las variables Sass específicas del modo oscuro de Bootstrap, pero eso no es obligatorio para ti.

Por ejemplo, puedes crear un "tema azul" con el selector data-bs-theme="blue". En tu archivo CSS o Sass personalizado, agrega el nuevo selector y anula cualquier variable CSS global o de componente según sea necesario. Si estás usando Sass, también puedes usar las funciones de Sass dentro de tus anulaciones de variables CSS.

[data-bs-theme="blue"] {
  --bs-body-color: var(--bs-white);
  --bs-body-color-rgb: #{to-rgb($white)};
  --bs-body-bg: var(--bs-blue);
  --bs-body-bg-rgb: #{to-rgb($blue)};
  --bs-tertiary-bg: #{$blue-600};

  .dropdown-menu {
    --bs-dropdown-bg: #{mix($blue-500, $blue-600)};
    --bs-dropdown-link-active-bg: #{$blue-700};
  }

  .btn-secondary {
    --bs-btn-bg: #{mix($gray-600, $blue-400, .5)};
    --bs-btn-border-color: #{rgba($white, .25)};
    --bs-btn-hover-bg: #{darken(mix($gray-600, $blue-400, .5), 5%)};
    --bs-btn-hover-border-color: #{rgba($white, .25)};
    --bs-btn-active-bg: #{darken(mix($gray-600, $blue-400, .5), 10%)};
    --bs-btn-active-border-color: #{rgba($white, .5)};
    --bs-btn-focus-border-color: #{rgba($white, .5)};
    --bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(255, 255, 255, .2);
  }
}
Ejemplo de tema azul

Un poco de texto de párrafo para mostrar cómo podría verse el tema azul con el texto escrito.


<div data-bs-theme="blue">
  ...
</div>

JavaScript

Para permitir que los visitantes o usuarios alternen los modos de color, deberás crear un elemento alternador para controlar el atributo data-bs-theme en el elemento raíz, <html>. Hemos creado un alternador en nuestra documentación que inicialmente se difiere al modo de color actual del sistema del usuario, pero proporciona una opción para anularlo y elegir un modo de color específico.

Aquí tienes un vistazo al JavaScript que lo alimenta. Siéntete libre de inspeccionar la barra de navegación de nuestra propia documentación para ver cómo se implementa utilizando HTML y CSS de nuestros propios componentes. Se sugiere incluir el JavaScript en la parte superior de tu página para reducir el parpadeo potencial de la pantalla durante la recarga de tu sitio. Ten en cuenta que si decides utilizar consultas de medios para tus modos de color, es posible que debas modificar o eliminar tu JavaScript si prefieres un control implícito.

/*!
 * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
 * Copyright 2011-2025 The Bootstrap Authors
 * Licensed under the Creative Commons Attribution 3.0 Unported License.
 */

(() => {
  'use strict'

  const getStoredTheme = () => localStorage.getItem('theme')
  const setStoredTheme = theme => localStorage.setItem('theme', theme)

  const getPreferredTheme = () => {
    const storedTheme = getStoredTheme()
    if (storedTheme) {
      return storedTheme
    }

    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
  }

  const setTheme = theme => {
    if (theme === 'auto') {
      document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
    } else {
      document.documentElement.setAttribute('data-bs-theme', theme)
    }
  }

  setTheme(getPreferredTheme())

  const showActiveTheme = (theme, focus = false) => {
    const themeSwitcher = document.querySelector('#bd-theme')

    if (!themeSwitcher) {
      return
    }

    const themeSwitcherText = document.querySelector('#bd-theme-text')
    const activeThemeIcon = document.querySelector('.theme-icon-active use')
    const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
    const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')

    document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
      element.classList.remove('active')
      element.setAttribute('aria-pressed', 'false')
    })

    btnToActive.classList.add('active')
    btnToActive.setAttribute('aria-pressed', 'true')
    activeThemeIcon.setAttribute('href', svgOfActiveBtn)
    const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
    themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)

    if (focus) {
      themeSwitcher.focus()
    }
  }

  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
    const storedTheme = getStoredTheme()
    if (storedTheme !== 'light' && storedTheme !== 'dark') {
      setTheme(getPreferredTheme())
    }
  })

  window.addEventListener('DOMContentLoaded', () => {
    showActiveTheme(getPreferredTheme())

    document.querySelectorAll('[data-bs-theme-value]')
      .forEach(toggle => {
        toggle.addEventListener('click', () => {
          const theme = toggle.getAttribute('data-bs-theme-value')
          setStoredTheme(theme)
          setTheme(theme)
          showActiveTheme(theme, true)
        })
      })
  })
})()

Agregar colores de tema

Agregar un nuevo color en $theme-colors no es suficiente para algunos de nuestros componentes como alertas y grupos de listas. Los nuevos colores también deben definirse en $theme-colors-text, $theme-colors-bg-subtle, and $theme-colors-border-subtle para el tema claro; pero también en $theme-colors-text-dark, $theme-colors-bg-subtle-dark, and $theme-colors-border-subtle-dark para el tema oscuro.

Este es un proceso manual porque Sass no puede generar sus propias variables Sass a partir de una variable o mapa existente. En futuras versiones de Bootstrap, revisaremos esta configuración para reducir la duplicación.

// Requerido
@import "functions";
@import "variables";
@import "variables-dark";

// Agregar un color personalizado a $theme-colors
$custom-colors: (
  "custom-color": #712cf9
);
$theme-colors: map-merge($theme-colors, $custom-colors);

@import "maps";
@import "mixins";
@import "utilities";

// Agregar un color personalizado a nuevos mapas de temas

// Modo claro
$custom-colors-text: ("custom-color": #712cf9);
$custom-colors-bg-subtle: ("custom-color": #e1d2fe);
$custom-colors-border-subtle: ("custom-color": #bfa1fc);

$theme-colors-text: map-merge($theme-colors-text, $custom-colors-text);
$theme-colors-bg-subtle: map-merge($theme-colors-bg-subtle, $custom-colors-bg-subtle);
$theme-colors-border-subtle: map-merge($theme-colors-border-subtle, $custom-colors-border-subtle);

// Modo oscuro
$custom-colors-text-dark: ("custom-color": #e1d2f2);
$custom-colors-bg-subtle-dark: ("custom-color": #8951fa);
$custom-colors-border-subtle-dark: ("custom-color": #e1d2f2);

$theme-colors-text-dark: map-merge($theme-colors-text-dark, $custom-colors-text-dark);
$theme-colors-bg-subtle-dark: map-merge($theme-colors-bg-subtle-dark, $custom-colors-bg-subtle-dark);
$theme-colors-border-subtle-dark: map-merge($theme-colors-border-subtle-dark, $custom-colors-border-subtle-dark);

// Resto de importaciones de Bootstrap
@import "root";
@import "reboot";
// etc

CSS

Variables

Decenas de variables CSS a nivel de raíz se repiten como anulaciones para el modo oscuro. Estas se limitan al selector de modo de color, que por defecto es data-bs-theme pero se puede configurar para usar una consulta de medios prefers-color-scheme. Utiliza estas variables como guía para generar tus propios modos de color nuevos.

--#{$prefix}body-color: #{$body-color-dark};
--#{$prefix}body-color-rgb: #{to-rgb($body-color-dark)};
--#{$prefix}body-bg: #{$body-bg-dark};
--#{$prefix}body-bg-rgb: #{to-rgb($body-bg-dark)};

--#{$prefix}emphasis-color: #{$body-emphasis-color-dark};
--#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color-dark)};

--#{$prefix}secondary-color: #{$body-secondary-color-dark};
--#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color-dark)};
--#{$prefix}secondary-bg: #{$body-secondary-bg-dark};
--#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg-dark)};

--#{$prefix}tertiary-color: #{$body-tertiary-color-dark};
--#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color-dark)};
--#{$prefix}tertiary-bg: #{$body-tertiary-bg-dark};
--#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg-dark)};

@each $color, $value in $theme-colors-text-dark {
  --#{$prefix}#{$color}-text-emphasis: #{$value};
}

@each $color, $value in $theme-colors-bg-subtle-dark {
  --#{$prefix}#{$color}-bg-subtle: #{$value};
}

@each $color, $value in $theme-colors-border-subtle-dark {
  --#{$prefix}#{$color}-border-subtle: #{$value};
}

--#{$prefix}heading-color: #{$headings-color-dark};

--#{$prefix}link-color: #{$link-color-dark};
--#{$prefix}link-hover-color: #{$link-hover-color-dark};
--#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)};
--#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)};

--#{$prefix}code-color: #{$code-color-dark};
--#{$prefix}highlight-color: #{$mark-color-dark};
--#{$prefix}highlight-bg: #{$mark-bg-dark};

--#{$prefix}border-color: #{$border-color-dark};
--#{$prefix}border-color-translucent: #{$border-color-translucent-dark};

--#{$prefix}form-valid-color: #{$form-valid-color-dark};
--#{$prefix}form-valid-border-color: #{$form-valid-border-color-dark};
--#{$prefix}form-invalid-color: #{$form-invalid-color-dark};
--#{$prefix}form-invalid-border-color: #{$form-invalid-border-color-dark};

Variables de Sass

Las variables CSS para nuestro modo de color oscuro se generan parcialmente a partir de variables Sass específicas del modo oscuro en _variables-dark.scss. Esto también incluye algunas anulaciones personalizadas para cambiar los colores de los SVG incrustados utilizados en nuestros componentes.

// scss-docs-start theme-text-dark-variables
$primary-text-emphasis-dark:        tint-color($primary, 40%);
$secondary-text-emphasis-dark:      tint-color($secondary, 40%);
$success-text-emphasis-dark:        tint-color($success, 40%);
$info-text-emphasis-dark:           tint-color($info, 40%);
$warning-text-emphasis-dark:        tint-color($warning, 40%);
$danger-text-emphasis-dark:         tint-color($danger, 40%);
$light-text-emphasis-dark:          $gray-100;
$dark-text-emphasis-dark:           $gray-300;
// scss-docs-end theme-text-dark-variables

// scss-docs-start theme-bg-subtle-dark-variables
$primary-bg-subtle-dark:            shade-color($primary, 80%);
$secondary-bg-subtle-dark:          shade-color($secondary, 80%);
$success-bg-subtle-dark:            shade-color($success, 80%);
$info-bg-subtle-dark:               shade-color($info, 80%);
$warning-bg-subtle-dark:            shade-color($warning, 80%);
$danger-bg-subtle-dark:             shade-color($danger, 80%);
$light-bg-subtle-dark:              $gray-800;
$dark-bg-subtle-dark:               mix($gray-800, $black);
// scss-docs-end theme-bg-subtle-dark-variables

// scss-docs-start theme-border-subtle-dark-variables
$primary-border-subtle-dark:        shade-color($primary, 40%);
$secondary-border-subtle-dark:      shade-color($secondary, 40%);
$success-border-subtle-dark:        shade-color($success, 40%);
$info-border-subtle-dark:           shade-color($info, 40%);
$warning-border-subtle-dark:        shade-color($warning, 40%);
$danger-border-subtle-dark:         shade-color($danger, 40%);
$light-border-subtle-dark:          $gray-700;
$dark-border-subtle-dark:           $gray-800;
// scss-docs-end theme-border-subtle-dark-variables

$body-color-dark:                   $gray-300;
$body-bg-dark:                      $gray-900;
$body-secondary-color-dark:         rgba($body-color-dark, .75);
$body-secondary-bg-dark:            $gray-800;
$body-tertiary-color-dark:          rgba($body-color-dark, .5);
$body-tertiary-bg-dark:             mix($gray-800, $gray-900, 50%);
$body-emphasis-color-dark:          $white;
$border-color-dark:                 $gray-700;
$border-color-translucent-dark:     rgba($white, .15);
$headings-color-dark:               inherit;
$link-color-dark:                   tint-color($primary, 40%);
$link-hover-color-dark:             shift-color($link-color-dark, -$link-shade-percentage);
$code-color-dark:                   tint-color($code-color, 40%);
$mark-color-dark:                   $body-color-dark;
$mark-bg-dark:                      $yellow-800;


//
// Forms
//

$form-select-indicator-color-dark:  $body-color-dark;
$form-select-indicator-dark:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$form-select-indicator-color-dark}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");

$form-switch-color-dark:            rgba($white, .25);
$form-switch-bg-image-dark:         url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color-dark}'/></svg>");

// scss-docs-start form-validation-colors-dark
$form-valid-color-dark:             $green-300;
$form-valid-border-color-dark:      $green-300;
$form-invalid-color-dark:           $red-300;
$form-invalid-border-color-dark:    $red-300;
// scss-docs-end form-validation-colors-dark


//
// Accordion
//

$accordion-icon-color-dark:         $primary-text-emphasis-dark;
$accordion-icon-active-color-dark:  $primary-text-emphasis-dark;

$accordion-button-icon-dark:         url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/></svg>");
$accordion-button-active-icon-dark:  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-active-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/></svg>");

Mixins de Sass

Los estilos para el modo oscuro, y cualquier modo de color personalizado que crees, se pueden limitar adecuadamente al selector de atributos data-bs-theme o consulta de medios con el mixin personalizable color-mode(). Consulta la sección de uso de Sass para obtener más detalles.

@mixin color-mode($mode: light, $root: false) {
  @if $color-mode-type == "media-query" {
    @if $root == true {
      @media (prefers-color-scheme: $mode) {
        :root {
          @content;
        }
      }
    } @else {
      @media (prefers-color-scheme: $mode) {
        @content;
      }
    }
  } @else {
    [data-bs-theme="#{$mode}"] {
      @content;
    }
  }
}