Why can't I animate custom properties (aka CSS variables)?
When this question was asked, it wasn't possible to animate custom properties, as @temani afif correctly pointed out -
since the UA has no way to interpret their contents
Since then, CSS Houdini have put together the CSS Properties and Values API specification
This specification extends [css-variables], allowing the registration
of properties that have a value type, an initial value, and a defined
inheritance behaviour, via two methods:A JS API, the registerProperty() method
A CSS at-rule, the @property rule
So now that you can register your own custom properties - including the type of the custom property - animating the custom property becomes possible.
To register the custom property via CSS - use the @property
rule
@property --o {
syntax: "<number>";
inherits: false;
initial-value: 0;
}
#one {
width: 50px;
height: 50px;
background-color: gold;
--o: 0;
animation: roll-o-1 2s infinite alternate ease-in-out both;
position: relative;
left: calc(var(--o) * 1px);
}
@keyframes roll-o-1 {
0% {
--o: 0;
}
50% {
--o: 50;
}
100% {
--o: 100;
}
}
#two {
width: 50px;
height: 50px;
background-color: silver;
animation: roll-o-2 2s infinite alternate ease-in-out both;
position: relative;
}
@keyframes roll-o-2 {
0% {
left: 0px;
}
50% {
left: 50px;
}
100% {
left: 100px;
}
}
@property --o {
syntax: "<number>";
inherits: false;
initial-value: 0;
}
<div id="one"></div>
<br>
<div id="two"></div>
CSS animate custom properties/variables
This can be achieved by defining variables using (as of writing this, not well-supported) @property
, which allows declaring types and that allows the browser to "understand", for example, that a certain property (variable) is a Number and then it can gradually animate/transition that variable.
Example Code:
@property --opacity {
syntax: '<number>'; /* <- defined as type number for the transition to work */
initial-value: 0;
inherits: false;
}
@keyframes fadeIn {
50% {--opacity: 1}
}
html {
animation: 2s fadeIn infinite;
background: rgba(0 0 0 / var(--opacity));
}
how to reset a CSS variable (aka custom properties) and use the fallback one?
You can unset the value using initial
to use the fallback one:
:root { --border-width-top: 2px; --border-width-right: 2px; --border-width-bottom: 2px; --border-width-left: 2px; --border-width: 0;}div { margin:5px; border-color: red; border-style: solid; border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));}
div.box { --border-width:initial; --border-width-top: 10px;}
<div>some content</div><div class="box">some content</div>
Accessing a CSS custom property (aka CSS variable) through JavaScript
You can use document.body.style.setProperty('--name', value);
:
var bodyStyles = window.getComputedStyle(document.body);
var fooBar = bodyStyles.getPropertyValue('--foo-bar'); //get
document.body.style.setProperty('--foo-bar', newValue);//set
More Information here.
Are CSS Custom Properties global across linked CSS documents?
In MDN:
Custom properties participate in the cascade: each of them can appear
several times, and the value of the variable will match the value
defined in the custom property decided by the cascading algorithm.
It works just like any other CSS properties. It should be declared in the ancestor of the target element. So usually it would be declared to the top-level element html
or root:
.
It does not matter whether CSS custom properties are declared in an external CSS file or the same file.
The following is a sample using two external CSS files. It works on Firefox, Safari and Chrome.
https://thatseeyou.github.io/css3-examples/basics/customproperty.html
variables.css :
:root {
--red: #f00;
--green: #0f0;
--blue: #00f;
}
style.css :
.red {
background-color: var(--red);
}
.green {
background-color: var(--green);
}
.blue {
background-color: var(--blue);
}
HTML :
<!DOCTYPE html>
<html lang="en">
<head>
<link href="customproperty/variables.css" rel="stylesheet">
<link href="customproperty/style.css" rel="stylesheet">
<style>
.module {
--red: #800;
--green: #080;
--blue: #008;
}
</style>
</head>
<body>
<div class="red">red</div>
<div class="green">green</div>
<div class="blue">blue</div>
<div class="module">
<div class="red">red in module</div>
<div class="green">green in module</div>
<div class="blue">blue in module</div>
<div>
</body>
</html>
Related Topics
Transparent Rounded Corners on Google Map
Custom.CSS Has Stopped Working in 32.0.1700.76 M Google Chrome Update
Twitter's Bootstrap 3 Grid, Changing Breakpoint and Removing Padding
Zebra Striping a Table with Hidden Rows Using CSS3
Why Use an Attribute Selector to Match Classes
Icon Fonts Not Loading in Ie11
How to Use Safe Center with Flexbox
Position:Relative Leaves an Empty Space
(Really) Long Background Image Does Not Render on iPad Safari
How to Apply Multiple Transform Declarations to One Element
Forcing Child to Obey Parent's Curved Borders in CSS
Centering the Image in Bootstrap
Combine CSS Attribute and Pseudo-Element Selectors
How to Prevent a CSS Keyframe Animation from Running on Page Load
Repeat CSS Background Image a Set Number of Times