space toggles for switching themes #6
Description
Clear and concise description of the problem
the current approach for dual themes is quite clever indeed, but it can be problematic in a few ways.
- it relies on implementation details like
.shiki
andspan
selectors. not a deal-breaker. - it could get unwieldy/verbose when considering additional themes (e.g. high-contrast). also not a deal-breaker. 🤷
- it relies on
!important
, which is pretty much deprecated in this day and age of cascade layers. As a user, it is important (ha!) to me that i have control over the cascade, as i might need to change the colors for particular cases (such as text highlighting, print stylesheets, or forced colors mode).
for reference, here is the css currently needed from the user's side for switching themes:
@media (prefers-color-scheme: dark) {
.shiki {
background-color: var(--shiki-dark-bg) !important;
color: var(--shiki-dark) !important;
& span {
color: var(--shiki-dark) !important;
}
}
}
Suggested solution
(edit: make sure to see update at the end)
i was just thinking about this, and realized that the space toggle technique would be a good fit for this use case, as it would allow users to switch values with a single css declaration.
@media (prefers-color-scheme: dark) {
:root {
--is-shiki-dark: var(--yes);
}
}
(where --yes: initial;
is just a convenience constant)
the inline style implementation would look like this, with full support for complex textmate grammar.
<pre style="--is-shiki-dark: /* no */;">
...
<span style="color: var(--is-shiki-dark, #ECEFF4) #6F42C1;">
this is already very good, but we can take this idea further:
-
for full control over the cascade, a custom property could be used instead of
color
.- <span style="color: var(--is-shiki-dark, #ECEFF4) #6F42C1;"> + <span style="--shiki-color: var(--is-shiki-dark, #ECEFF4) #6F42C1;">
and shikiji could ship with a small stylesheet, which can be imported into user's desired cascade layer:
:root { --no: ; --yes: initial; --is-shiki-dark: var(--no); } .shiki { background-color: var(--shiki-bg); color: var(--shiki-color); & span { color: var(--shiki-color); } }
(this
--shiki-color
is an implementation detail that could be obscured/minified into something like--_)s-c
. the user only needs to care about the public api, which is--is-shiki-dark
) -
for supporting multiple themes, cyclic dependency space toggles can be used instead of regular space toggles.
<pre> ... <span style=" --_s-c-light: hotpink; --_s-c-dark: red; --_s-c-hc-light: black; /* hc means "high contrast", _ means implementation detail */ --_s-c-hc-dark: white; ">
and shikiji would ship with this small stylesheet that can be imported inside or outside a cascade layer.
:root { --shiki-theme: var(--shiki--light); --shiki--light: var(--shiki-theme,); --shiki--dark: var(--shiki-theme,); --shiki--hc-light: var(--shiki-theme,); --shiki--hc-dark: var(--shiki-theme,); } .shiki, .shiki span { color: var(--shiki--light, var(--_s-c-light)) var(--shiki--dark, var(--_s-c-dark)) var(--shiki--hc-light, var(--_s-c-hc-light)) var(--shiki--hc-dark, var(--_s-c-hc-dark)); }
finally, the user only needs to set
--shiki-theme
in their own stylesheet.:root { --shiki-theme: var(--shiki--light); @media (prefers-contrast: more) { --shiki-theme: var(--shiki--hc-light); } @media (prefers-color-scheme: dark) { --shiki-theme: var(--shiki--dark); } @media (prefers-color-scheme: dark) and (prefers-contrast: more) { --shiki-theme: var(--shiki--hc-dark); } }
here's a small demo showing this technique in action: stackblitz.com/edit/js-txy3pa
let me know what you think or if i can clarify anything.
Update
As of 3 minutes ago, there is support for multiple themes, complete with the ability to modify prefixes. This makes the scope of this change much smaller :D At this point, I would be ok with just replacing inline color
style with --shiki-light
, so that !important
is not necessary in the custom css. Everything else could be left upto the user.
Alternative
css-variables
theming, but as i understand this makes it difficult to achieve full support for complex syntax highlighting, so not ideal.
Additional context
No response
Validations
- Follow our Code of Conduct
- Read the Contributing Guide.
- Check that there isn't already an issue that request the same feature to avoid creating a duplicate.