Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: ECSS – Simple rules for efficient CSS (ecss.info)
43 points by emmacharp 8 months ago | hide | past | favorite | 20 comments
A list of CSS authoring rules with examples and a Stylelint config accessible from the top of the page.

I've come to these through 20 years of experience and a willingness to make vanilla CSS a better alternative to frameworks.

I encourage you all to comment on the rules themselves and the Stylelint Config for ECSS. Here's the link for faster access (I still suggest at least zipping through the rules beforehand).

https://www.npmjs.com/package/@efficientcss/stylelint-config...




>Use attribute selectors to convey unicity.

> /* Do */

> [id="main"] { max-width: 80ch; }

> /* Don't */

> #main { Max-width: 80ch; }

I strongly disagree with this kind of guideline. The id attribute has very good uses, and in those cases the hash syntax should be the preferred way.

The use of id in an attribute selector is such a bad choice that makes me question the whole document.


I'm curious: why is it such a bad choice?

As for the #selector, in what cases do you need that much specificity? Not a rhetorical question!


iirc, ids are indexed - that is, when you select an #id, the engine picks the element directly out of the DOM. It’s the fastest / most performant way to select an element, because it has the smallest pool of possible nodes to evaluate to match the id provided.

If you use an attribute selector, the engine must search through every single node in the DOM in order to return matches - an incredibly costly operation by comparison.

(Disclaimer, there may well be optimizations I’m not aware of at this point, but I’m pretty sure that’s why ids are generally preferred as a rule of thumb)


I think these rules (and I think they are excellent) are poorly named as "efficient" css. That makes me think of performance.

In that case, yes it's less performant. But the specificity problem is so significant that I've followed the rule of never using ids for styling at all. The problems I've run into with CSS have entirely been regarding maintainability and preventing visual bugs, I've never had any CSS performance problem worth addressing. (I almost skipped this submission because I thought that was what is about, I'm glad I didn't.)


True, this change is about maintainability.

I'm sure the browser css engine treats that id attribute selector (without any regex-like) as an #id. Now if it were [id(*|^|$)=''] then it could have performance consequences, but they won't show up until you have thousands upon thousands of elements at which point maybe you should've looked into virtualization yesterday and not jump to wildcard selectors (speaking from experience).


I see, yes. I meant "efficient" in it's pure economic definition:

Producing effectively with a minimum of waste, expense, or unnecessary effort.

Is there a better term you're thinking of?

And in my experience, the performance cost of using attribute instead of id selectors is so small as being imperceptible. So, as you say, the gain of suing them far outweighs the possible cost.


Yeah, I know about that. Still, a good point. Thanks.

Nevertheless, in practice, I haven't seen any perceptible performance cost in using attribute selectors. It may have been the case years ago, when browsers weren't as efficient or devices as powerful.

I'd say the reduction of specificity here is well worth the theoretical cost.


This is a very interesting approach, and the rules and principles are very sensible. It's nice to see something that tries to really use the platform and emphasize semantic HTML.

Of course, as with any convention-based, getting everyone to follow the rules might be difficult, although the stylelint-config helps.

It would be helpful to see an example of the ruleset applied to a large-ish solution. There are a lot of rules, so it's kind of hard to imagine what it would look actually look like in the css.

Could you elaborate a little on what you mean by “just-in-time” rulesets and how rule 22 ("Component styling should only be served with live components.") works in practice? Are you referring to web components?


I'm working on refactoring some sites in ECSS right now. I can report back when done if you care enough! As of now, you can look into the ecss.info CSS on github if you want a taste. Not large-ish, but still representative I'd say.

https://github.com/efficientcss/ecss.info

As for the "just-in-time" CSS, I include the link tag directly in the component itself. Could be Web component or any other type. Yes, the link tag is repeated, but the browser does not download/interpret the file again since it's cached. Been experimenting with this in the past year and I only see advantages.

First, there's a lot less unused CSS in any page (for instance, on Tailwind's front page there is something like 80% unused CSS as per Google coverage tool).

Second, you have a live link to the CSS in your component file (I use Vim but I know VS Code can follow sources too).


ECSS also means "European Consortium for Space Standardization". They edit the standards for all fields within space engineering :)


Ha! Nice, we're in good company then!


Eh, I dislike Tailwind but this doesn't sound like it will hold water in the long run.

Why the hell does a rule talk about consistent padding and then not use css variable? A class name .card is a sure thing to conflict somewhere. Typography inheritance is another good way how to introduce hard to debug bugs. Global scope css - ewww (use only absolute minimum necessary).

Please use css-in-js, Tailwind, shadow dom or at the bare minimum css modules. Friends and future you will thank you.

But hey, maybe they are building some blog. I live in the apps world.

Also some rules are valid like the one about not using margin on the component itself.


Thanks for the comment. It reminds me that examples should be more real-like. Hehe. Because, yeah, I would absolutely use a custom property for it. Same with .card, a simple example which in practice may be more precise, yes.

Global scope is for base rules, yes. Rhythm, typography, maybe colors only. Still it's great to be able to style these design layers globally!

I'll adjust the examples to reflect this. Thanks for the lesson!

PS: hard to debug bugs? The inspector shows styles handily for global styles!


And because of your post I was prodded to learn more about layers, thanks for that!


Nice! They're great for establishing a strict scope for rulesets.


A pre-commit script would be nice and easy entry (at least for me)


As of now, you can integrate the Stylelint config in the editor/IDE of your choice to have live linting (tested with VS Code and Vim). Or you can run stylelint manually in the terminal.

Didn't think about git pre-commit hooks to be honest. But I'll look into it. If you have any ideas/suggestions, they are very welcome!


Check out lint-staged and husky within the node ecosystem.


Pretty solid approach, been a good read.

CSS performance is underrated as well.


Thanks! And you're right about performance. The "just in time" approach as an alternative to the monolithic minified CSS file has proven to be quite interesting on this subject.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: