{"id":330632,"date":"2021-01-05T08:05:43","date_gmt":"2021-01-05T16:05:43","guid":{"rendered":"https:\/\/css-tricks.com\/?p=330632"},"modified":"2021-01-05T12:07:42","modified_gmt":"2021-01-05T20:07:42","slug":"custom-properties-as-state","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/custom-properties-as-state\/","title":{"rendered":"Custom Properties as State"},"content":{"rendered":"\n
Here’s a fun idea<\/a> from James Stanley: a CSS file<\/a> (that presumably updates daily) containing CSS custom properties for “seasonal” colors (e.g. spring is greens, fall is oranges). You’d then use the values to theme your site, knowing that those colors change slightly from day to day. <\/p>\n\n\n\n\n\n\n\n This is what I got while writing this:<\/p>\n\n\n\n I think it would be more fun if the CSS file provided was just<\/em> the custom properties and not the opinionated other styles (like what sets the body background and such). That way you could implement the colors any way you choose without any side effects.<\/p>\n\n\n This makes me think that a CDN-hosted CSS file like this could have other<\/em> useful stuff, like today’s date for usage in pseudo content, or other special time-sensitive stuff. Maybe the phase of the moon? Sports scores?! Soup of the day?! <\/p>\n\n\n\n It’s almost like a data API that is tremendously easy to use. Pseudo content is even accessible content these days \u2014 but you can’t select the text of pseudo-elements, so don’t read this as an actual endorsement of using CSS as a content API.<\/p>\n\n\n Will Boyd just blogged about what is possible<\/a> to put in a custom property. They are tremendously flexible. Just about anything is a valid custom property value and then the usage tends to behave just how you think it will. <\/p>\n\n\n\n Bram Van Damme latched onto that flexiblity while covering Will’s article:<\/p>\n\n\n\n That\u2019s why you can use CSS Custom Properties to:<\/p> \u2022 perform conditional calculations<\/a><\/p> \u2022 pass data from within your CSS to your JavaScript<\/a><\/p> \u2022 inject skin tone \/ hair color modifiers onto Emoji <\/a><\/p> \u2022 toggle multiple values with one custom property ( Bram points out this “basic” state-flipping quality that a custom property can pull off:<\/p>\n\n\n\n Add a couple of scoops of complexity and you get The Raven<\/a> (media queries with custom properties). <\/p>\n\n\n\n I’d absolutely love to see something happen in CSS to make this easier. Using CSS custom properties for generic state would be amazing. We could apply arbitrary styles when the UI is in arbitrary states! Think of how useful media queries are now, or that container queries will be, but compounded because it’s arbitrary state, not just state that those things expose. <\/p>\n\n\n\n Bram covered that<\/a> as well, mentioning what Lea Verou called “higher level custom properties”<\/a>:<\/p>\n\n\n\n Will calls them “CSS variables” which is super<\/em> common and understandable. You’ll read (and I have written) sentences often that are like “CSS variables (a.k.a CSS Custom Properties)” or “CSS Custom Properties (a.k.a CSS Variables.” \u0160ime Vidas recently noted<\/a> there is a rather correct way to refer to these things: :root {\n --seasonal-bg: hsl(-68.70967741935485,9.419354838709678%,96%);\n --seasonal-bgdark: hsl(-68.70967741935485,9.419354838709678%,90%);\n --seasonal-fg: hsl(-68.70967741935485,9.419354838709678%,30%);\n --seasonal-hl: hsl(-83.70967741935485,30.000000000000004%,50%);\n --seasonal-hldark: hsl(-83.70967741935485,30.000000000000004%,35%);\n}<\/code><\/pre>\n\n\n\n
CSS as an API?<\/h3>\n\n\n
\/* <div class=\"soup\">The soup of the day is: <\/div> *\/\n.soup::after {\n content: var(--soupOfTheDay); \/* lol kinda *\/\n}<\/code><\/pre>\n\n\n\n
Custom Property Flexibility<\/h3>\n\n\n
body {\n \/* totally fine *\/\n --rgba: rgba(255, 0, 0, 0.1);\n background: var(--rgba);\n\n \/* totally fine *\/\n --rgba: 255, 0, 0, 0.1;\n background: rgba(var(--rgba));\n\n \/* totally fine *\/\n --rgb: 255 0 0;\n --a: 0.1;\n background: rgb(var(--rgb) \/ var(--a));\n}\n\nbody::after {\n \/* totally fine *\/\n --song: \"I need quotes to be pseudo content \\A and can't have line breaks without this weird hack \\A but still fairly permissive (💧💧💧) \";\n content: var(--song);\n white-space: pre;\n}<\/code><\/pre>\n\n\n\n
--foo: ;<\/code> hack)<\/em><\/a><\/p><\/blockquote>\n\n\n\n
:root {\n --is-big: 0;\n}\n\n.is-big {\n --is-big: 1;\n}\n\n.block {\n padding: calc(\n 25px * var(--is-big) +\n 10px * (1 - var(--is-big))\n );\n border-width: calc(\n 3px * var(--is-big) +\n 1px * (1 - var(--is-big))\n );\n}<\/code><\/pre>\n\n\n\n
\/* Theoretical! *\/\n\n.square {\n width: 2vw;\n padding: 0.25vw;\n aspect-ratio: 1\/1;\n\n @if (var(--size) = big) {\n width: 16vw;\n padding: 1vw;\n }\n}\n\n.my-input {\n @if(var(--pill) = on) {\n border-radius: 999px;\n }\n}<\/code><\/pre>\n\n\n
About that naming<\/h3>\n\n\n
--this-part<\/code> is the custom property and
var(--this-part)<\/code> is the variable, which comes right from usage in the spec<\/a>. <\/p>\n\n\n
JavaScript Library State… Automatically?<\/h3>\n\n\n