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.

Screen shot showing comparison of link and button styles in Chrome

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.

Screen shot showing comparison of link and button styles in Firefox

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.

Screen shot showing comparison of link and button styles in Safari

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.

Published May 18, 2016
Categorized as HTML and CSS
Short URL: https://snook.ca/s/1084

Conversation

5 Comments · RSS feed
Christoph said on May 18, 2016

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...

Jonathan Snook said on May 18, 2016

@Christoph: Unfortunately, all: unset makes other alterations, but again, is inconsistent in its application across browsers. For example, Safari reset color to black but neither Chrome nor Firefox did. Cursor also exhibited the same behaviour as described above.

Andrey Sitnik said on May 19, 2016

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.

Andrey Sitnik said on May 19, 2016

Also with all: initial polyfill from cssnext we have consistently behavioral across browsers.

trolololo said on May 19, 2016

The main question is what you have with all: initial polyfill from cssnext?

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.