Is there a difference between CSS custom properties and CSS variables? - css

In all of the material I've read online, it appears that CSS custom properties and CSS variables are the same thing. However, at the end of an example in the Inheritance of CSS Variables section of the Mozilla Developer Network documentation, there is this confusing statement:
Keep in mind that these are custom properties, not actual CSS
variables. The value is computed where it is needed, not stored for
use in other rules. For instance, you cannot set a property for an
element and expect to retrieve it in a sibling's descendant's rule.
The property is only set for the matching selector and its
descendants, like any normal CSS.
Which gives me the impression that these two concepts are not synonymous.
What is the difference between custom properties and variables?

A CSS Custom Property is the same thing as a CSS Variable. But that seems to come of some clumsy naming.
They weren't wrong to title the page: Using CSS custom properties (variables)
However a CSS Variable is not a variable in the traditional sense, as there is no way to define it so that it is globally scoped like in a programming language, or CSS Preprocessor (LESS/Sass).
Even a root scoped custom property/variable is not global. Changing the value of a property in a child will not change the value above or for siblings of that scope. If someone is expecting to be global, it may cause confusion and I suspect that's what Mozilla's writers are trying to point out.
if you look at
w3.org's CSS Custom Properties for Cascading Variables
This module introduces a family of custom author-defined properties known collectively as custom properties
Custom properties are definitions that can be referenced using var(--my-custom-prop). Like a variable!
quote continued...
as one only has to change the value once, in the custom property, and the change will propagate to all uses of that variable automatically.
Awkward... The above statement is not true exactly. It seems Mozilla Developer Network documentation is trying clarify that idea so that it's less confusing. Repeating the original quote:
Keep in mind that these are custom properties, not actual CSS variables. The value is computed where it is needed, not stored for use in other rules. For instance, you cannot set a property for an element and expect to retrieve it in a sibling's descendant's rule. The property is only set for the matching selector and its descendants, like any normal CSS.
They're pointing out it's not a variable in the traditional sense of a programming language. But that it is computed just like styles, adhering to the general cascade/scoping rules of CSS.
Thus var(--my-custom-prop) could resolve to very different things based on where it is declared, and that declarations don't propagate out to a higher scope.
Here's a codepen to mess around with if you'd like to try it out.
So think of CSS Custom Property the same as CSS Variable but be sure to remember that values cascade, and there's no global scope.

To be clear, the specification is called Custom Properties for Cascading Variables. The key is in the word "Cascading"; custom properties cascade, much like any other property with a few key differences.
In everyday usage, there is no difference between a "custom property" and a "CSS variable"; as far as authors are concerned, they're the same thing, just as "property" and "attribute" refer to the same thing in everyday usage even though the correct terms are "custom property" and "property" respectively (CSS doesn't have attributes; any reference to an attribute such as in attribute selectors and attr() refers to attributes in host languages like HTML).
The name "CSS Variables", the spec's URL slug css-variables, and the var() notation, are all just there to placate authors' clamors over the years for variable support in CSS. The spec never actually canonizes the term "CSS variable", even though it uses the word "variable" a couple dozen times throughout its prose to make itself easier for authors to understand (which is strange because CSS specs aren't intended to be read by authors).
As MDN explains, custom properties aren't true variables like that of programming languages or even CSS preprocessors, even though they have a lot in common. As mentioned above, cascading is what sets custom properties apart. Those traits that they have in common are what authors really are looking for in "variable" support in CSS, and they're good enough for most authors' needs.
That's why everyone just calls them "CSS variables", even though in reality it's a bit of a misnomer.

I have looked at the page you have linked; they are trying to explain the "cascading" of css. They are saying that the style depends on a selector's parents, as opposed to being a set value as you would get in a variable.
The explanation attempts to clarify the difference between a css property and a vairable in programming languages. If you already understand css, you don't need to worry about this explanation.
If we look at the example they provide:
<div class="one">
<div class="two">
<div class="three"></div>
<div class="four"></div>
</div>
</div>
If you give properties to class="two", they will be applied to class="three" and class="four".
If you re-use class="three" and class="four" within another class, like this:
<div class="five">
<div class="three"></div>
<div class="four"></div>
</div>
then they will inherit whatever properties you applied to class="five" with nothing to do with class="two".
This all assumes that class="three" and class="four" do not have their own properties. Let's say you assign the color red to class="three", then it will be red in both cases plus the properties inherited from its parent classes.

I believe that it simply means that if you have the following rules:
#foo{
--my-prop: 10px;
}
.bar{
height: var(--my-prop);
}
with the following HTML:
<div id="foo">
<div class="bar"></div>
</div>
<div id="sibling">
<div class="bar"></div>
</div>
then the height of the .bar div in the #sibling div is going to be 0, because the value of --my-prop is only inherited by descendants of #foo.
The language is confusing. I think the author is probably trying to draw a distinction between variables in procedural languages (like JS) versus Custom CSS Properties. You cannot set a property and use it anywhere, like you might with a variable in another language.

