-
-
Notifications
You must be signed in to change notification settings - Fork 79k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider dynamic theming support #37983
Comments
This is super interesting, thanks for sharing! We're definitely in a weird place with v5.3.0 with theming—it's both powerful and slightly cumbersome. We've known it wasn't the complete solution for awhile and that's what we aim to address most in v6. We've talked about reimagining theme settings with a new map as well: $theme: (
"colors": (
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
),
"fgs": (
"default": $body-color,
"secondary": $body-secondary,
"tertiary": $body-tertiary,
),
"bgs": (
"default": $body-bg,
"secondary": $body-bg-secondary,
"tertiary": $body-bg-tertiary,
),
"borders": (
"default": $body-border,
"secondary": $body-border-secondary,
"tertiary": $body-border-tertiary,
),
) !default; But adding in another layer for each theme, and iterating over those themes, is also really cool. Finding a middle ground here would be tremendous in v6. |
Thanks for considering this, @mdo! I also considered the secondary-tertiary colors, but I think they can be inferred from the defaults. Overriding all of those could be done as well, but maybe only via CSS variables, as the reuse of those variables across user code would provide issues that make Bootstrap non-responsive of theme changes currently. Having a "minimal configuration, good defaults" policy could go a long way, if a way to override those defaults is also provided. In my final example above, I intentionally avoided the Consider the following part of the example: "blue": (
"body-bg": $blue-100,
"body-color": $gray-900,
"accent-1": $blue-600,
"accent-2": $cyan-300,
"error": $purple-200
) This means that components that support theming would gain (at least) I have to say that the only things that shouldn't be allowed as variables are discreet colors. Considering all colors are part of a theme, it might be a good practice to never allow SCSS variables to have a discreet color value (except maybe the variables that refer to the colors themselves, like As for me, unfortunately, I have to move away from using Bootstrap in my current project, because I think it's going to be extremely hard to change the current behaviors, even in v6. Some places use the $form-range-thumb-active-bg: tint-color($component-active-bg, 70%) !default; The solution to this would be to refactor all colors INTO the theme declaration. Obviously, that would make the theme definition very large. Hence, the defaults should be inferred as much as possible and refer to a limited set of colors in the theme (or prefer the use of opacity where possible). I tried to fix these issues at usercode level, but it's simply not feasible. I started fixing it at the framework level (inside Bootstrap's SCSS), but it's too woven into the fabric that it is a huge undertaking that it's simply not viable for me to invest another two weeks of my time. Because of this, I have to cut my losses here and move on, but before that I wanted to open a few issues so that you guys at Bootstrap can consider moving in this direction if you feel it aligns with your goals. |
This comment was marked as off-topic.
This comment was marked as off-topic.
@Karl1b Yes, that's been the intention with our migration to CSS variables, but we're not 100% there due to technical issues and concerns around breaking changes. |
I personally think that $primary, $secondary, $success, $info, $warning, and $danger are essential to the way bootstrap has been built for a long time. Changing the names of these common variables to something like accent-1 and error does nothing to change the functionality so it's a breaking change in the way people have used bootstrap for no gain. There has to be a better reason to change naming than just that you like it better. Also, removing secondary is a bad idea too. It's not just another gray. It's gray in the documentation site but not everyone uses it that way. I really do like the idea of having a map of themes. It's a great idea. But I think we should decouple the renaming of variables from that idea as they are really unrelated. Adding the maps, even with no other changes would add value. That can stand on its own merit without anything else IMO. |
Can you just separate all color related classes in a separate SCSS files so BS can be easily theme-able. It is still really hard to add themes to bootstrap even in v5. I use this pattern in our product and it is working pretty good. The only hard thing is to "stop" BS colors :) . |
It's pretty easy to change the theme colors. You can just Add your own theme variables and then @import the main bootstrap scss file, or you can do
|
This way you will generate all the CSS for each theme instead just the color difference. And that's a lot of duplicate css. |
@nkostadinov this is true, but it's the only way with how this is all set up right now. A separate css file for themes can only be done when everything is switched to css variables. Which is an ongoing effort. For now this is the workaround. I will be very happy when the theme colors are no longer scss variables passed around everywhere. |
css variables have nothing to do with it. I mean one scss containing all positioning properties and one for colors e.g. : butons.scss:
The define the colors and include scss containing these colors. themes.scss
themes/buttons.scss
This way you can have unlimited number of themes in themes.scss based on prefix. You can also export different css files for each theme and change them by js. |
@nkostadinov that's going to result in extra css for each theme for every place a theme is used. The css variables that they are already doing and is the direction they are already heading is a better solution. You just end up overriding the css variables for the theme instead of having duplicate styles for every class that uses themes. They have already done this for dark mode and it's super simple. Way simpler than having duplicate output css for each class. In Bootstrap 5.0.2 the use of css variables was minimal and there were 407 selectors using theme colors in the compiled css. Now in 5.3 that's down to 152 selectors using theme colors. The resulting file is also significantly smaller due to that change. I'd much rather see the bootstrap team keep heading in the direction of switching to css variables than get sidetracked by reorganizing the scss when the css variables will provide a much better solution in the long term. You'll be able to just create one css file for your theme like this: [data-bs-theme="light"] {
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
/* Light overrides */
}
[data-bs-theme="dark"] {
/* Dark overrides */
} And then you import that file after the bootstrap minified css. |
I am working on making themes easier to use, while transitioning to v6: https://learn.webpixels.io/themes My focus is to create multiple themes with light/dark mode support: // Functions, variables, maps, and mixins
@import "@webpixels/css/core";
// Variables
@import "blue/variables";
// Mixins
@import "blue/light";
@import "blue/dark";
@import "blue/styles";
.theme-blue {
@include blue-styles;
}
[data-bs-theme="light"],
:root:not([data-bs-theme="dark"]) {
.theme-blue {
@include blue-light;
}
}
// Dark theme (System)
// Automatically enabled if user's prefered scheme is dark
@media only screen and (prefers-color-scheme: dark) {
:root:not([data-bs-theme]) {
.theme-blue {
@include blue-dark;
}
}
}
// Dark theme (Manual)
// Enabled if the data-bs-theme="dark" is added
[data-bs-theme="dark"] {
.theme-blue {
@include blue-dark;
}
} The dark mode can be activated based on user's preferred scheme, or manually using the existing <!doctype html>
<html lang="en" data-bs-theme="light">
<body class="theme-blue">
...
</body>
</html> You can see the entire code here in this repo |
Prerequisites
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: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 (#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: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:
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.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:
A breaking change though would be how the default values would need to be set for the users for themes:
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:
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:$themes
map.A user can then simply add a theme by doing something like:
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
andbody-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
).The text was updated successfully, but these errors were encountered: