views:

218

answers:

7

I use only classes and never use IDs. Many people like to use IDs for different reasons.

I've seen many questions regarding IDs vs classes on stackoverflow, but no one addressed pure code organization point of view disregarding compatibility and runtime performance.

From code organization point of view, I think that using IDs is bad just like using global variables in Visual Basic code.

One reason is that IDs have to be unique which introduces unnecessary and bad dependency between different independent parts of your code (controlling different parts of HTML DOM tree).

Another reason is that making new class names is actually easier than ID names because with IDs you have to worry about global scope and with class names you need to worry only about uniqueness in local scope, same benefit as with local variables.

Most people will argue that performance of addressing by ID is better than by class and I will agree with that. But as browsers become more advanced with native implementations of CSS addressing from javascript and computers become faster, performance becomes less and less important. So let's disregard it and concentrate only on organization of code in context of current question.

This discussion started here, but my potentially wrong advice generates negative points and became too big to keep in comments, so here I try to convert it into something positive and manageable.

One visible point in favor of IDs is to use them as a tool of rule prioritization because priority of #name is higher than priority of .name. My response: using IDs to raise priorities is bad hack, it's cleaner and there is more freedom if you use additional root elements inserted between body and other levels of tree, for example priority of body div div span.class1{} is higher than body div span.class1{} is higher than body span.class1{} is higher than span.class1{}. Another tool to use for that purpose is !important. Some may argue that using more root elements means more difficulties when the page structure changes, but I don't think this is the case because you never have to put anything between body and designated for prioritization divs. Those divs can always stay below body and above all other content.

Another interesting association was brought about pointers and that IDs are not bad because pointers are not bad. My response: pointers are bad if you hardcode absolute memory address in your code. Using relative pointers is always better (examples: using segments(CS,DS,SS,ES) in 8086 CPU; relative variable and method addresses generated by compilers). If we consider DOM tree as memory and compare using ID to using class then #name represents absolute memory address, but div.tab1 .name represents relative address (relative to div.tab1).

Another supporting point that I've seen for IDs is that elements with IDs are more easily available in javascript as becoming global properties. My response: again, this is like saying that global variables in Visual Basic are more conveniently available. The problem is that you can't keep large enough global (or any other) namespace in order without introducing naming hierarchy like level1_level2_name, which is just a hack to replace one namespace mechanism with another. DOM tree is convenient enough to organize namespaces, why disregard it ?

Namespace simulation inside IDs using underscore is bad because you can't establish naming context and will have to duplicate all paths everywhere in your code. That practically means that you won't be able to use CSS preprocessors that fix inability of CSS to use contexts.

+12  A: 

quick answer: its a best practice, if you have only one instance of something and you only want one instance if it, use an ID to define that there should only be one instance of it.

This is like the difference between constant variables vs regular variables. You can use a regular variable to be a constant variable, but its better to define it as such if that is what its intended to be.

It lets fellow programmers (and yourself) know more information about the object.

ocdcoder
-1: "Do it because it's a best practice" is not a meaningful answer unless you also state *why* it's a best practice.
Dave Sherohman
@Dave, i did state why, read the rest of my answer.
ocdcoder
@ocdcoder: marking variable as constant gives only benefit without any expense, marking element with ID is expensive because it charges global namespace potentially polluting it. That side effect is too expensive to accept advantages. Why not consider better analogy with global variable names or global namespaces ?
alpav
@alpav, it was not meant to be a perfect one to one example, but just an example of what you can use something one way when there is something else that is designed to do what you really want. Plus you mentioned disregard "speed and compatibility", so i wasn't worried about being 'too expensive'. ALSO, claiming that ids are too expensive is completely situational. If you are doing a LOT of dynamic JS, I would argue the opposite.
ocdcoder
Thinking about it more, you gotta think about what is "expensive", memory or cpu? To my knowledge, its less expensive for the cpu to do a search for an id than it is to do a search for classes (this goes for css and js). That being the case, it may be worth the added memory for the cpu gain, which I think many JS developers consider to be the case.
ocdcoder
quoting you "no one addressed pure code organization point of view disregarding compatibility and runtime performance." -- if that is the case, then id's should be used when you want to address an item that is purely unique, as they are a part of specifications to represent (aka, to organize) purely unique elements.
ocdcoder
@ocdcoder: I've read your answer several times and I'm still not seeing a clear reason stated. Paragraph 1 says, "it's a best practice; you should do it". Paragraph 2 says, "you can do this, but you should do that instead". Both are simple assertions with no reasoning to back them. Paragraph 3 is the only one that gives a reason - "it provides more information" - but it's a very weak one, as the information that "X should be unique" can be conveyed just as clearly (if not more so - I've seen pages using duplicate CSS ids) with .X-unique as with #X; this is not dependent on using ids.
Dave Sherohman
This question disregards CPU and memory, so 'too expensive' is about cost of programmer labor. Term "namespace pollution" is all about cost of labor it has never been about CPU or memory.
alpav
Is it not a mistake to disregard CPU and memory? Certainly you could argue for the most elegant and efficient design in terms of programmer labor, but if it then fails in implementation and user experience it will be for naught. (vis. twitter)
ghoppe
@ghoppe: It is mistake for some huge websites where cost of labor is insignificant, but for some internal ERP that is implemented in HTML/CSS/JS cost of labor is higher priority and those assumptions about CPU, memory, compatibility are valid.
alpav
+4  A: 

