Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • B bootstrap
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 263
    • Issues 263
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 114
    • Merge requests 114
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Bootstrap
  • bootstrap
  • Issues
  • #37983
Closed
Open
Issue created Jan 31, 2023 by Administrator@rootContributor2 of 2 checklist items completed2/2 checklist items

Consider dynamic theming support

Created by: yugabe

Prerequisites

  • I have searched for duplicate or closed feature requests
  • I have read the contributing guidelines

Proposal

Consider adding support to virtually any number of themes, or even theming dynamically.

The theming support introduced in 5.3.0-alpha1 only made it harder to customize or extend the color palette. This proposal would make it arguably a lot easier to add custom themes, extend the color palette, shrink the CSS output by trimming unused colors from the palette and make both the user and framework codes easier to maintain.

Motivation and context

In the end, the current $primary/$secondary/$info etc. variables are leftovers of a time before CSS variables (custom properties) were made available to use. Consider defining a rule as follows, either by user code or in Bootstrap's source itself:

// Some user code:
.some-class {
  color: $primary;
}

This approach is problematic, because if $primary refers to a raw value (like it does currently, which is $blue, that resolves to #0d6efd by default), the .some-class rule above won't respond correctly to theming changes (https://github.com/twbs/bootstrap/issues/37976). This also happens if the user changes the default value to whatever else: in the end, the raw color value will be compiled into the raw CSS. A much more preferable way would be if both user code and framework code would refer to the CSS variable, like so:

// Some user code:
.some-class {
  color: var(--#{$prefix}primary);
}

Although, this interpolation is very prone to breaking, because nothing guarantees that the given hard-coded variable name will be correct. The user might simply make a typo and it would be very hard to debug an issue like this in some cases. A simple solution would be something like this:

// Some user code:
$primary-var: var(--#{$prefix}primary);
.some-class {
  color: $primary-var;
}

It is very much also possible that making the theme colors (like $primary) available would serve no other purpose than for users to incorrectly use the raw, default, initial values of. Thus, it makes sense to fully repurpose the SCSS variables so that they point to the CSS variables instead of the raw values.

// Proposed change to Bootstrap variable declaration:
$primary: var(--#{$prefix}primary); // notice no '!default', as there is no reason to change this variable at all

This way, user code would, in most cases, automatically follow theming changes as well, because they wouldn't have to change from the initial example above:

// Some user code:
.some-class {
 color: $primary;
}

A breaking change though would be how the default values would need to be set for the users for themes:

// Proposed change to Bootstrap variable declaration:
:root {
    #{$primary}: $blue;
}

The above would set the CSS variable corresponding to the "old" $primary SCSS variable to $blue, its current default value. The problem with this approach is that there is no way to set these as "default" values, as because technically this isn't an SCSS variable declaration, and !default is SCSS's syntax - obviously not supported in compiled CSS. Thus, the user would have to manually define the variable value themselves at :root.

A more elegant way to define a full themeset could look as follows:

// Proposed change to Bootstrap theme declaration:
$themes: (
  "light": (
    "body-bg":    $white,
    "body-color": $gray-900,
    "primary":    $blue,
    "success":    $green,
    "info":       $cyan,
    "warning":    $yellow,
    "danger":     $red
  ),
  "dark": (
    "body-bg":    $gray-900,
    "body-color": $gray-500,
    "primary":    $blue-300,
    "success":    $green-300,
    "info":       $cyan-300,
    "warning":    $yellow-300,
    "danger":     $red-300
  )
) !default;

Notice that there are no more variable declarations at all (no $primary, nor $primary-var). That's because the above 5 values in the themes can be considered fully agnostic of context. The user can:

  • name the colors however they'd like,
  • can add or remove any number of them,
  • can simply add more themes by providing a theme key with a map structured as all other maps in the $themes map.

A user can then simply add a theme by doing something like:

$themes: (
  "light": (
    "body-bg": $gray-100,
    "body-color": $gray-900,
    "accent-1": #9ffa5c,
    "accent-2": $green-700,
    "error": $red
  ),
  "dark": (
    "body-bg":    $black,
    "body-color": $gray-200,
    "accent-1": tint-color(#9ffa5c, 60%),
    "accent-2": $green-300,
    "error": $red-200
  ),
  "blue": (
    "body-bg": $blue-100,
    "body-color": $gray-900,
    "accent-1": $blue-600,
    "accent-2": $cyan-300,
    "error": $purple-200
  )
)

Shading, borders, emphasis etc. can all be calculated based on the given values as well, and can be applied to themable components at the component level. Overriding any variable would be done in CSS variables instead. Notice that in the last example, body-bg and body-color were required colors, and "secondary", "light" and "dark" were removed. This is because $secondary (and tertiary) were repurposed in the most recent release, so they are essentially shades of gray or shades/tints of a given them color (-subtle).

Assignee
Assign to
Time tracking