Reputation: 579
From a CSS Working Group post:
Custom properties are used for more than just variables [...]
Contradicting what a lot of people think (see this), this post confirms not only that variables and custom properties are not the same thing, but that custom properties may be used for other things than variables.
My question is about the last part. Has anyone ever come across some CSS code where custom properties were used for something other than variables?
Upvotes: 4
Views: 2553
Reputation: 272817
The other questions explained custom properties and CSS variables but what if we make it simple and say that custom properties are simply here to allow us to add more properties in addition to the CSS default ones. Of course, a custom property alone is useless as the browser will do nothing with it and that's why in 99% of the cases they are used with CSS variables.
The other fact is that when doing CSS we will intuitively think about using default CSS properties in order to do what we want and when we face a complex situation we will try to combine a lot of properties, pseudo-element, etc in order to achieve our needs. But what if we think differently and we start using custom properties for such purpose? What if instead of complex CSS code we simply write a custom property and implement a JS/jQuery code that will do the job for us.
Let's take a simple and common example. You have an element that you want to make absolute position in order to use it as an overlay of his parent element. With CSS we will do something like this:
.block {
height:100px;
width:100px;
margin:20px;
border:1px solid red;
position:relative; /* we usually forget this !*/
}
.overlay {
position:absolute;
top:0;
right:0;
left:0; /*sometimes we use width:100% but it won't work with padding!*/
bottom:0;
padding:5px;
z-index:1; /* we can forget this sometimes*/
background:rgba(0,0,0,0.5);
}
<div class="block">
<span class="overlay"></span>
some text here
</div>
This is pretty easy and we can use the same class everywhere if we want to have the same thing. But we can consider a custom property that will reduce the CSS code and make it easier:
$('*').each(function() {
if ($.trim($(this).css('--overlay')) === "top") {
$(this).css({
'position': 'absolute',
'top': 0,
'bottom': 0,
'left': 0,
'right': 0,
'z-index':2
});
$(this).parent().css('position','relative');
} else {
//we test the other values and we do the necessary changes
}
})
.block {
height: 100px;
width: 100px;
margin: 20px;
border: 1px solid red;
}
.overlay {
--overlay: top;
background: rgba(0, 0, 0, 0.5);
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div class="block">
<span class="overlay"></span>
some text here
</div>
I know that the first thought is "Why bother using all this code for such simple thing that we can do with CSS?" and "What if the property changes? What if the parent has a position already set?" It's true, but this is a very simplified example. Imagine you build a JS or jQuery library where your provide many custom properties for complex stuffs (create common CSS shapes, do complex transformation where it's hard to calculate the values, etc) and you provide a documentation for each one with their respective values.
It's like a JS/jQuery library that tells you to add a class to your element and call one function and then you have a responsive slider, an interactive map, a twitter widget, etc. Why not doing the same with custom properties? We ask people to include the library and simply write CSS, then see the magic.
We can also consider this like an upgrade by adding more useful properties in order to make things easier. Exactly like the CSS makers do BUT we do it by our self and don't wait until there is a new specification and until it's approved.
Let's take the example of flexbox. Before flexbox, if we want to have N numbers of div inside a container having exactly the same size and filling all the container we are obliged to write some complex code that we have to adjust each time we add a new element. Now with flexbox, we simply set flex:1
and that's it! The browser will do all the complicated stuff for us.
We can do exactly the same. We create our custom properties to make things easier and we share it to the community. People will start using them and may find them useful then they can become a reference for common problems. Maybe some browser will even think about an implementation to integrate them.
So custom properties can also be a way to contribute to the enhancement of CSS.
Upvotes: 2
Reputation: 723588
Note that the context of the text you cite is the CSSWG justifying why --foo
and var(--foo)
are used in place of $foo
. My guess is that their saying "Custom properties are used for more than just variables" is alluding to the fact that the --foo
identifier syntax is set to appear in other places, used for other custom things, such as custom media queries that were originally in MQ4 and are now in MQ5. Clearly, those aren't cascading variables, because media queries don't cascade (their enclosed rules do). (Although, if that's the case, "Custom properties" should have been something else, but it's likely the CSSWG wasn't thinking of a proper collective name for these things yet.)
Has anyone ever come across some CSS code where custom properties were used for something other than variables?
I haven't come across any real-world examples, but I just knocked up an example that uses JavaScript to toggle a class on an element based on a custom property, which in turn affects a selector elsewhere in the CSS:
let p = document.querySelector('p');
if (window.getComputedStyle(document.documentElement).getPropertyValue('--boolean').trim() === "'true'")
p.classList.add('toggle');
else
p.classList.remove('toggle');
:root {
--boolean: 'true';
}
p.toggle {
color: #f00;
}
p::before {
content: 'Value of --boolean is "' var(--boolean) '"';
}
<p>
The caveat, of course, being that this is CSS and JavaScript. You cannot use custom properties for anything other than cascading variables in CSS alone, because custom properties participate in the cascade much like any other CSS property and don't exist outside of it. This is why authors conflate the two terms in everyday usage — because any differences between them are academic. Any other part of a stylesheet that wants to depend on a custom property must work with a script in order to use it.
You might be wondering why something like this can't be implemented in CSS. Consider:
p.toggle {
--boolean: 'false';
}
If we were to propose a pseudo-class for matching elements based on their CSS property values, like p:prop(--boolean: 'true')
,
window.getComputedStyle()
does not always return computed values.cyclic dependencies become inevitable:
:root {
--boolean: 'true';
}
/*
* Causes p to stop matching the selector, switching back to
* inheriting from :root, which in turn causes it to start
* matching the selector again, ad infinitum.
*/
p:prop(--boolean: 'true') {
--boolean: 'false';
}
Look closely at the JavaScript example above and you'll notice that it's not robust. The property value is only evaluated once, as soon as the document is done being put together. Change the custom property value again and the element does not update itself to reflect the change. If it listened to changes to the custom property value, it'd run into the same cyclic dependency issue immediately — and worse, lock up your browser (until it notices and intercepts the infinite recursion).
Upvotes: 2
Reputation: 21092
The Stack Overflow answer you linked is actually not wrong, and is talking about something a little different from what you are asking. It talks about how, in the relevant CSS spec, custom properties are often described as variables for ease of understanding, despite the fact that they work differently from how variables in other languages work (but that's kind of par for the course with CSS, isn't it?).
The variable part of CSS custom properties is actually in how you call (or use) the custom property:
.example {
background: var(--custom-property);
}
As you can see from the spec, fully titled "CSS Custom Properties for Cascading Variables Module Level 1", there is only one use: to be called as the value in a cascaded element with var()
. So it's a little unclear what the author of that wiki post means when they say that custom properties are used for more than just variables. Further, the followup sentences don't really describe or backup that claim, they just talk about how using $
instead of -
is "weird".
Perhaps they mean that you can declare a custom property that only works when read by JavaScript? Or declare a custom property in JS that is then applied to the CSS. The custom variables syntax supports equations that wouldn't be read properly by CSS parsers, but would be read properly in JavaScript. However, the result is still the property value of an element declared with var()
.
And to put the matter into some perspective, it wouldn't make sense to call them custom properties if they had a use for something other than in a property. The spec does not mention an alternative way to call or use a property in CSS or JS without using var()
in a cascaded selector's property-value section (the bit of code between the {}
).
Upvotes: 2