I agree with you in general: Classes are much cleaner to use; you can create "namespaces" and clean cascades with them; and they can be combined: class='class1 class2'.

IDs still have their place when you're addressing really unique elements on the page, especially when addressing an element that is going to be changed in JavaScript later (e.g. a hidden overlay.)

Pekka
+1 Agree. I prefer .class over #id css declarations for these reasons. But this doesn't mean #id should _never_ be used.
ghoppe
@Pekka: I still don't get definition of "really unique".You still have to use classes for TDs even if they have to be unique within TR so why use IDs for something that have to be unique on BODY level ? If I need to have a shortcut to address something to avoid long CSS path then I just keep reference on it in my JavaScript structure.
alpav
@alpav if you have *one* message box `#messagebox` that you are showing 20 seconds after page load using `$("#messagebox").fadeIn()` then it makes sense to make the CSS hiding that box (`display: none;`) to that one element with that ID, and not a class. It's the only good reason to use IDs I can think of.
Pekka
+2  A: 

For me, I like using IDs on HTML elements that are absolutely unique, and classes on things that are possibly non-unique (regardless of whether or not they are).

For example, I would use <div id="header"> because there can only be one header. But I would use <div class="profile"> if there could conceivably be more than one on the page (even if there is only one). This makes the CSS a little easier for me to understand.

Plynx
I use ID's for layout elements and classes to style elements within them, in much the same way as you mention, so i can do things like #header div { some style }, and know that its not going to affect any div elsewhere in the page and still easily identify that its used in the header.
Mauro
@Plynx,Mauro: That is what my question was about and that is what I am really against. Using IDs for that purpose is wrong from code design point of view. Many other cases like speed, compatibility, href='#name' are valid, this one is not. Having id=header anywhere means that you can't safely inject your page into another page, can't make it as component, can't utilize benefits of CSS preprocessor.
alpav
@alpav which is exactly the point! One means one. Having two #headers on a page would be an error. They should not be embedded on another page. Any "embedding system" (AJAX preview as a browser addon is the only use case that comes to mind) needs to account for that anyway so the onus is not on the page designers but on the embedding system to get that right. I also don't see any loss of benefits from a CSS preprocessor--they handle IDs just fine.
Plynx
@Plynx: benefits are lost with preprocessor because with classes you can use more than 1 node in path to address element so you can use simple small class names, but with IDs you have to use only one, so you have to encode paths into IDs to make them unique. Preprocessors allow to specify and reuse part of CSS path, but they do not or have inconvenient syntax to specify and concatenate parts of IDs.
alpav
+4  A: 

I look at classes and ids the same way I look at a (programming) class versus an object. An object is one, specific instance of a class. I want all my classes to share a certain number of behaviors, but an individual object may have its own unique properties. CSS classes are for applying properties to broad groups of similar items, ids are for specific items and the specificity hierarchy reflects that.

To invert your question, why use classes at all when you could achieve the same effects with very specific tag selectors? For ease of use, repeatability and clarity of intent.

Tom
Because if you use IDs then paths are going to be encoded into names and then you can't use CSS preprocessor to avoid path duplication or it is harder to use it.
alpav
+1  A: 

"DOM tree is convenient enough to organize namespaces, why disregard it ?"

Because the DOM can change due to AJAX or other javascripty-goodness.

I like @ocdcoder 's constant/variable analogy. Sometimes you want to refer to exactly that particular element. Having to adhere to a strict DOM namespace is a straightjacket that doesn't help maintenance at all, imho.

ghoppe
Constant/variable analogy has one flaw - IDs have side effect (namespace pollution), but constants don't. Why is this analogy better than global variable analogy ?You can keep references on DOM nodes inside your own JavaScript hierarchy. That can help against DOM changes. Also if javascripty-goodness is so dirty that it spoils your DOM then it's better to avoid it rather than let it force you to use bad design pattern.
alpav
+1  A: 

I think the discussion is incomplete without addressing the underlying reason for using classes and IDs. Saying that either should be used in every situation does not work well generally and historically.

