All or Nothing
There’s a recent CSS property that I had originally been quite excited about: all
.
The all
property is a shortcut for resetting all of the properties on a given element. Like a big ol’ CSS reset in one line. Reset them to what? Either a complete blank slate using the initial
value or by having everything inherit from the parent using the inherit
value.
When would you want to use the all
property? The problem with answering this question is that it depends on what you think the all
property would actually do.
My expectation was such that it creates a blank slate, resetting all properties and allowing you to declare what you really care about on this element.
Why would I want a blank slate?
In creating a module that could apply to different HTML scenarios, I’d like to create a consistent baseline without having to write extra code to do so.
Let’s look at this scenario and see why the all
property, as currently implemented, fails this expectation.
Creating a baseline
Take this scenario of wanting to style a link like a button. (Why not use a button, you ask? Because it’s a link to another page, that’s why, and we want a big ol’ button to get people to click on it.)
<a href=“…” class=“button”>Buy Now</a>
We need to style up this button, of course.
.button {
border: 1px solid blanched almond;
border-radius: 3px;
padding: 5px 10px;
background-color: cornsilk;
color: brown;
}
Because it’s a link, we need to add some extra CSS to deal with the default browser styles for links.
text-decoration: none;
But now we want to apply this to <button>
, too. Again, though, we have to add some extra CSS to deal with the default browser styles for buttons.
font-size: 16px; /* or ems or rems or inherit */
font-family: Arial; /* or inherit or pick font stack */
cursor: pointer; /* or not, if you don’t care */
My expectation was that I could add all: initial
and everything would suddenly be reset to a blank slate. Instead, each browser does something a bit different.
In Chrome, everything is reset. This comes the closest to what I expect. The font gets reset to the browser default. Oh wait. Except cursor. Link cursor is still pointer.
In Firefox, we get pretty close, too. The only problem is that there’s 1 extra pixel of padding that it adds to buttons. You need to use the following code to get things aligned. (Which you’d need to do anyways.)
.button::-moz-focus-inner {
padding:0;
border:0;
}
(Which, by the way, removes any focus ring. Please add one back in some other way.)
Oh, and link cursor changes to text selection. Why? I have no idea.
In Safari, though, the behaviour is much different. The link font resets to Arial, not Times New Roman. The button font resets to the system font. And the link cursor, like Chrome, remains a pointer.
IE and Edge don’t have support for all
yet. Maybe that’s a good thing.
Excuse me while I step outside to flip some tables. (Because I keep my tables outside, apparently. Oh, look, there’s a table on my deck. It has now been flipped.)
Oh, and one more thing to mention, in case you are deciding to use all
on your project. Like some CSS resets, it also removes any focus ring and this is consistent across browsers. Please add something back in!
Conclusion: Useless
In conclusion, the problem with all
is such that the implementation is so inconsistent across browsers that it’s useless. There’s no way to create a consistent baseline in which to build on, thereby negating when I would ever want to use this property.
There may be some cases where it might be useful but, at this point, I think being explicit—by declaring the properties you actually care about—is likely to create a more consistent and predictable result, even if it might end up creating more code.
Conversation
What about all: unset?
Make sure to test with more complex HTML tough (hint: color inheritance,...).
My basic idea for a component embeddable on 3rdparty websites was like #container *{ all: unset; } and then style everything from there... my conclusion was the same tough...
@Christoph: Unfortunately,
all: unset
makes other alterations, but again, is inconsistent in its application across browsers. For example, Safari resetcolor
to black but neither Chrome nor Firefox did. Cursor also exhibited the same behaviour as described above.Awesome article. We in PostCSS are thinking about new methodology, when we automatically insert all:initial to all elements, to be sure, that components are isolated from inherited styles.
So we created all:initial polyfill in postcss-cssnext and postcss-autoreset to insert it by some rules.
Also with all: initial polyfill from cssnext we have consistently behavioral across browsers.
The main question is what you have with all: initial polyfill from cssnext?