CSS custom properties and theming/styling #343
Replies: 7 comments
-
and this could be a transition way to implement more specific CSS variables : .tag--primary {
background-color: var(--sl-tag-background-color-primary, var(--sl-color-primary-95));
} |
Beta Was this translation helpful? Give feedback.
-
The main problem here is something I first recognized in Bootstrap, which is variable hell. Take a look at their variables file — it's over 1,300 lines. I'm reluctant to do this because it starts here: :root {
--sl-tag-background-color-primary
--sl-tag-border-color-primary
--sl-tag-color-primary
} Then people "need" more and it quickly leads to this: :root {
--sl-tag-background-color-primary
--sl-tag-border-color-primary
--sl-tag-color-primary
--sl-tag-border-radius-primary
--sl-tag-box-shadow-primary
--sl-tag-padding-primary
/* ...and every other conceivable property because somebody needs it */
} Oops, let's not forget the state modifiers: :root {
--sl-tag-background-color-primary
--sl-tag-border-color-primary
--sl-tag-color-primary
--sl-tag-border-radius-primary
--sl-tag-box-shadow-primary
--sl-tag-padding-shadow-primary
/* ... */
--sl-tag-background-color-primary-hover
--sl-tag-border-color-primary-hover
--sl-tag-color-primary-hover
--sl-tag-border-radius-primary-hover
--sl-tag-box-shadow-primary-hover
--sl-tag-padding-primary-hover
/* ... */
--sl-tag-background-color-primary-active
--sl-tag-border-color-primary-active
--sl-tag-color-primary-active
--sl-tag-border-radius-primary-active
--sl-tag-box-shadow-primary-active
--sl-tag-padding-primary-active
/* ... */
--sl-tag-background-color-primary-focus
--sl-tag-border-color-primary-focus
--sl-tag-color-primary-focus
--sl-tag-border-radius-primary-focus
--sl-tag-box-shadow-primary-focus
--sl-tag-padding-primary-focus
/* ... */
} And oh yeah, one for each theme: :root {
--sl-tag-background-color-primary
--sl-tag-border-color-primary
--sl-tag-color-primary
--sl-tag-border-radius-primary
--sl-tag-box-shadow-primary
--sl-tag-padding-primary
/* ... */
--sl-tag-background-color-primary-hover
--sl-tag-border-color-primary-hover
--sl-tag-color-primary-hover
--sl-tag-border-radius-primary-hover
--sl-tag-box-shadow-primary-hover
--sl-tag-padding-primary-hover
/* ... */
--sl-tag-background-color-primary-active
--sl-tag-border-color-primary-active
--sl-tag-color-primary-active
--sl-tag-border-radius-primary-active
--sl-tag-box-shadow-primary-active
--sl-tag-padding-primary-active
/* ... */
--sl-tag-background-color-primary-focus
--sl-tag-border-color-primary-focus
--sl-tag-color-primary-focus
--sl-tag-border-radius-primary-focus
--sl-tag-box-shadow-primary-focus
--sl-tag-padding-primary-focus
/* ... */
--sl-tag-background-color-success
--sl-tag-border-color-success
--sl-tag-color-success
--sl-tag-border-radius-success
--sl-tag-box-shadow-success
--sl-tag-padding-success
/* ... */
--sl-tag-background-color-success-hover
--sl-tag-border-color-success-hover
--sl-tag-color-success-hover
--sl-tag-border-radius-success-hover
--sl-tag-box-shadow-success-hover
--sl-tag-padding-success-hover
/* ... */
--sl-tag-background-color-success-active
--sl-tag-border-color-success-active
--sl-tag-color-success-active
--sl-tag-border-radius-success-active
--sl-tag-box-shadow-success-active
--sl-tag-padding-success-active
/* ... */
--sl-tag-background-color-success-focus
--sl-tag-border-color-success-focus
--sl-tag-color-success-focus
--sl-tag-border-radius-success-focus
--sl-tag-box-shadow-success-focus
--sl-tag-padding-success-focus
/* ... */
--sl-tag-background-color-info
--sl-tag-border-color-info
--sl-tag-color-info
--sl-tag-border-radius-info
--sl-tag-box-shadow-info
--sl-tag-padding-info
/* ... */
--sl-tag-background-color-info-hover
--sl-tag-border-color-info-hover
--sl-tag-color-info-hover
--sl-tag-border-radius-info-hover
--sl-tag-box-shadow-info-hover
--sl-tag-padding-info-hover
/* ... */
--sl-tag-background-color-info-active
--sl-tag-border-color-info-active
--sl-tag-color-info-active
--sl-tag-border-radius-info-active
--sl-tag-box-shadow-info-active
--sl-tag-padding-info-active
/* ... */
--sl-tag-background-color-info-focus
--sl-tag-border-color-info-focus
--sl-tag-color-info-focus
--sl-tag-border-radius-info-focus
--sl-tag-box-shadow-info-focus
--sl-tag-padding-info-focus
/* ... */
--sl-tag-background-color-warning
--sl-tag-border-color-warning
--sl-tag-color-warning
--sl-tag-border-radius-warning
--sl-tag-box-shadow-warning
--sl-tag-padding-info-warning
/* ... */
--sl-tag-background-color-warning-hover
--sl-tag-border-color-warning-hover
--sl-tag-color-warning-hover
--sl-tag-border-radius-warning-hover
--sl-tag-box-shadow-warning-hover
--sl-tag-padding-warning-hover
/* ... */
--sl-tag-background-color-warning-active
--sl-tag-border-color-warning-active
--sl-tag-color-warning-active
--sl-tag-border-radius-warning-active
--sl-tag-box-shadow-warning-active
--sl-tag-padding-warning-active
/* ... */
--sl-tag-background-color-warning-focus
--sl-tag-border-color-warning-focus
--sl-tag-color-warning-focus
--sl-tag-border-radius-warning-focus
--sl-tag-box-shadow-warning-focus
--sl-tag-padding-warning-focus
/* ... */
--sl-tag-background-color-danger
--sl-tag-border-color-danger
--sl-tag-color-danger
--sl-tag-border-radius-danger
--sl-tag-box-shadow-danger
--sl-tag-padding-danger
/* ... */
--sl-tag-background-color-danger-hover
--sl-tag-border-color-danger-hover
--sl-tag-color-danger-hover
--sl-tag-border-radius-danger-hover
--sl-tag-box-shadow-danger-hover
--sl-tag-padding-danger-hover
/* ... */
--sl-tag-background-color-danger-active
--sl-tag-border-color-danger-active
--sl-tag-color-danger-active
--sl-tag-border-radius-danger-active
--sl-tag-box-shadow-danger-active
--sl-tag-padding-danger-active
/* ... */
--sl-tag-background-color-danger-focus
--sl-tag-border-color-danger-focus
--sl-tag-color-danger-focus
--sl-tag-border-radius-danger-focus
--sl-tag-box-shadow-danger-focus
--sl-tag-padding-danger-focus
/* ... */
} If you're still scrolling, you've probably gotten my point by now. I'm not saying we can't figure out a way to make customization easier, but it's probably not a good idea to introduce tons of global CSS vars. And sure, this is a bit contrived. It probably doesn't make sense to include every single CSS property for every possible state/theme. But then we have to think about which ones should be included, and users will likely expect them all and PR the ones that are missing. It becomes more difficult to develop, maintain, and use the library than if we simply rely on higher level color primitives. I still think the solution involves design tokens first, then overriding various parts if and when it's needed. If you had more control over managing the color palette, for example, I think this would be much less of an issue. And introducing a professionally curated palette of color generics like I'm exploring in #283 will help with that because:
One thing that I find particularly interesting about Bootstrap is, despite offering nearly 1,400 variables, most users only seem to customize basic things such as the brand color. Rarely do they take the time to tweak every component, and at that point it's always a hunt for the right variable(s) when it could be a simple property override. (Not to mention the confusion when changing one variable somehow affects a dozen other things and you end up writing custom styles anyways.) For now, I'd like to continue to explore #283 to see if we can introduce some patterns/helpers that make this easier. This has given me more things to hack on. 😄 |
Beta Was this translation helpful? Give feedback.
-
It's not the idea to set all CSS variables for a theme but only color palette. A theme is component agnostic, it's a palette that does not need to be modified if you add a component. For exemple in that case : .tag--primary {
background-color: var(--sl-tag-background-color-primary, var(--sl-color-primary-95));
} until --sl-tag-background-color-primary is set, normally in a subtree for a particular case, it's never used or define so the --sl-color-primary-95 is apply. And I agree with the idea to have a less complex palette in term of CSS Variables. the syntax below is also use to define the default theme color palette, this is resulting of a scss compilation where a global theme variables define a $color-primary-95 : #BFDBFE. (the 1300 lines file, is not that big that it's all css default values) .tag--primary {
background-color: var(--sl-tag-background-color-primary, var(--sl-color-primary-95, #BFDBFE));
} the idea to style a component is to set a CSS property with fallback values : own variable (component styling) -> global variable (theme) -> default value (default theme) In the case of Shoelace, the only rewrite that have to be done is to name a variable in scss of each component, think about a global variable pick in a palette and eventually default the property value at build time with scss (or keep the way you done with importing the default palette in default.css) and fill the documentation. I know my english is not good enough to be technically precise so i hope you can find here a sufficient explanation of what i wanted to mean. Unfortunately, until a system like this have been done, Sholeace is not usable in application while it's one of the more promising webcomp library i've seen. Whatever, i could miss something in the way you imagine style, so please take time to modify this example https://codesandbox.io/s/goofy-https-0ip1j to show us how the final sl-button should get the dark style. Best regards, awesome work you've done! |
Beta Was this translation helpful? Give feedback.
-
I like @eskan's example there with the fallbacks…it provides the extra customizability I would like to see without actually requiring hundreds of new variables to be declared. I understand your concern @claviska about becoming Bootstrap all over again! |
Beta Was this translation helpful? Give feedback.
-
There's definitely some validity to this concern, but I'm not convinced CSS custom properties are the sole solution. I'd like to explore other options first, such as Constructable Sytlesheets. @eskan for the sake of simplicity, here's a Fiddle that demonstrates https://jsfiddle.net/dxsL4qbo/ To summarize, the current approach involves importing a theme stylesheet at the root and encapsulating content with Problems with the current approach:
Before we tackle this problem, it's worth mentioning the these limitations are spec'd like this by design. Shadow DOM's best feature is encapsulation, so I don't think we should break that by default — the solution should probably be opt-in. |
Beta Was this translation helpful? Give feedback.
-
I have to admit, after the latest changes to the color theming in the beta, I'm finding this less of a problem. Once I initially set some variables in |
Beta Was this translation helpful? Give feedback.
-
Hey, folks! There are many discussions/issues around theming, so in an effort to consolidate and track improvements, let's focus the discussion on #381 moving forward. |
Beta Was this translation helpful? Give feedback.
-
One of the issues I've run into with bringing Shoelace components into an existing site design is matching up certain component colors with the rest of my color scheme, for example the primary button color, or the success tag color, etc. While I can affect the hue of the components in general by changing the colors of the Shoelace theme itself, I can't effect the brightness of each component individually.
As mentioned here:
#283 (comment)
The only remedy I currently have is to use
::part
and override the background, border, and text colors manually.Instead, what I would like to see is, rather than the component hardcoding the values in its CSS (tag component example):
it would reference relevant CSS variables at the component level, something like this:
and then those variables could be defined either on
.tag
or:host
:That way, all I would need to do to override these values in my own global stylesheet would be to change the CSS variables (
--sl-tag-background-color-primary
, etc.), and therefore using::part
for this use case would be unnecessary.Hopefully that makes sense. Let me know if you have any questions!
Beta Was this translation helpful? Give feedback.
All reactions