Related

Are there a css property that would change nothing and where we can store information?

Are there a css property that would change nothing?
I need this for testing purposes very often when writing scss just to see that I created a css selector correctly. For instance, I would be glad to have something like this foo: "helloworld1"; and later on I would be able to change the value of the foo and check the value in the developer tools to see that my selectors have indeed reached a correct element.
I thought about using the width: auto;, but sometimes the width is specified (e.g. width: 100px;).
Define your own properties using custom properties (aka CSS variables)
Custom properties are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here.
Also
Custom properties are ordinary properties, so they can be declared on any element, are resolved with the normal inheritance and cascade rules, can be made conditional with #media and other conditional rules, can be used in HTML’s style attribute, can be read or set using the CSSOM, etc.

BEM and single selectors

This is sort of a theoretical question, but it bugs me for a couple of hours now.
I'm learning BEM and it's great so far, but I have a problem. Let's say I have this code:
<div class="section-hi main-section">
<h2 class="main-section_header">Blah</h2>
<p>Generated from the CMS</p>
</div>
How do I target the p to make it good with BEM? Can I just go with
.main-section p
or this would be against the rules? I coudn't find any answers to this, since every example and article about BEM focuses only on classes, and I can't expect my CMS to add different class to every groups of paragraphs.
One of the concepts of BEM is to create reusable components, using an element such as p goes against that.
Why?
By specifying p we are restricting the ways in which our component can be used. To display correctly the p tag must be used. For example the following markup would not work with the component.
<div class="section-hi main-section">
<h2 class="main-section_header">Blah</h2>
<span>Generated from the CMS</span> <!-- this will not pick up the styles -->
</div>
Specificity
Another important point is BEM aims to keep specificity to a minimum, using single class names. Creating a style with a p increases specificity.
.main-section p
It is now hard for me to override this style with a utility class, as it has a higher specificity than a single class.
More on CSS specificity
The solution
So instead the idea is to use class names to describe the element. That way we can choose to use whatever markup we like and the component will display as expected. e.g.
<div class="section-hi main-section">
<h2 class="main-section_header">Blah</h2>
<h3 class="main-section_subHeader>Generated from the CMS</h3> <!-- This will work -->
</div>
Must I always use class names?
You will find occasions when it is OK or necessary to create styles for elements and not use class names. For example you may have a component that you only want to be used with certain markup. Then it is perfectly valid to do so.
Summary
As a general rule always try and keep to the single class rule unless there is a valid reason not to do so. Otherwise it will trip you up later on down the line.
For further reading on BEM I recommend this post http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
If we just look on this code - you can do that, but what if you have more <p> elements? If you can't add class to every element, you can always add id and call element by
#element_id{ }

What's the point of writing div#id_name vs. #id_name?

