{"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

: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

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

CSS as an API?<\/h3>\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

\/* <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

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

Custom Property Flexibility<\/h3>\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

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

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 (--foo: ;<\/code> hack)<\/em><\/a><\/p><\/blockquote>\n\n\n\n

Bram points out this “basic” state-flipping quality that a custom property can pull off:<\/p>\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

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

\/* 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

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: --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

I’m reminded of this Vue proposal<\/a>. I’m not sure if it went anywhere, but the idea is that the state of a component would automatically<\/em> be exposed as CSS custom properties. <\/p>\n\n\n\n

<template>\n  <div class=\"text\">Hello<\/div>\n<\/template>\n\n<script>\nexport default {\n  data() {\n    return {\n      color: 'red'\n    }\n  }\n}\n<\/script>\n\n<style vars=\"{ color }\">\n.text {\n  color: var(--color);\n}\n<\/style><\/code><\/pre>\n\n\n\n

By virtue of having color<\/code> as part of the state of this component, then --color<\/code> is available as state to the CSS of this component. I think that’s a great idea. <\/p>\n\n\n\n

What if every time you used useState<\/code> in React, CSS custom properties were put on the :root<\/code> and were updated automatically. For example, if you did this:<\/p>\n\n\n\n

import React, { useState } from 'https:\/\/cdn.skypack.dev\/react@^16.13.1';\nimport ReactDOM from 'https:\/\/cdn.skypack.dev\/react-dom@^16.13.1';\n\nconst App = () => {\n  const [ activeColor, setActiveColor ] = useState(\"red\");\n  return(\n    <div className=\"box\">\n      <h1>Active Color: {activeColor}<\/h1>\n      <button onClick={() => {setActiveColor(\"red\")}}>red<\/button>\n      <button onClick={() => {setActiveColor(\"blue\")}}>blue<\/button>\n    <\/div>\n  );\n}\n\nReactDOM.render(<App \/>,\ndocument.getElementById(\"root\"))<\/code><\/pre>\n\n\n\n

And you knew you could do like:<\/p>\n\n\n\n

.box {\n  border-color: 2px solid var(--activeColor);\n}<\/code><\/pre>\n\n\n\n

Because the state automatically mapped itself to a custom property. Someone should make a useStateWithCustomProperties<\/code> hook or something to do that. #freeidea<\/strong><\/p>\n\n\n\n

Libraries like React and Vue are for building UI. I think it makes a lot of sense that the state that they manage is automatically exposed to CSS.<\/p>\n\n\n

Could browsers give us more page state as environment variables?<\/h3>\n\n\n

Speaking of state that CSS should know about, I’ve seen quite a few demos that do fun stuff by mapping over things, like the current mouse position or scroll position, over to CSS. I don’t think it’s entirely unreasonable to ask for that data to be natively exposed to CSS. We already have the concept of environment variables, like env(safe-area-inset-top)<\/code>, and I could see that being used to expose page state, like env(page-scroll-percentage)<\/code> or env(mouseY)<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"

Here’s a fun idea from James Stanley: a CSS file (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","protected":false},"author":3,"featured_media":332260,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4],"tags":[1036,1114],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/01\/birds-clouds.jpg?fit=1200%2C600&ssl=1","jetpack-related-posts":[{"id":332699,"url":"https:\/\/css-tricks.com\/usestateincustomproperties\/","url_meta":{"origin":330632,"position":0},"title":"useStateInCustomProperties","date":"January 21, 2021","format":false,"excerpt":"In my recent \"Custom Properties as\u00a0State\" post, one of the things I mentioned was that theoretically, UI libraries, like React and Vue, could automatically map the state they manage over to CSS Custom Properties so we could use that state right there if we wanted. Someone should make a\u00a0useStateWithCustomProperties\u00a0hook or\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/01\/custom-properties-state.gif?fit=792%2C390&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":312969,"url":"https:\/\/css-tricks.com\/using-custom-property-stacks-to-tame-the-cascade\/","url_meta":{"origin":330632,"position":1},"title":"Using Custom Property “Stacks” to Tame the Cascade","date":"June 22, 2020","format":false,"excerpt":"Since the inception of CSS in 1994, the cascade and inheritance have defined how we design on the web. Both are powerful features but, as authors, we've had very little control over how they interact. Selector specificity and source order provide some minimal \"layering\" control, without a lot of nuance\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/06\/custom-property-stacks.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":325393,"url":"https:\/\/css-tricks.com\/color-theming-with-css-custom-properties-and-tailwind\/","url_meta":{"origin":330632,"position":2},"title":"Color Theming with CSS Custom Properties and Tailwind","date":"November 19, 2020","format":false,"excerpt":"Custom properties not only enable us to make our code more efficient, but allow us to work some real magic with CSS too. One area where they have huge potential is theming. At Atomic Smash we use Tailwind CSS, a utility class framework, for writing our styles. In this article,\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/11\/tailwind-custom-properties-color-theming.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":254332,"url":"https:\/\/css-tricks.com\/css-custom-properties-theming\/","url_meta":{"origin":330632,"position":3},"title":"CSS Custom Properties and Theming","date":"May 1, 2017","format":false,"excerpt":"We posted not long ago about the difference between native CSS variables (custom properties) and preprocessor variables. There are a few esoteric things preprocessor variables can do that native variables cannot, but for the most part, native variables can do the same things. But, they are more powerful because of\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":358263,"url":"https:\/\/css-tricks.com\/open-props-and-custom-properties-as-a-system\/","url_meta":{"origin":330632,"position":4},"title":"Open Props (and Custom Properties as a System)","date":"December 6, 2021","format":false,"excerpt":"Perhaps the most basic and obvious use of CSS custom properties is design tokens. Colors, fonts, spacings, timings, and other atomic bits of design that you can pull from as you design a site. If you pretty much only pull values from design tokens, you'll be headed toward clean design\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/12\/Screen-Shot-2021-12-01-at-1.01.18-PM.png?fit=1200%2C1013&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":333595,"url":"https:\/\/css-tricks.com\/a-complete-guide-to-custom-properties\/","url_meta":{"origin":330632,"position":5},"title":"A Complete Guide to Custom Properties","date":"April 27, 2021","format":false,"excerpt":"Everything important and useful to know about CSS Custom Properties. Like that they are often referred to as \"CSS Variables\" but that's not their real name.","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/09\/custom-properties-code.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/01\/birds-clouds.jpg?fit=1024%2C512&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/330632"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=330632"}],"version-history":[{"count":10,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/330632\/revisions"}],"predecessor-version":[{"id":332287,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/330632\/revisions\/332287"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/332260"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=330632"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=330632"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=330632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}