revision:
CSS variables - also called custom properties - allow a value to be stored in one place, then to be referenced in multiple other places. They also make it possible to change CSS dynamically at runtime (which previously required a CSS preprocessor).
To use a CSS variable, it first need to be declared by writing it inside a CSS set, like is the case for any other CSS declaration. Custom properties or variables are entities defined by CSS authors that contain specific values to be reused throughout a document. They are set using custom property notation (e.g., --main-color: black;) and accessed using the var() function (e.g., color: var(--main-color);).
Example:
.card { --spacing: 1.2rem; padding: var(--spacing); margin-bottom: var(--spacing); }
Explanation: in above example, --spacing is the custom property with 1.2rem as the value, and var(--spacing) is the variable in use. Declaring a custom property is done using a custom property name that begins with a double hyphen (--), and a property value that can be any valid CSS value. Like any other property, this is written inside a ruleset.
Perhaps the most valuable reason to use custom properties is not repeating yourself (DRY code).
examples
This paragraph should have a blue background and yellow text.
This paragraph should have a yellow background and blue text.
This paragraph should have a green background and yellow text.
Codes:
<style> :root {--first-color: #16f;--second-color: #ff7;} #firstParagraph {background-color: var(--first-color); color: var(--second-color);} #secondParagraph {background-color: var(--second-color);color: var(--first-color);} #container {--first-color: #290; } #thirdParagraph {background-color: var(--first-color); color: var(--second-color);} </style> <p class="spec" id="firstParagraph">This paragraph should have a blue background and yellow text.</p> <p class="spec" id="secondParagraph">This paragraph should have a yellow background and blue text.</p> <div id="container"> <p class="spec" id="thirdParagraph">This paragraph should have a green background and yellow text.</p> </div>
1: they help DRY up your CSS. That is "Do not repeat yourself." Custom properties can make code easier to maintain, because you can update one value and have it reflected in multiple places. Careful though, overdoing abstraction can make have the opposite effect and make code less understandable.
2: they are particularly helpful for things like creating color themes on a website.
3: they unlock interesting possibilities in CSS. In no small part because they cascade.
4: the fact that they can be updated in JavaScript opens up even more interesting possibilities.
examples
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.
<div class="containerA" style="margin-left:4vw;"> <h3>Lorem Ipsum</h3> <p class="spec">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.</p> <p class="spec">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.</p> <p class="spec"> <button>Yes</button> <button>No</button> </p> </div> <style> .containerA {--blue: #1e90ff;--white: #ffffff;} h3 {border-bottom: 2px solid var(--blue);} .containerA {color: var(--blue); background-color: var(--white); padding: 1.5vw;} button {background-color: var(--white); color: var(--blue); border: 1px solid var(--blue); padding: 0.5vw;} </style>
The var() function is used to insert the value of a CSS variable. The syntax of the var() function is as follows: var(name, value), where the variable name must begin with two dashes (--) and it is case sensitive!
When you declare a CSS variable, you also give that variable a scope: a variable's scope determines where that variable will work, based on where you declare it. CSS variables can have either local or global scope. Global variables can be accessed/used through the entire document, while local variables can be used only inside the selector where it is declared. To create a variable with global scope, declare it inside the ":root" selector, which matches the document's root element. To create a variable with local scope, declare it inside the selector that is going to use it.
The place in the CSS hierarchy where you declare a CSS variable will determine its level of visibility throughout the lower levels of the hierarchy. A CSS variable used throughout the entire page is declared in the "::root pseudo-selector", or in the "html selector". This is because all the elements on the page are enclosed in one HTML element, so CSS variables declared in the HTML element or in its ::root selector will be visible for consumption from its children. Generally, a CSS variable is only visible to child elements of the parent element it is declared in.
examples
explanation: two global variables (--blue and --white) are declared. Then, the var() function is used to insert the value of the variables later in the style sheet.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.
<div class="container3"> <h3>Lorem Ipsum</h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.< /p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.< /p> <p> <button>Yes</button> <button>No< /button> </p> </div> <style> :root {--blue: #1e90ff; --white: #ffffff; --top-color: orange; --bottom-color: yellow;} h3{margin-left:4vw; border-bottom: 2px solid var(--blue);} .container3{margin-left:4vw; color: var(--blue); background-color:var(--white); padding: 1.5vw;} button{background-color: var(--white); color: var(--blue); border:1px solid var(--blue);} </style>
Advantages of using var() are:
1/ makes the code easier to read (more understandable),
2/ makes it much easier to change the color values
Inheritance: like with normal CSS, child elements inherit the CSS variable values of their parent elements (as long as the parent value is not overwritten in the child element).
Fallback values: every time you use var(), you must specify a CSS variable inside the parenthesis.
You also have the option to write a fallback value, a CSS value that is applied if your CSS variable doesn't work for some reason.
This could be due to a typo somewhere in your CSS, or the browser being unable to render the value you specify for your variable.
Fallback values are placed within the parenthesis of the var() call after the first argument, the CSS variable name. The two arguments are separated by a comma.
You can even add multiple fallback values for the same CSS property in case your first fallback doesn't work. In this case, fallback values are written in a list separated by commas, and are applied in that order.
examples
explanation: the snippet here below creates the --my-gradient variable and sets it to the value of both the --top-color and --bottom-color variables to create a gradient.
<div> <div class="demo1"></div> <div class="d1"></div> <div class="d2"></div> <div class="d3"></div> </div> <style> :root {--blue: #1e90ff; --white: #ffffff; --top-color: orange; --bottom-color: yellow; --my-gradient: linear-gradient(var(--top-color), var(--bottom-color));--my-gradient2: linear-gradient(var(--bottom-color), var(--top-color));} .demo1, .d1, .d2, .d3{margin-left: 5vw; height: 5vw; width: 10vw; border: 1px solid black;} .demo1{background-color: var(--top-color);} .d1{background-color: var(--bottom-color);} .d2{background-image: var(--my-gradient);} .d3{background-image: var(--my-gradient2);} </style>
Custom properties must be within a selector and start with two dashes (--): e.g. element{--main-bg-color:brown;}.
The selector given to the ruleset defines the scope that the custom property can be used in. A common best practice is to define custom properties on the :root pseudo-class, so that it can be applied globally across the HTML document: e.g. :root{--main-bg-color:brown}
With respect to naming, it's best to stick with letters, numbers, and dashes while making sure the custom property is defined inside of a valid selector. Custom property names are moreover case sensitive: e.g. --my-color will be treated as a separate custom property to --My-color.
Examples:
Nope, not within a selector: --foo: 1;
No, 0 or 1 dash won't work: foo: 1; -foo: 1;
Yep!: --foo: 1;
OK, but they're different properties: --FOO: 1; --Foo: 1;
Totally fine: --mainColor: red; --main-color: red;
Special characters are a no: --color@home: red; --black&blue: black;
You can set the value of a custom property with another custom property:
Examples:
--red: #a24e34;
--green: #01f3e6;
--yellow: #f0e765;
--error: var(--red);
--ok: var(--green);
--warning: var(--yellow)
P.S. the custom property value is used by specifying the custom property name inside the var() function, in place of a regular property value: e.g. element {background-color: var(--main-bg-color);}
Custom properties are surprisingly tolerant when it comes to the values they accept. They can be hex values, color functions, units of all kinds, and even strings of text.
Examples:
--brand-color: #990000;
--transparent-black: rgba(0, 0, 0, 0.5);
--spacing: 0.66rem;
--max-reading-length: 70ch;
--brandAngle: 22deg;
--visibility: hidden;
--my-name: "Fred Aster";
You can use custom properties to break up multi-part values.
Splitting colors
Examples:
button {--h: 100; --s: 50%; --l: 50%; --a: 1; background: hsl(var(--h) var(--s) var(--l) / var(--a)); }
button:hover { /* Change the lightness on hover */--l: 75%;}
button:focus { /* Change the saturation on focus */ --s: 75%;}
button[disabled] { /* Make look disabled */ --s: 0%; --a: 0.5; }
By breaking apart values like that, we can control parts of them in a way we never could before. Just look at how we did not need to declare all of the HSL arguments to style the hover, focus and disabled state of a button. We simply overrode specific HSL values when we needed to.
Shadows: box-shadow doesn't have a shorthand property for controlling the shadow's spread on its own. But we could break out the box-shadow spread value and control it as a custom property.
Examples:
button {--spread: 5px; box-shadow: 0 0 20px var(--spread) black;} button:hover {--spread: 10px; }
Gradients: there is no such thing as a background-gradient-angle (or the like) shorthand for gradients. With custom properties, we can just change that part as if there was such a thing.
Examples:
body {--angle: 180deg; background: linear-gradient(var(--angle),red, blue);} body.sideways {--angle: 90deg;}
Comma-separated values (like backgrounds): any property that supports multiple comma-separated values might be a good candidate for splitting values too, since there is no such thing as targeting just one value of a comma-separated list and changing it alone.
Examples:
body { --bg1: url(./img/angles-top-left.svg); --bg2: url(./img/angles-top-right.svg); --bg3: url(./img/angles-bottom-right.svg); --bg4: url(./img/angles-bottom-left.svg); --bg5: url(./img/bonus-background.svg); background-image: var(--bg1), var(--bg2), var(--bg3), var(--bg4); } @media (min-width: 1500px) { body {background-image: var(--bg1), var(--bg2), var(--bg3), var(--bg4), var(--bg5);} }
Grids: we can take the "grid-template-columns" property and abstract its values into custom properties to make a super flexible grid system.
Examples:
.grid {display: grid; --edge: 10px; grid-template-columns: var(--edge) 1fr var(--edge);} @media (min-width: 1000px) { .grid {--edge: 15%;} }
Transforms: CSS will soon get individual transforms but we can get it sooner with custom properties. The idea is to apply all the transforms an element might get up front, then control them individually as needed.
Examples:
button {transform: var(--scale, scale(1)) var(--translate, translate(0));} button:active {--translate: translate(0, 2px);} button:hover {--scale: scale(0.9);}
Concatenation of unit types: There are times when combining parts of values doesn't work quite how you might hope. For example, you can't make 24px by smashing 24 and px together. It can be done though, by multiplying the raw number by a number value with a unit.
Examples:
body { --value: 24;--unit: px; /* Nope */ font-size: var(--value) + var(--unit); /* Yep */ font-size: calc(var(--value) * 1px); /* Yep */ --pixel_converter: 1px; font-size: calc(var(--value) * var(--pixel_converter)); }
By declaring a custom property on the :root pseudo-class and using it where needed throughout the document, a CSS author can reduce the need for repetition.
examples
<style> :root{--main-bg-color: blue;} .een{color: white; background-color: var(--main-bg-color); margin: 1vw; width: 5vw; height: 5vw; display: inline-block;} .twee{color: white; background-color: black; margin: 1vw; width: 15vw; height: 7vw; display: inline-block; } .drie{color: white; background-color: var(--main-bg-color); margin: 1vw; width: 25vw;} .vier{color: white; background-color: var(--main-bg-color); margin: 1vw; width: 10vw;} .vijf{background-color: var(--main-bg-color);} </style> <div style="margin-left:4vw;"> <div class="een">1:</div> <div class="twee">2: Text <span class="vijf">5 - more text</span></div> <input class="drie"/> <textarea class="vier">4: Lorem Ipsum</textarea> </div>
Custom properties do inherit. This means that if no value is set for a custom property on a given element, the value of its parent is used.
Example:
<div class="one"> <div class="two"> <div class="three"></div> <div class="four"></div> </div> </div> <style> .two {--test: 10px;} .three {--test: 2em;} </style>
In this case, the results of var(--test) are: for the class="two" element: 10px; for the class="three" element: 2em; for the class="four" element: 10px (inherited from its parent); for the class="one" element: invalid value, which is the default value of any custom property
Using the var() function, you can define multiple fallback values when the given variable is not yet defined; this can be useful when working with Custom Elements and Shadow DOM.
The first argument to the function is the name of the custom property to be substituted. The second argument to the function, if provided, is a fallback value, which is used as the substitution value when the referenced custom property is invalid.
The function only accepts two parameters, assigning everything following the first comma as the second parameter. If that second parameter is invalid, such as if a comma-separated list is provided, the fallback will fail.
Example:
.two {color: var(--my-var, red); /* Red if --my-var is not defined */} .three {background-color: var(--my-var, var(--my-background, pink)); /* pink if --my-var and -my-background are not defined */} .three { background-color: var(--my-var, --my-background, pink); /* Invalid: "--my-background, pink" */}
Including a custom property as a fallback, as seen in the second example above, is the correct way to provide more than one fallback. The technique has been seen to cause performance issues as it takes more time to parse through the variables.
Overriding global variables with local variables: sometimes we want the variables to change only in a specific section of the page. Then, we can re-declare the variable inside the selector. The local variable will override the global variable for the selected elements.
Add a new local variable: if a variable is to be used on only one single place, a new local variable can be declared.
Variables in media queries: we first declare a new local variable named --fontsize for the respective class. We set its value to 25 pixels. Then we use it in other related classes. Then, we create a @media rule that says "When the browser's width is 450px or wider, change the --fontsize variable value of the class to 50px."
CSS variables have access to the DOM, which means that they can be changed with JavaScript.
examples
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.
<div class="container1"> <h3>Lorem Ipsum</h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit.</p> <p> <button>Yes</button> <button>No</button> </p> </div> <br> <button class="drie" type="button" onclick="myFunction_get()">Get CSS variable with JavaScript</button> <button class="drie" type="button" onclick="myFunction_set()">Change CSS variable with JavaScript</button> <style> :root{--main-bg-color: blue;} h3{margin-left:4vw; border-bottom: 2px solid var(--blue);} .container1{margin-left:4vw; color: var(--blue); background-color:var(--white); padding: 1.5vw;} button{background-color: var(--white); color: var(--blue); border:1px solid var(--blue);} </style> <script> // Get the root element var r = document.querySelector(':root'); //Create a function for getting a variable value function myFunction_get() { // Get the styles (properties and values) for the root var rs = getComputedStyle(r); // Alert the value of the --blue variable alert("The value of --blue is: " + rs.getPropertyValue('--blue')); } // Create a function for setting a variable value function myFunction_set() { // Set the value of variable --blue to another value (in this case "lightblue") r.style.setProperty('--blue', 'lightblue'); } </script>
examples
<div class="container2"> <div class="toggle-controls"><button class="toggle-controls_button" type="button">Click to choose blend & color</button></div> <div class="controls"> <label for="multiply"> <input type="radio" id="multiply" name="blends" value="multiply"> Multiply</label> <label for="overlay"> <input type="radio" id="overlay" name="blends" value="overlay"> Overlay</label> <label for="screen"> <input type="radio" id="screen" name="blends" value="screen"> Screen</label> <label for="darken"> <input type="radio" id="darken" name="blends" value="darken"> Darken</label> <label for="lighten"> <input type="radio" id="lighten" name="blends" value="lighten"> Lighten</label> <label for="color-dodge"> <input type="radio" id="color-dodge" name="blends" value="color-dodge"> Color-Dodge</label> <label for="color-burn"> <input type="radio" id="color-burn" name="blends" value="color-burn"> Color-Burn</label> <label for="soft-light"> <input type="radio" id="soft-light" name="blends" value="soft-light"> Soft-Light</label> <label for="hard-light"> <input type="radio" id="hard-light" name="blends" value="hard-light"> Hard-Light</label> <label for="exclusion"> <input type="radio" id="exclusion" name="blends" value="exclusion"> Exclusion</label> <label for="difference"> <input type="radio" id="difference" name="blends" value="difference"> Difference</label> <label for="hue"> <input type="radio" id="hue" name="blends" value="hue"> Hue</label> <label for="saturation"> <input type="radio" id="saturation" name="blends" value="saturation"> Saturation</label> <label for="color"> <input type="radio" id="color" name="blends" value="color"> Color</label> <label for="luminosity"> <input type="radio" id="luminosity" name="blends" value="luminosity"> Luminosity</label> <label for="normal"> <input type="radio" id="normal" name="blends" value="normal"> Reset</label> <input type="color" class="color-picker" id="colorPicker" value="#ff0000"> </div> </div> <style> .container2 {--blend-mode: multiply; --bg-color: #ff0000;--page-overflow: hidden;width: 100%; height: 100vh; overflow: var(--page-overflow); position: relative; background-color: var(--bg-color); background-image: url(../pics/3.jpg); background-repeat: no-repeat; background-position: top center; background-size: cover; background-blend-mode: var(--blend-mode);} .toggle-controls {position: absolute; top: 0; left: 0; width: 15vw; padding: 1vw;background-color: rgba(0,0,0,.5); z-index: 2;} .toggle-controls_button {--webkit-appearance: none; --moz-appearance: none; padding: 0.5vw; background-color: transparent; color: white; text-transform: uppercase; text-align: center; cursor: pointer; } .controls {--left-pos: translate(-25vw);--controls-display: hidden;--transparency: 0;position: absolute; top: 12.5vw; left: 0; transform: var(--left-pos); opacity: var(--transparency); max-width: 15vw; overflow: var(--page-overflow); padding: 1vw; background-color: white; transition: transform 1s, opacity 1s;} .controls label {display: inline-block; width: 100%; margin-bottom: 0.5vw; font-weight: bold; color: #444;} label:last-of-type { text-transform: uppercase; border-bottom: 3px dotted #444; padding-bottom: 0.5vw;} .color-picker { border: none; width: 10vw; height: 4vw; margin-top: 0.5vw; } </style> <script> //function to open and close the sidebar with the controls (with the click to choos button) const toggleControls = (elem, container, isOpen) => { //if the sidebar is open these values applied to the appropriate CSS variables will close it if(isOpen) { elem.style.setProperty('--left-pos', 'translate(-25vw)'); elem.style.setProperty('--controls-display', 'hidden'); elem.style.setProperty('--transparency', '0'); container.style.setProperty('--page-overflow', 'hidden'); } //otherwise the sidebar is closed and this code opens it else { elem.style.setProperty('--controls-display', 'visible'); elem.style.setProperty('--transparency', '1'); elem.style.setProperty('--left-pos', 'translate(0)'); container.style.setProperty('--page-overflow', 'auto'); } }; //function to select a blend mode const pickBlendMode = (blendMode, elem) => { let chosenMode; //if the radio button is checked, grab its value and set it as value of the --blend-mode CSS variable if (blendMode.checked) { chosenMode = blendMode.value; elem.style.setProperty('--blend-mode', chosenMode); } }; //function to select background color from color picker and use it to set the value of the --bg-color CSS variable const setBgColor = (picker, elem) => { let chosenColor = picker.value; elem.style.setProperty('--bg-color', chosenColor); }; //vars const colorPicker = document.querySelector("#colorPicker"), toggleButton = document.querySelector('.toggle-controls_button'), controlsSidebar = document.querySelector('.controls'), docElement = document.querySelector('.container2'), //turn blends from node list of radio buttons into array, so you can use array methods on this variable blends = [].slice.call(document.getElementsByName("blends")); //picking blend modes by looping over the radio buttons, attaching click events and calling the appropriate function defined above blends.forEach((radioBtn) => { radioBtn.addEventListener('click', () => pickBlendMode(radioBtn, docElement)); }); //picking a color: attach a listener for when users change color on the color picker colorPicker.addEventListener('change', () => setBgColor(colorPicker, docElement)); //toggling controls panel on button click toggleButton.addEventListener('click', () => { //retrieve the current value of the --left-pos variable const cssStyles = getComputedStyle(controlsSidebar); let cssVal = String(cssStyles.getPropertyValue('--left-pos')).trim(); //hide or show the sidebar with the controls depending on the value of cssVal: -250px means the sidebar is closed //(the parameter isOpen in the toggleControls() function is false), therefore the button click //needs to open it, otherwise the button click will close it if(cssVal === 'translate(-25vw)') { toggleControls(controlsSidebar, docElement, false); } else { toggleControls(controlsSidebar, docElement, true); } }); </script>
To get the CSS variable's value in Javascript use "getComputedStyle()" to get the real-time CSS properties of the element.
CSS variables are applied on the root element of the document. This root element can be referred through "document.documentElement".
getComputedStyle() returns all CSS properties of the element. To get the value of a specific CSS property we need to use "getPropertyValue()" on it.
Example 6:
"var bg_color_val = getComputedStyle(document.documentElement).getPropertyValue('--bg-color');"
To set the CSS variable's value in Javascript: first access the styles of the root element with "document.documentElement.style". Then use "setProperty" to set the variable's value
Example 7:
"document.documentElement.style.setProperty('--bg-color', '#999999');"
Hover effects: change background colors
examples
<div> <div class="btn">Hover me</div> <div class="btn red">Hover me</div> <div class="btn teal">Hover me</div> <div class="btn orange">Hover me</div> <div class="btn green">Hover me</div> </div> <style> .btn {border: 2px solid var(--color, black); background: white; font-size: 1vw; line-height: 2vw; border-radius: .2vw; margin-bottom: .5vw;text-align: center;} .btn:hover {cursor: pointer; background: var(--color, black);color: white;} .btn.red {--color: red;} .btn.yellow {--color: yellow;} .btn.green {--color: green;} .btn.orange {--color: orange;} .btn.teal {--color: teal;} </style>
Hover effects: move elements
examples
<ul> <li>Hover on me!</li> <li>Hover on me!</li> <li>Hover on me!</li> </ul> <style> ul {padding: 2vw; list-style: none; width: 20vw;} li {font: normal 1.8vw sans-serif; padding: 2vw; transition: 0.4s; margin: 1vw; color: #444; cursor: pointer; background-color: yellow; } ul {--tiny-shadow: 4px 4px 2px 0 rgba(0, 0, 0, 0.8);--animate-right: translateX(2vw);} li {box-shadow: var(--tiny-shadow);} li:hover {transform: var(--animate-right);} </style>
Managing CSS variables
examples
CSS variable managed through JS
<div> <div class="head_background">some text</div> <div class="change_color"> <span class="change_color--red">red</span> <span class="change_color--green">green</span> <span class="change_color--blue">blue</span> <span class="change_color--yellow">yellow</span> <span class="change_color--purple">purple</span> <span class="change_color--pink">pink</span> </div> </div> <style> .head_background {width:80vw; height:10vw;line-height: 2vw; text-transform: uppercase; background-color: var(--basic-bg-grey); /*reusing CSS variable*/ border: 0.2vw solid #000000;} .change_color--red { background: #FF0000; } .change_color--green { background: #008000;} .change_color--blue { background: #87CEEB;} .change_color--yellow { background: #FFFF00;} .change_color--purple { background: #9370DB; } .change_color--pink { background: #FF69B4;} .head_background, .change_color {text-align: center; margin: 2vw; } .change_color span { margin: 0 1vw; display: inline-block; padding: 1vw 0; min-width: 7vw; border: 2px solid transparent; cursor: pointer;} </style> <script> var div = document.querySelector('.head_background'); var color = document.querySelectorAll('.change_color span'); color.forEach((changeColor) => { changeColor.addEventListener('click', () => { const clickedStyle = getComputedStyle(changeColor); const backgroundColor = clickedStyle.backgroundColor; div.style.setProperty('--basic-bg-grey', backgroundColor); }) }); </script>
Creating theme styles with CSS variables
examples
CSS variables make creating site-wide theme styles easy.
<div class="three"> <div class="theme"> <button value="dark">dark</button> <button value="calm">calm</button> <button value="light">light</button> </div> <article> <h3>Hello World</h3> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ... Vivamus elementum semper nisi. Aenean v <h4>Can the world hear?</h4> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ... Vivamus elementum semper nisi. Aenean v </article> </div> <style> :root{--bg: green; --bg-text: blue;} .three{ width: 35vw; height: auto; background-color: var(--bg, white); color: var(--bg-text, black)} .three article {padding: 0.5vw;} .three article h3 {margin-top: 1vw;} </style> <script> const root = document.documentElement; const themeBtns = document.querySelectorAll('.theme > button') themeBtns.forEach((btn) => { btn.addEventListener('click', handleThemeUpdate) }) function handleThemeUpdate(e) { switch(e.target.value) { case 'dark': root.style.setProperty('--bg', 'black') root.style.setProperty('--bg-text', 'white') break case 'calm': root.style.setProperty('--bg', '#B3E5FC') root.style.setProperty('--bg-text', '#37474F') break case 'light': root.style.setProperty('--bg', 'white') root.style.setProperty('--bg-text', 'black') break } } </script>
Using JavaScript to update CSS variables
examples
updating CSS variables with JavaScript
<main class="booth"> <aside class="slider"> <label>Move this 👇 </label> <input class="booth-slider" type="range" min="-50" max="50" value="-50" step="5"/> </aside> <section class="color-boxes"> <div class="color-box" id="1"><input value="red"/></div> <div class="color-box" id="2"><input/></div> <div class="color-box" id="3"><input/></div> <div class="color-box" id="4"><input/></div> <div class="color-box" id="5"><input/></div> <div class="color-box" id="6"><input/></div> </section> <footer class="instructions"> 👉🏻 Move the slider<br/> 👉🏻 Write any color in the red boxes </footer> </main> <style> main {margin: 0; color: rgba(255,255,255,0.9); font-family: 'Shadows Into Light Two', cursive;} main.booth {min-height: 20vh; display: flex; justify-content: center; align-items: center;} .slider{position: relative;background: rgba(0,0,0,0.4); margin: 1vw 2vw; border-radius: 0.5vw; } .instructions{position: relative;background: rgba(0,0,0,0.4); margin: 1vw 0.2vw; border-radius: 0.5vw; } .slider {right: 1vw; top:1vw;} .slider > * {display: block;} .instructions {text-align: right; bottom: 0; background: initial;color: black;} .color-boxes {background: red; box-shadow: 1vw 1vw 3vw rgba(0,0,0,0.4); border-radius: 0.3vw; transform: perspective(50vw) rotateY( calc(var(--slider) * 1deg)); transition: transform 0.3s;} .color-box {padding: 1vw 3.5vw; margin-bottom: 0.5vw; border: 1px solid rgba(255,255,255,0.2); border-radius: 0.3vw; box-shadow: 1vw 1vw 3vw rgba(0,0,0,0.4);} .color-box:nth-child(1) {background: var(--bg-1);} .color-box:nth-child(2) {background: var(--bg-2);} .color-box:nth-child(3) {background: var(--bg-3);} .color-box:nth-child(4) {background: var(--bg-4);} .color-box:nth-child(5) {background: var(--bg-5);} .color-box:nth-child(6) {background: var(--bg-6);} </style> <script> const inputs = document.querySelectorAll('.color-box > input') const root1= document.documentElement const range = document.querySelector('.booth-slider') //as slider range's value changes, do something range.addEventListener('input', handleSlider) //as the value in the input changes, do something. inputs.forEach(input => { input.addEventListener('input', handleInputChange) }) function handleInputChange (e) { let value = e.target.value let inputId = e.target.parentNode.id let inputBg = `--bg-${inputId}` root1.style.setProperty(inputBg, value) } function handleSlider (e) { let value = e.target.value root1.style.setProperty('--slider', value) } </script>