I've noticed that a lot of css style recipes are often stated like this:
div#id_name {
blah: blah;
}
But since IDs are unique, what's the point of sticking "div" in front of #id_name? Is there any advantage over the following snippet?
#id_name {
blah: blah;
}
I would argue that the latter is superior because you might decide to make the id_name element into something besides a div.
This is primarily done to advance specificity and to hint the document as to what type of element #id_name is.
First, specificity:
Specificity determines which styles are actually applied to your element. The more specific you are in calling your element out, the more priority that block of properties takes over another.
For example:
Given HTML
<div id="id_name">
Look at this blue text!
</div>
With CSS
div#id_name {
color: red;
}
#id_name {
color: blue;
}
Results in
This will render a div with red text as opposed to blue text. This is beneficial when writing a framework if you want to guard your styles from being arbitrarily overwritten by local styles.
Secondly, hinting:
Oftentimes, CSS is an afterthought. It's a shame, too, as it's gotten increasingly more powerful and has taken many of the responsibilities previously reserved for client-side scripting languages like JavaScript. There is no implicit inheritance in CSS, rather it's explicit via a long declaration.
What I'm talking about with this is that you don't see
div {
.my-class {
/* RULES! */
}
#my-id {
/* RULES! */
}
}
as a part of CSS unless you're using a precompiler like LESS or SASS. Hinting a document with the element name instead of only the id or class allows for much greater readability for not only future you, but any collaborators you may have on the project.
And finally:
Sometimes it just doesn't make sense to not add a an element guard to your rule. If I have a rule that sets things like height, width or padding, I wouldn't want that same rule applied to a span. I would rather see it fail loud than silent to prevent rules being applied that have no place being there. It can cause messy and unexpected results given the exact scenario you described.
In addition, there's no guarantee that #id-name won't be re-used on a later page for an element that is not a div in the scenario you gave. So there's that, too.
Using ID's have a very strict specificity issue. Realistically, according to the standards, you can only use an ID once in any given HTML document. That doesn't mean you can't use ID's as styling selectors, though, it does come with dangerous pitfalls in larger projects. They're fine if you're using them as targets in Javascript. Go crazy.
ID selectors are very, very specific in targeting elements and in return, you end up with problems later down the line dealing with CSS specificity. Class selectors are reusable and have much looser specificity. Styling with ID's doesn't have anything different that a class selector doesn't have, so why use them if they're causing specificity issues? Read this and this. They are both fantastic articles on why ID's are not cool for CSS. It is a personal preference, but, making your CSS very specific is a front-end disaster in all real-world cases web development.
So, to answer your question properly, adding div at the start of and id selector, like div#id_name means you can only apply that id to a <div> element. You couldn't add it to a <span>, or any other element for example, which is an insanely restrictive method of styling in CSS. If you just use #id_name, you can apply this selector on any element instead.
The only difference is that div#id_name has higher specificity. This is seldom relevant, and there are other ways to make a selector more specific. People may include the element (tag) name for documentation purposes, but then they take the risk that was referred to in the question: someone might change the div to, say, p and forget to modify the CSS selector(s).

inherit properties from class other than parent

Say I have two classes in my CSS, say .classA{} and .classB{}, and I've defined and tailored classA to however I like it. Now I'd like classB to be mostly like classA, with a couple of changes. Since they will be used separately (i.e., A is not the parent of B), B won't inherit properties from A in the layout. Can I do something like
.classB{
from .classA inherit *
some additional changes
}
while writing the CSS, which will avoid having to copy/paste and also ensure that if I were to change A sometime later, B changes automatically and I don't have to keep track of it.
CSS has no concept of variables to allow for the adjusting of one CSS measurement to influence others automatically. However, there are CSS writing systems that allow for variables (that are then 'compiled' and spit out plain CSS). Those are useful, but require use of the particular framework. (one example: http://lesscss.org/ )
If you are using a server side scripting language such as PHP, you could write your CSS files as PHP files, using variables within.
Barring that, I'd use multiple classes:
.sharedStyles {...the styles to be the same on elements}
.uniqueStylesA {...}
.uniqueStylesB {...}
Then apply as such:
<div class="sharedStyles uniqueStylesA">...</div>
<div class="sharedStyles uniqueStylesB">...</div>
Or...if you can nest in your HTML:
<div class="sharedStyles">
<div class="uniqueStylesA">...</div>
<div class="uniqueStylesB">...</div>
</div>

Class Style Sheet with two names or?

<div id="SideBar" class="sidebar mainbar">
I've just seen this in a .aspx file. Is this valid? Can someone point me in the right direction to learn what this does. I'm assuming its valid, but I'm not finding it in the css file. I am finding sidebar defined as a class, but not mainbar.
Thanks in advance,
Randy
This div just has two classes, which means it will get the properties defined under .sidebar as well as those under .mainbar
Sure, you can have an element implement as many css classes as you like. If there is no class defined in the CSS files it is possible that either:
The additional css classes have been removed from the styles sheets and the .aspx pages have not been refactored to match.
The css class is been used to identify the element(s) via javascript or some other scripting language.
As for mainbar not showing up in your CSS file, sometimes developers assign classes to elements and then reference those classes in javascript.
Yes this is perfectly valid. An element can be styled by multiple classes.
See this reference and this one which touches on which one takes precedence for duplicate style attributes.
CSS Tricks has a few other CSS tricks including having two classes.
Copy/Pasting the trick from the above site:
Usually attributes are assigned just one class, but this doesn't mean that that's all you're allowed. In reality, you can assign as many classes as you like!
Using these two classes together (separated by a space, not with a comma) means that the paragraph calls up the rules assigned to both text and side. If any rules overlap between the two classes then the class which is below the other in the CSS document will take precedence.
Beware of IE6 if someday you try to style an element using more than one class, it doesn't work like intended.
Googling "multiple classes ie6"
test case
No problem with id+class (like #anid.class ) or two selectors like .classA and then .classB but no .classA.classB

Resources