6 ms·
Don’t use IDs in CSS selectors? (2011)
- Joe8Bit 12y agoI have to admit to not feeling too strongly either way about this, but the argument I would have against the 'never use IDs in CSS selectors' is purely a semantic one. 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.
- lcmatt 12y agoThat's exactly the problem - you're referencing a single element which can't be reused. I bet all the styling being used on the element could be broken down in to reusable classes leading to cleaner code and less specificity.
- Joe8Bit 12y agoI would argue about cleaner code, in my view doing something like: // 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).
- talmand 12y agoAre we saying "cleaner" as in "more efficient"? You have to keep in mind the resulting CSS generated after compiling. There is a balance to be had between clean CSS and efficient 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.
- nirvdrum 12y agoMaybe I've just seen some particularly bad JS, but I often see a lookup by class name and then just fetching the first element. This pattern would suffer the same fate, without the semantic hint that there should only be a single element that an ID provides. Likewise, in my experience, a lot of code gets more convoluted when trying to be more general than it needs to be (the YAGNI principle) or by trying to be DRY by happenstance rather than by semantics.
- Joe8Bit 12y agoIf the SASS compiler wasn't smart enough to deduplicate several references to a mixin it would unquestionably mean redundant properties and more weight in the compiled CSS, but it wouldn't be any less efficient from a page paint POV. 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!
- ratbeard 12y agoA case where the "only 1 instance" assumption can break is on a styleguide page, where you might want to include multiple instances of a singleton element to show it in different states, say for your #header for example. Multiple elements w/ the same id will pick up css styles, though.
- onion2k 12y agothe performance difference between classes and IDs is irrelevant 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.
- debacle 12y agoDid you read the article? It said explicitly that regardless of `div.class a` or `div#id a` the same lookup takes place - every anchor on the page's parent is checked to see if it has the id or class specified by the selector. So the selector `a#id` will be faster than `a.class` but a parent selector uses the same heuristic.
- deleted 12y ago[deleted]
- ddebernardy 12y ago> 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. Best I'm aware this was true until browsers all supported getElementsByClassName: http://caniuse.com/#feat=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.
- _RPM 12y ago[Slightly off topic] One of the reasons I wouldn't use ID's is because the DOM element with that ID is automatically introduced to the global scope. Open up the console and type "up_8630368" and you will see it yields a DOM Element.
- fla 12y agoUpvoted with : up_8630835.click()
- thisGuysAccount 12y agosame to you, in Firefox.
- paulojreis 12y agoIs this true? If I have a element with id="foo", then "foo" will be available as a variable in the global JS context? I tried, but can't reproduce it (Chrome, Windows & Safari, OS X).
- paulojreis 12y agoOK, sorry about the reply to myself, but it is true indeed. 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'].
- nailer 12y agoI've been told it's unspecified, but IE implemented it. and when when IE was the most popular browser, other browsers replicated the behaviour as some sites were using it in their JS - as a kind of quick shortcut for document.getElementByID. Don't have a reference though.
- ad_hominem 12y agoHN title should be "Don't use IDs in CSS selectors? [2011]" (missing question mark from original title and the year written)
- dreamweapon 12y agoThis is rather like famous "Go To Statement Considered Harmful" dictum of lore, and its variants in other contexts: the key takeaway shouldn't be that we should never use these constructs -- rather than we should be circumspect about using them, as they tend to have hidden side effects.
- drinchev 12y agoTotally agree, but in this case I can say for sure that the benefits of using IDs are so impractical, that with no doubt I will add a class name to the target element style the class not the ID. 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 ).
- moron4hire 12y agoI don't think you can really make a blanket statement like this. When you make blanket statements, you're ultimately basing a decision on superstition, rather than need or evidence. It's why I don't really care for anything that claims to be "best practices". The term "best practices" really just means "this worked for us in our situation". That's great, and one should be aware of such things, but that doesn't make it a standard or a law.
- simonsayscode 12y agoI disagree with your statement. I believe that "best practices" means that "this is probably how it should be in the majority of uses." Obviously each situation is different and not everyone's solution will work for you, but I'd be willing to be that more often than not, it would. Whenever something deviates from best practices, I would think that that raises a red flag for justification of difference.
- moron4hire 12y agoYeah, but justify to whom? To the Jr. programmer trying to move up in the company, no matter who he has to throw under the bus to get there? To the entrenched Sr. programmer who uses effort to make up for a lack of skill? To the manager who doesn't know anything about programming?
- simonsayscode 12y agoYou're mixing politics with good engineering. 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.
- mistercow 12y ago> The term "best practices" really just means "this worked for us in our situation" 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").
- deleted 12y ago[deleted]
- spion 12y agoOr simply don't use CSS at all: https://speakerdeck.com/vjeux/react-css-in-js 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".
- 1010 12y agoIn my experience, "Don't use X at all" is very rarely, if ever, a suitable response to "X has some flaws".
- spion 12y agoI agree, and I understand that such "radical" claims invite a dismissive reaction (downvotes). But the presentation really does make a very compelling argument and offers a simple and elegant alternative solution that solves most problems.
- reverius42 12y agoTotally agree. I have found that most of the problems solved by separating CSS, HTML, and JavaScript weren't really problems to begin with, if you model your application views the way React does (as a render function that produces DOM tree based on external properties and internal component state). Somehow using multiple technologies (CSS for styling, HTML for markup, JavaScript for logic) got conflated with "separation of concerns", but true separation of concerns involves separating component A from component B. Encapsulating the entire component in JS actually helps cohesion.
- deleted 12y ago[deleted]