I know there are many so-called "css resets", e.g.
https://ageek.dev/normalize-css,
https://meyerweb.com/eric/tools/css/reset/, or
https://elad2412.github.io/the-new-css-reset/
But what I don't understand is why it seems it is not possible to use something way more simpler.
As far as I know, the initial keyword resets a property to the value that is defined as the default value of that property in the CSS specification.
And since nowadays we have the all property-like keyword, I expected that I can use something like
* {
all: initial;
}
or
:root {
all: initial;
}
instead of all these reset.csss and normalize.csss. That is, I expected that one of these short snipets will help me to remove styles added to a web page from user agent stylesheet.
But it doesn't really work as I expected it. It seems that
:root, html, body {
all: initial
}
doesn't really remove styles "inherited" from user agent stylesheet at all, and
* {
all: initial
}
removes styles too aggressively. For example, it makes my style and script elements visible! I don't think that CSS specification says that these two elements should be visible. I'm sure that CSS specification says that they should be not visible. That is, it seems that
* {
all: initial
}
instead of resetting my styles to the CSS specification-level, resets them to the absolute-zero-level. This is not what I want.
Can anybody explain what is wrong in my understanding?
You are correct that initial resets to initial values for a given CSS property, but note that CSS properties have no initial value for each element-- they only have an initial value for that property, which will be the same for any and all elements it is applied to. For instance, the color property spec has a single initial value defined-- not a list of initial values to which it should be set for every element. So when you use it in conjunction with all, using:
* {
all: initial
}
...you are telling the browser to take every property of every single element and reset it to the property's default value. So, for instance, the display property spec defines its initial value as inline-- so every single element on your page will be displayed as inline.
Related
Is it possible to override the display property with its default value? For example if I have set it to none in one style, and I want to override it in a different with its default.
Or is the only way to find out what the default of that element is and then set it to that? Would like to not have to know if the element is usually block, inline or whichever...
A browser's default styles are defined in its user agent stylesheet, the sources of which you can find here. Unfortunately, the Cascading and Inheritance level 3 spec does not appear to propose a way to reset a style property to its browser default. However there are plans to reintroduce a keyword for this in Cascading and Inheritance level 4 — the working group simply hasn't settled on a name for this keyword yet (the link currently says revert, but it is not final). Information about browser support for revert can be found on caniuse.com.
While the level 3 spec does introduce an initial keyword, setting a property to its initial value resets it to its default value as defined by CSS, not as defined by the browser. The initial value of display is inline; this is specified here. The initial keyword refers to that value, not the browser default. The spec itself makes this note under the all property:
For example, if an author specifies all: initial on an element it will block all inheritance and reset all properties, as if no rules appeared in the author, user, or user-agent levels of the cascade.
This can be useful for the root element of a "widget" included in a page, which does not wish to inherit the styles of the outer page. Note, however, that any "default" style applied to that element (such as, e.g. display: block from the UA style sheet on block elements such as <div>) will also be blown away.
So I guess the only way right now using pure CSS is to look up the browser default value and set it manually to that:
div.foo { display: inline-block; }
div.foo.bar { display: block; }
(An alternative to the above would be div.foo:not(.bar) { display: inline-block; }, but that involves modifying the original selector rather than an override.)
If using javascript is allowed, you can set the display property to an empty string. This will cause it to use the default for that particular element.
var element = document.querySelector('span.selector');
// Set display to empty string to use default for that element
element.style.display = '';
Here is a link to a jsbin.
This is nice because you don't have to worry about the different types of display to revert to (block, inline, inline-block, table-cell, etc).
But, it requires javascript, so if you are looking for a css-only solution, then this is not the solution for you.
Note: This overrides inline styles, but not styles set in css
Unset display:
You can use the value unset which works in both Firefox and Chrome.
display: unset;
.foo { display: none; }
.foo.bar { display: unset; }
No, it is generally not possible. Once some CSS (or HTML) code sets a value for a property on an element, there is no way to undo it and tell the browser to use its default value.
It is of course possible to set a property a value that you expect to be the default value. This may work rather widely if you check the Rendering section of HTML5 CR, mostly reflecting what browsers actually do.
Still, the answer is “No”, because browsers may have whatever default values they like. You should analyze what was the reason for wanting to reset to defaults; the original problem may still be solvable.
What worked for me was revert!
revert resets the property to its inherited value if it inherits from its parent or to the default value established by the user agent's stylesheet.
If you have access to JavaScript, you can create an element and read its computed style.
function defaultValueOfCssPropertyForElement(cssPropertyName, elementTagName, opt_pseudoElement) {
var pseudoElement = opt_pseudoElement || null;
var element = document.createElement(elementTagName);
document.body.appendChild(element);
var computedStyle = getComputedStyle(element, pseudoElement)[cssPropertyName];
element.remove();
return computedStyle;
}
// Usage:
defaultValueOfCssPropertyForElement('display', 'div'); // Output: 'block'
defaultValueOfCssPropertyForElement('content', 'div', ':after'); // Output: 'none'
Concerning the answer by BoltClock and John, I personally had issues with the initial keyword when using IE11. It works fine in Chrome, but in IE it seems to have no effect.
According to this answer IE does not support the initial keyword:
Div display:initial not working as intended in ie10 and chrome 29
I tried setting it blank instead as suggested here:
how to revert back to normal after display:none for table row
This worked and was good enough for my scenario. Of course to set the real initial value the above answer is the only good one I could find.
According to my understanding to your question, as an example: you had a style at the beginning in style sheet (ex. background-color: red), then using java script you changed it to another style (ex. background-color: green), now you want to reset the style to its original value in style sheet (background-color: red) without mentioning or even knowing its value (ex. element.style.backgroundColor = 'red')...!
If I'm correct, I have a good solution for you which is using another class name for the element:
steps:
set the default styles in style sheet as usual according to your desire.
define a new class name in style sheet and add the new style you want.
when you want to trigger between styles, add the new class name to the element or remove it.
if you want to edit or set a new style, get the element by the new class name and edit the style as desired.
I hope this helps. Regards!
For a CSS framework I am developing, I am using all: unset, which by itself works fine:
#foo { all: unset; }
However, in certain cases, I want to "undo" the effect of this rule, as in
#foo:hover { all: auto; }
However, this obviously does not work because there is no value of auto for all. Instead, we have the values inherit and initial, which instead of "cancelling" the all property, have different effects: of reverting all values to their parent's value, or their initial (I assume this means system-level default values).
To accomplish what I want, I am currently doing
#foo:not(:hover) { all: unset; }
which works fine, but is not too scalable if I want to do this for multiple pseudo-classes, for example, and I would prefer to override the all: unset property? Is there any way to do so?
It does not appear to be possible to undo the effects of the all property once it has been specified. This may be due to all being a shorthand property (that happens to accept only the CSS-wide keywords as values).
You can't erase a shorthand declaration from the cascade the same way that css-cascade-4's introduction of the revert keyword allows you to erase author-level declarations, and that's because a shorthand property doesn't exist as its own entity in the cascade; instead, it simply represents all of its component properties. Like with the more traditional shorthand properties such as background and font, the only way to override a shorthand declaration that has been applied is to re-specify the values for the longhands that were overridden, either via longhand declarations or via another shorthand declaration. But you can't do the latter with the all property since it only accepts CSS-wide keywords.
As the former is obviously not practical with the all shorthand, since you can't predict which author-level declarations are being overridden to begin with, your only other option is to restrict it via a selector, thereby preventing it from ever applying in specific circumstances in the first place. Hopefully we will see more implementations of level 4 :not() in the near future, which will make writing selectors a little easier.
Additionally to what BoltClock explained, what you want is not currently possible even for non-shorthand properties.
* { color: red; }
#foo { color: unset; }
#foo:hover { color: /* How to revert to red? */ }
Once you add a value which wins the cascade, there is not way to tell the cascade to "go back" and get the previous winner instead. You must set it explicitly, but that's only possible if you know it.
The closest thing is the revert keyword, introduced by CSS Cascade 4, which rolls back the cascade to previous origin level. But rolling the cascade back to the previous winner in the same origin level is currently not possible.
Then, the solution is restricting your selectors to apply only when you want them. This way there is no need to undo.
Have you tried
all: revert
More infos here MDN
I have a custom HTML5 tag called <scroll-content>. This tag actually gets created and inserted for me by a framework in certain places inside of my HTML file. Now I would like to modify the CSS of this tag so inside my CSS file I went:
scroll-content{
overflow: hidden;
}
It did what it was supposed to, but is this the proper way of styling the custom tags?
I can't add a class to them because I do not create the tags, the framework does, so I can't access them in my code and I would like to avoid using Javascript to find these tags and adding classes that way.
I would prefer to know the standard/safest way of modifying custom tags.
You can apply CSS to custom elements just like you can to standard HTML elements.
There's nothing wrong with scroll-content { ... }, as written in your code.
A Little Background
The browser, at a basic level, has no clue what elements exist. It doesn't recognize anything... until it is exposed to the default style sheet (sample).
The default style sheet introduces the browser to HTML elements.
Custom elements can therefore be defined as elements that are not included in the default style sheet. (Elements that exist, but are unsupported by the browser, could share this definition.)
Custom elements could, however, be introduced to the browser in author styles.
Here's something important to consider:
If the browser doesn't recognize an element (i.e., it's not in the default style sheet), it will apply CSS initial values.
6.1.1 Specified
values
User agents must first assign a specified value to each property based
on the following mechanisms (in order of precedence):
If the cascade results in a value, use it.
Otherwise, if the property is inherited and the element is not the root of the document tree, use the computed value of the parent
element.
Otherwise use the property's initial value. The initial value of each property is indicated in the property's definition.
As outlined above, if an element is unrecognized (#1 & #2 don't apply), use the initial value from the property definition (#3 applies).
So in your case:
Your custom element is: <scroll-content>
Your CSS is: scroll-content { overflow: hidden; }
You say in your question that this code does what it's supposed to do. But unless the framework you mention provides additional styles for custom elements, it cannot work (demo).
Here's why:
Since <scroll-element> is not in the default style sheet it will use CSS initial values.
Well, the initial value of the display property is inline.
But the overflow property only works on block elements.
So there's no way this HTML/CSS combination could work – the overflow property would be ignored, as would height, width and any other properties that don't apply to inline elements.
A custom element would need to have display: block applied for overflow to work (demo).
Similarly, the only reason body, div, h1, p, ul exist as block elements is because they are defined this way in the default style sheet (sample).
So, putting aside the arguments for and against custom elements, here's the bottom line:
Add display: block to your custom elements and you're good-to-go.
Cannot exist standard tags with a hyphen "-" in his name, so there is not such problem.
It would be preferable if you can avoid using custom tags since you never know when those tags may become standardized or have a specific usage at some point.
I think it would be safer if you create a class to that custom tag, something like:
.scroll-content{
overflow: hidden;
}
This should do it.
Is it possible to override the display property with its default value? For example if I have set it to none in one style, and I want to override it in a different with its default.
Or is the only way to find out what the default of that element is and then set it to that? Would like to not have to know if the element is usually block, inline or whichever...
A browser's default styles are defined in its user agent stylesheet, the sources of which you can find here. Unfortunately, the Cascading and Inheritance level 3 spec does not appear to propose a way to reset a style property to its browser default. However there are plans to reintroduce a keyword for this in Cascading and Inheritance level 4 — the working group simply hasn't settled on a name for this keyword yet (the link currently says revert, but it is not final). Information about browser support for revert can be found on caniuse.com.
While the level 3 spec does introduce an initial keyword, setting a property to its initial value resets it to its default value as defined by CSS, not as defined by the browser. The initial value of display is inline; this is specified here. The initial keyword refers to that value, not the browser default. The spec itself makes this note under the all property:
For example, if an author specifies all: initial on an element it will block all inheritance and reset all properties, as if no rules appeared in the author, user, or user-agent levels of the cascade.
This can be useful for the root element of a "widget" included in a page, which does not wish to inherit the styles of the outer page. Note, however, that any "default" style applied to that element (such as, e.g. display: block from the UA style sheet on block elements such as <div>) will also be blown away.
So I guess the only way right now using pure CSS is to look up the browser default value and set it manually to that:
div.foo { display: inline-block; }
div.foo.bar { display: block; }
(An alternative to the above would be div.foo:not(.bar) { display: inline-block; }, but that involves modifying the original selector rather than an override.)
If using javascript is allowed, you can set the display property to an empty string. This will cause it to use the default for that particular element.
var element = document.querySelector('span.selector');
// Set display to empty string to use default for that element
element.style.display = '';
Here is a link to a jsbin.
This is nice because you don't have to worry about the different types of display to revert to (block, inline, inline-block, table-cell, etc).
But, it requires javascript, so if you are looking for a css-only solution, then this is not the solution for you.
Note: This overrides inline styles, but not styles set in css
Unset display:
You can use the value unset which works in both Firefox and Chrome.
display: unset;
.foo { display: none; }
.foo.bar { display: unset; }
No, it is generally not possible. Once some CSS (or HTML) code sets a value for a property on an element, there is no way to undo it and tell the browser to use its default value.
It is of course possible to set a property a value that you expect to be the default value. This may work rather widely if you check the Rendering section of HTML5 CR, mostly reflecting what browsers actually do.
Still, the answer is “No”, because browsers may have whatever default values they like. You should analyze what was the reason for wanting to reset to defaults; the original problem may still be solvable.
What worked for me was revert!
revert resets the property to its inherited value if it inherits from its parent or to the default value established by the user agent's stylesheet.
If you have access to JavaScript, you can create an element and read its computed style.
function defaultValueOfCssPropertyForElement(cssPropertyName, elementTagName, opt_pseudoElement) {
var pseudoElement = opt_pseudoElement || null;
var element = document.createElement(elementTagName);
document.body.appendChild(element);
var computedStyle = getComputedStyle(element, pseudoElement)[cssPropertyName];
element.remove();
return computedStyle;
}
// Usage:
defaultValueOfCssPropertyForElement('display', 'div'); // Output: 'block'
defaultValueOfCssPropertyForElement('content', 'div', ':after'); // Output: 'none'
Concerning the answer by BoltClock and John, I personally had issues with the initial keyword when using IE11. It works fine in Chrome, but in IE it seems to have no effect.
According to this answer IE does not support the initial keyword:
Div display:initial not working as intended in ie10 and chrome 29
I tried setting it blank instead as suggested here:
how to revert back to normal after display:none for table row
This worked and was good enough for my scenario. Of course to set the real initial value the above answer is the only good one I could find.
According to my understanding to your question, as an example: you had a style at the beginning in style sheet (ex. background-color: red), then using java script you changed it to another style (ex. background-color: green), now you want to reset the style to its original value in style sheet (background-color: red) without mentioning or even knowing its value (ex. element.style.backgroundColor = 'red')...!
If I'm correct, I have a good solution for you which is using another class name for the element:
steps:
set the default styles in style sheet as usual according to your desire.
define a new class name in style sheet and add the new style you want.
when you want to trigger between styles, add the new class name to the element or remove it.
if you want to edit or set a new style, get the element by the new class name and edit the style as desired.
I hope this helps. Regards!
Is it possible to override the display property with its default value? For example if I have set it to none in one style, and I want to override it in a different with its default.
Or is the only way to find out what the default of that element is and then set it to that? Would like to not have to know if the element is usually block, inline or whichever...
A browser's default styles are defined in its user agent stylesheet, the sources of which you can find here. Unfortunately, the Cascading and Inheritance level 3 spec does not appear to propose a way to reset a style property to its browser default. However there are plans to reintroduce a keyword for this in Cascading and Inheritance level 4 — the working group simply hasn't settled on a name for this keyword yet (the link currently says revert, but it is not final). Information about browser support for revert can be found on caniuse.com.
While the level 3 spec does introduce an initial keyword, setting a property to its initial value resets it to its default value as defined by CSS, not as defined by the browser. The initial value of display is inline; this is specified here. The initial keyword refers to that value, not the browser default. The spec itself makes this note under the all property:
For example, if an author specifies all: initial on an element it will block all inheritance and reset all properties, as if no rules appeared in the author, user, or user-agent levels of the cascade.
This can be useful for the root element of a "widget" included in a page, which does not wish to inherit the styles of the outer page. Note, however, that any "default" style applied to that element (such as, e.g. display: block from the UA style sheet on block elements such as <div>) will also be blown away.
So I guess the only way right now using pure CSS is to look up the browser default value and set it manually to that:
div.foo { display: inline-block; }
div.foo.bar { display: block; }
(An alternative to the above would be div.foo:not(.bar) { display: inline-block; }, but that involves modifying the original selector rather than an override.)
If using javascript is allowed, you can set the display property to an empty string. This will cause it to use the default for that particular element.
var element = document.querySelector('span.selector');
// Set display to empty string to use default for that element
element.style.display = '';
Here is a link to a jsbin.
This is nice because you don't have to worry about the different types of display to revert to (block, inline, inline-block, table-cell, etc).
But, it requires javascript, so if you are looking for a css-only solution, then this is not the solution for you.
Note: This overrides inline styles, but not styles set in css
Unset display:
You can use the value unset which works in both Firefox and Chrome.
display: unset;
.foo { display: none; }
.foo.bar { display: unset; }
No, it is generally not possible. Once some CSS (or HTML) code sets a value for a property on an element, there is no way to undo it and tell the browser to use its default value.
It is of course possible to set a property a value that you expect to be the default value. This may work rather widely if you check the Rendering section of HTML5 CR, mostly reflecting what browsers actually do.
Still, the answer is “No”, because browsers may have whatever default values they like. You should analyze what was the reason for wanting to reset to defaults; the original problem may still be solvable.
What worked for me was revert!
revert resets the property to its inherited value if it inherits from its parent or to the default value established by the user agent's stylesheet.
If you have access to JavaScript, you can create an element and read its computed style.
function defaultValueOfCssPropertyForElement(cssPropertyName, elementTagName, opt_pseudoElement) {
var pseudoElement = opt_pseudoElement || null;
var element = document.createElement(elementTagName);
document.body.appendChild(element);
var computedStyle = getComputedStyle(element, pseudoElement)[cssPropertyName];
element.remove();
return computedStyle;
}
// Usage:
defaultValueOfCssPropertyForElement('display', 'div'); // Output: 'block'
defaultValueOfCssPropertyForElement('content', 'div', ':after'); // Output: 'none'
Concerning the answer by BoltClock and John, I personally had issues with the initial keyword when using IE11. It works fine in Chrome, but in IE it seems to have no effect.
According to this answer IE does not support the initial keyword:
Div display:initial not working as intended in ie10 and chrome 29
I tried setting it blank instead as suggested here:
how to revert back to normal after display:none for table row
This worked and was good enough for my scenario. Of course to set the real initial value the above answer is the only good one I could find.
According to my understanding to your question, as an example: you had a style at the beginning in style sheet (ex. background-color: red), then using java script you changed it to another style (ex. background-color: green), now you want to reset the style to its original value in style sheet (background-color: red) without mentioning or even knowing its value (ex. element.style.backgroundColor = 'red')...!
If I'm correct, I have a good solution for you which is using another class name for the element:
steps:
set the default styles in style sheet as usual according to your desire.
define a new class name in style sheet and add the new style you want.
when you want to trigger between styles, add the new class name to the element or remove it.
if you want to edit or set a new style, get the element by the new class name and edit the style as desired.
I hope this helps. Regards!