The original purpose of classes was to attach presentation to the document, or introduce style as a separate concern than the structure of the document itself. Please correct me if I am wrong, but I think you are trying to address the problem of attaching semantic information to the elements rather than just style. If that is indeed the case, then classes serve two purposes for us - controlling presentation, and acting and semantic tags. IDs serve the purpose of acting as a unique semantic tag.

XML is highly extensible and allows namespaces which was supposed to be used in XHTML documents to assign meaning to a document as authors saw fit. But there were none in HTML and maybe it was browser incompatibilities or the non ease of use (as Tom mentioned), but most web pages and applications did not take the path of using namespaces in XHTML.

Surely the HTML spec authors saw the glaring need for attaching semantic data to HTML documents and introduced the data- attributes in HTML5 that could be assigned to any element. I would argue that if it's semantic meaning that you are concerned with, this is absolutely the best approach so far, but again browser incompatibilities have always had a major role in determining which spec becomes more commonplace and I hope IE does not have their say this time.

Anurag
@Anurag: So if I understand you correctly then if my question contained more specificity stating "within context of semantic meaning" then you can agree with me that it's better to never use IDs ?
alpav
@alpav - yes, IDs have their place, but not in adding semantic meaning, and neither classes by my standards. Also, there are no namespaces in CSS (its still being worked out), so I guess you mean some pseudo-namespace that the developer creates and adheres to?
Anurag
@Anurag: yes. HTML/CSS/DOM give node access freedom that is well used if developer creates and adheres to own constraints/structures such as pseudo-namespaces.
alpav
+1  A: 

Using an id attribute allows you to link to an element E.g. if you’ve got this HTML:

<div id="log-in">

you can link to the log in section of the page using href="#log-in".

You’re quite right that classes are usually the most convenient and appropriate way to identify page components. But assuming that you’ve got an element that only appears once per page, and assuming you can give it an appropriate name or generate one, I don’t think you’re likely to run into problems using an id for it.

Paul D. Waite
href='#login' is one valid reason to use IDs that I forgot to address, but ajax pages usually handle things through onclick events so there is minor need to use those hrefs and mostly in static pages. I guess I should've included more exclusions into my question because my question is about good code design.About "element that only appears once per page", could you give any examples of global variables that appear only once per program so it should stay global (VB,JavaScript, ...) except those cases when it's root of a well known library like dojo or jQuery ?
alpav
@alpav assigning a href and using that to load ajax content rather than with onclick has the added advantage of bookmarking and a working back button (if history using fragments is managed well).
Anurag
“could you give any examples of global variables that appear only once per program so it should stay global” — I don’t think global variables are a great comparison. Classes are just as global as ids in HTML and CSS, it’s just not invalid to have several elements with the same value for their class attribute. They’ll still all attract the same styles, so if you accidentally use the same class for two different things, you’re still screwed.
Paul D. Waite
@Paul: Yes, classes are global too, but together with classes I advocate using DOM tree, meaning that I almost never use .class, I almost always use something like .page1 .tab1>.field1 With that in mind tab1 is local to page1, field1 is local to tab1 so I never worry about uniqueness because I never need to think in global namespace. Anyone who uses IDs has to keep registry of global names, which is additional burden, exactly the same burden as with global variables.
alpav
“I almost always use something like .page1 .tab1>.field1” — right, but other people maintaining the code might not keep the same discipline. You’ve still got to be aware of classes and ids throughout the stylesheet, and the pages it’s applied to. (Plus the child selector doesn’t work in IE 6, so if your code has to work there, you’re stuck with just descendant selectors, which can fall apart of you’re styling elements that can be nested within themselves.)
Paul D. Waite
@Paul: this is why I excluded compatibility - IE6 with >; "people maintaining the code" is more interesting point. If I use IDs then other people are required to follow ID prefix pattern page1_tab1_field1 to avoid collisions with me, if I use DOM tree then other people are required to follow node prefix pattern that I mentioned before, so from people interaction point of view it seems like there is no difference.
alpav
Sorry, you’re quite right, you did exclude compatibility. “If I use IDs then other people are required to follow ID prefix pattern page1_tab1_field1 to avoid collisions with me” — they don’t have to use that particular system, but yes, with both classes and ids, you have to be aware of other classes and ids in the system. That’s kind of my point: there isn’t enough difference between classes and ids to justify *never* using ids. There’s...
Paul D. Waite
...no *problem* with never using ids (unless you need to link to a page fragment), and it’s rare in practice that ids are necessary, but I don’t think they cause problems when used for their purpose, i.e. uniquely identifying an item on a page. It’s great that you’re thinking about HTML and CSS at this level of detail though.
Paul D. Waite