Skip to content

Instantly share code, notes, and snippets.

@SageStarCodes
Created August 18, 2020 00:24
Show Gist options
  • Save SageStarCodes/6c5785f19158ee389a0507d3a5f1165c to your computer and use it in GitHub Desktop.
Save SageStarCodes/6c5785f19158ee389a0507d3a5f1165c to your computer and use it in GitHub Desktop.
How to achieve theming in Stylus -- the dumb but working way
//So imagine you want your application to be usable at night and/or under different light conditions.
//You obviously need to implement some kind of theme switching and while you could use the
//@media (prefers-color-scheme: dark/light) and call it a day the target OS and browser might not support
//this query, so it is better to also implement a theme switcher.
//To do this in Stylus should be as easy as using selector-exists with variables, right? WRONG!
//There is an issue that has been opened in 2017 (still has not been fixed) where if there is anything after the
//selector-exists function call the code will fail to compile.
//To work around this issue I thought to myself: "Does vanilla CSS have variables?" -- it turns out it does!
//So in your main.styl file you just define
$primary = var(--primary-color) //yay for transparent CSS interop
$secondary = var(--secondary-color)
$... //you get the gist
//You can then normally use your color variables in your Stylus code, they will be output as the CSS literals we defined
//So
body
color $primary
//will output
body {
color: var(--primary-color);
}
//Cool, we are now outputting something the browser can understand!
//Now the fun part, we need to define the colors somewhere, I did this in a Vue/Nuxt component
//called top-toolbar because that's where I want my theme switcher to live.
//(yes, I could create a separate component for the theme switcher but I do not plan to use it anywhere else,
//so why bother)
//In the return object of the data function I defined a property holding all my themes
//
// data() {
// return {
// selectedTheme: "light",
// themes: [
// {value: "light", name: "Light",
// primary: "#262261", secondary: "#ffffff", accent: "#5ac7d2"},
// {value: "dark", name: "Dark",
// primary: "#ffffff", secondary: "#262261", accent: "#5ac7d2"}
// ]
// }
// },
//I then passed this array to a custom select component which emits the input event with the value of well...
//the value property of each theme object.
//I then have a watcher of the selectedTheme property which gets the HTML element and it's style object.
//I then set properties according to the selected theme:
//
// const rootStyle = document.getElementsByTagName("html")[0].style;
// let theme = this.themes.find(el => el.value === val); //val is the value we are watching
// rootStyle.setProperty("--primary-color", theme.primary);
// rootStyle.setProperty("--secondary-color", theme.secondary);
// rootStyle.setProperty("--accent-color", theme.accent);
//And there we go, on-the-fly theme switching -- don't forget to also define some default colors
//somewhere outside your component, otherwise your app will use whatever the default system colors are.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment