Don’t use IDs in CSS selectors? (2011)
oli.jp
oli.jp
I was testing with an id which contains a "-" (hyphen). As the hyphen isn't valid for a variable, you can't access it directly or via the window object (with the "dot" notation). However, it is there, and you can access it with the array-like syntax.
Is this part of the spec? Or creative interpretations?
tl;dr: HTML element with id="foo-bar". You can't access it as the variable foo-bar in the global context or window.foo-bar (invalid var name). However, you can access it via window['foo-bar'].
Classic race to the bottom. :(
I agree that polluting JavaScript's global space is bad. I wonder if this could be a vector for some attack. Probably not because it would be well known for a long while (but I didn't know about it untile 5 minutes ago, thanks).
Despite the easy access as a global variable, using document.getElementById() turns out to still be faster - http://jsperf.com/id-vs-class-vs-tag-selectors/328
In my development practice I've found that messing CSS with IDs don't help scale your app ( you can hardly override them ), they are also subject of all the reasons stated here and in the article ( bad performance, global scope introduction, ... ).
The only reason to style IDs would be if I happen to have an old theme that people styling it were using IDs.
I totally don't support styling IDs ( or using !important - which basically is on the same page ).
An ID, by design, semantically references a single thing. This has important meaning when making HTML (amd CSS) readable and parseable. Now, I'm not necessarily saying this is a 'winning' argument, but throwing away a useful tool for declaring semantic meaning for hand wave'y arguments about 'britality' feels like overkill.
Multiple elements w/ the same id will pick up css styles, though.
// HTML
<div id="myLoginWidget">...</div>
// SCSS
#myLoginWidget {
@extends #baseWidget;
@extends #somethingElse;
@include rounded-cornders(0.5rem);
background: darken($base-blue, 20%);
...
}
Is 'cleaner' than: // HTML
<div class="baseWidget somethingElse small-rounded-corners dark-blue-bg">...</div>
// SCSS
.baseWidget { ... }
.somethingElse { ... }
.small-rounded-corners { ... }
.dark-blue-bg { ... }
It achieves the same reusability (in code) without polluting the content (HTML) with the presentation (CSS).If you are using the classes from the second example in more than one place in your HTML and then depending on your actual CSS in those classes, then the second option may be more efficient then your first. In SASS, it will totally depend on how you write the actual CSS, not just the class versus id debate.
But a question from the article comes to mind in your example, what if you are requested to insert a second login widget to the page? Even worse, if your Javascript uses the ID for targeting the login code then you have to reconsider that code as well.
There's a completely valid argument that any "improvements" in the above sense are outweighed by the extra time in downloading and parsing a larger cold-cached CSS file, but in my case I am happy to rely on the browser cache and the compiler to be smart (and maybe sacrifice a small amount of resulting CSS weight if it's not) resulting in "cleaner", more semantic HTML (and arguably CSS).
In terms of the second login widget, you're absolutely right, my implementation would fall down, but then it would be a VERY simple refactor. However having n of something on a page would have a semantically different meaning than my case, so therefore classes are indeed the right specificity method!
I strongly disagree. Obviously there are always exceptional circumstances, but if something is really a best practice, that means "if you decide not to do it this way, you should have a good reason for that decision".
Now I would agree that people are too quick to call something a "best practice", when really it's just their personal preference (e.g. "always use semicolons in JS", or "never use semicolons in JS").
The coding style guide put out by your 12 member startup isn't "best practice" for everyone. It's just best practice for continuing to work there.
Whenever something deviates from best practices, I would think that that raises a red flag for justification of difference.
I would argue that a quorum of engineers would generally agree with whatever is justifiably deviating from best practices. If it makes sense to you because of good engineering reasons, then it should probably make sense to other engineers. Reality perhaps dictates otherwise, but that's what it should strive for.
Instead of a test with a list of 1000 elements, try a test with a nested list of 1000 elements. The performance problem with classes is that the browser has to traverse the DOM to find them, starting from the deepest element and working up. It's pretty quick, but not that quick when you have a deep tree. Whereas finding an element by ID is literally just a single lookup in an index regardless of where the element actually appears.
That said, DOM traversal was a very slow procedure for a long time, so browser developers spent a lot of time and energy optimising it. It's way better than it was. It could well be the case that classes don't have the performance problems they once did. Unfortunately, the test in this article won't show whether that's true or not.
To clarify, if you have a selector like "div.class a", and HTML like;
<div class="class"><div><div><div><div><div><div><a>Woo!</a></div></div></div></div></div></div></div>
..then the browser goes to every anchor in the DOM and then looks up the tree asking 'Does this div have a class of 'class'?". That's what's slow. If you use "div#id a" then the browser can look for the id more quickly. That's why IDs are faster.
Source: I implemented this in Servo and studied Gecko, WebKit, and Blink code for it.
Best I'm aware this was true until browsers all supported getElementsByClassName:
http://caniuse.com/#feat=getelementsbyclassname
The only material difference between that and looking up a DOM ID is that the first yields an array (of a potentially wide range of tags) instead of a single element.
Plus, as already highlighted in a separate comment, `div.class a` or `div#id a` will both work the DOM tree from every `a` element up (just like describe) anyway.
Obviously, I don't work at the scale of Facebook, but it's a tendency that I have witnessed in different projects.
So it's possible that the speed tradeoff between classes and ids become irrelevant, if it's not already.
So the selector `a#id` will be faster than `a.class` but a parent selector uses the same heuristic.
https://speakerdeck.com/vjeux/react-css-in-js
That presentation goes into more depth describing problems with CSS. Given a virtual DOM in JS, the solution becomes simple and obvious: plain objects.
Its interesting how React completely reinvents "best practices".
(missing question mark from original title and the year written)