12

In designing the HTML and CSS for a page, when should I use

img.className

versus

.className

versus

#idName

or some other variant?

Are there guidelines or recommendations?

1

12 Answers 12

19

In general you should be as specific as the item demands.

There is no general rule, it depends on the style in question.

A lot of people will recommend you keep to the lowest specificity with the theory that this allows the maximum cascading reuse but this is absolutely toxic in real world situations where you have multiple developers all working on slightly different versions of what a .foo might look like. Pollution from inheritance you did not want leads to massive bloat in trying to undo that locally or time-loss in refactoring.

The best guideline I always offer is to try and think of CSS in OO terms: class selectors map to interfaces more or less, tags map to classes, and ID selectors map to instances. Consequently decide if the style you want to apply really applies to that thing, all things like it, or anything which wants it.

I also strongly encourage you to make use of high level IDs on wrapper elements so you can write selectors in a namespace like fashion (i.e. #foo .bar, #foo .baz where #foo is unique to a page or set of page designs) which allows you both a level of specificity which reduces cross-design pollution and a level of generality which lets you make the most of cascading CSS reuse.

Best of both worlds.

Sign up to request clarification or add additional context in comments.

3 Comments

That makes it really easy to understand from an OO perspective. Thanks!
Interesting analogy. But in my opinion looking at CSS in terms of OO can be dangerous. It is fairly easy to understand if you have a good grasp of OO. For people that are less experienced in OO this analogy may be much harder to "get right". And if wrongly interpreted, it could lead to bad CSS code. The problem is that you work on two entirely different things: The visual definitions (CSS) and the data model (DOM). And neither has real classes or instances. I like the analogy nonetheless quite a lot :)
@exhuma - this is possibly true but my experience is that those who come from a design background have a good grasp of CSS and/or ask questiosn elsewhere. People who ask CSS questions here are programmers who should understand OO - and to be honest 90% of the time programmers are terrible at design becuase visual studio and apps dev in general promotes ideas which are are really really anti-CSS. Don't forget that CSS and DOM should be separate. The class names you apply at the DOM level are really just decorator attributes.
8

It depends on the intended semantics, and, as others said, be as specific as possible.

  • #idName for unique elements on the page. Good examples are #header and #footer
  • TAGNAME for general purpose page styling.
  • TAG.classname and .classname for exceptions/overrides to the above rules.

And don't forget the use of advanced selectors. A bad example:

<style>
    H1{ font-size: 200%; color: #008; }
    #mainMenu { color: #800; }
    .in_the_menu { color: #800; font-size: 150%; }
</style>

<h1>Hello World!</h1>
<div id="mainMenu">
    <h1 class="in_the_menu">My Menu</h1>
</div>

The same could have been achieved with:

<style>
    H1{ font-size: 200%; color: #008; }
    #mainMenu { color: #800; }
    #mainMenu H1 { color: #800; font-size: 150%; }
</style>

<h1>Hello World!</h1>
<div id="mainMenu">
    <h1>My Menu</h1>
</div>

The second example gets rid of the superflous "class" attribute on the H1 element in the "mainMenu" div. This has two important benefits:

  1. The HTML code is smaller and cleaner
  2. You are less likely to forget to add the class attribute

If you take good care of you CSS, and make use of proper advanced selectors, you can nearly completely leave out CSS classes. And keep them only for exceptions/overrides.

Take this example which draws boxes with headers:

#content H2{
   border: 1px solid #008789;
   padding: 0em 1em;
   margin: 0.2em 0em;
   margin-bottom: 1em;
   font-size: 100%;
   background: #cccb79
}

#content H2 + DIV{
   margin-top: -1em;
   border-left: 1px solid #008789;
   border-right: 1px solid #008789;
   border-bottom: 1px solid #008789;
   margin-bottom: 1em;
}

Now, as soon as you follow a H2 with a DIV in the #content element, you have a nice box. other DIVs and H2s are left alone:

<div id="content">

    <h2>Hello Box!</h2>
    <div>Some text</div>

    <div>Some more text</div>

    <div>Some more text</div>

    <h2>And another title</h2>

</div>

If you get these rules right, you hardly ever need classes, and can work with IDs and TAG names alone. And as an added bonus, your HTML will be a lot nicer to read and maintain.

4 Comments

I used "divs" here as example, but it surely would have worked with "p" tags as well. Which would be semantically better.
Also, if you give your classes names based on the expressed meaning ("error" instead of "redOnYellow") you'll find that the HTML becomes even more readable/maintainable. And these classes often have a much higher reusability.
Some great best practices here. Thank you! The only thing I don't like so much is moving the complexity out of HTML and into the CSS with the use of advanced selectors.
I disagree. The added complexity in CSS is in general presentation logic. Which belongs into CSS. If it gets too complex, then it is likely that your HTML can be adapted to that. Doing this kind of "strong" separation forces you to think about your DOM. It even forces you to make use of less common (yet useful) HTML elements. In the end, this enriches your DOM, which in turn is useful for JavaScript manipulations, XSL Transformations or scraping. But there are always exceptions. There are always cases where you may want to "break out of the box". Purism is not always a good trait ;)
3

You preference should be, in order from highest to lowest:

  1. id

  2. tag
  3. tag.className
  4. .className

ID selectors are fast. Tag selectors are reasonably fast. Pure class selectors are slow because the browser essentially has to interrogate every element and see if each has that class. Getting elements by ID or tag name are "native" operations from a browser's context.

Also, I find it good practice to make your CSS selectors as restrictive as possible otherwise it just turns into a mess and you end up getting all sorts of unintended consequences where CSS rules apply where you didn't otherwise expect, which often forces you to create a similar yet different selector just so none of the rules regarding the first don't apply (translating into more mess).

Basically if you know if you only use a class on div elements then do this

div.className

not

.className

If you apply a class to several elements just list them:

h1.selected, h2.selected, h3.selected

instead of

.selected

In practice I find very few situations where you need to use "naked" class selectors or where it is advisable to do so.

4 Comments

Thanks for your answer! Is there ever a good reason to just use tag?
Sure, when its appropriate, like h2 { font-size: xx-large; }
Using just tag is in fact very common. The most simple example is to change the display of all links throughout the site: A { text-decoration:none; color: #080; } Then you can always override or extend where necessary using more specific rules (id, class, pseudoclass, ...). For example: A:hover { text-decoration: underline; }
This answer discounts the danger of over-specificity. If you've ever worked on a large and mature app that has unreadable LESS / SASS "pyramids of doom" that cannot be refactored because they're trying to be more specific than their parents' elements without resorting to !important, you'll know what I mean. Overly specific css is also much harder to refactor and is a self-propagating problem.
3

you should use the selector best describing your rules

  • id: when you want to select one single element

  • .classname: when you want to style elements regardless of their tag
  • tag.classname: when you want to style only tags with the given class
  • tag tag tag: when you want to style all subelements of a tag

Comments

2

Class selectors

.className

This is to be used when you have more than one element on the page that you would like to apply the same style to. It can be to any tag element. So in the following all will use the same style as set out by the .className.

<a href="#" class="className"></a>
<p class="className"></p>
<img src="/path/to/image.png" class="className" />

But you can also restrict it like so:

img.className

By placing the tag along with the style definition, you're saying that this style is only to be used when it's the class used by that particular tag, in this case, an image.

HTML code will look like this:

<img src="/path/to/image.png" class="className" />

If you have other elements on the page using the same class style, but are not of the same tag, then the styles set out in this will not be applied and they will take on the more generic version as mentioned in the first example.

So repeating the example above:

<a href="#" class="className"></a>
<p class="className"></p>
<img src="/path/to/image.png" class="className" />

Only the image will take on the style as set out by img.className whereas all the rest will take on the style rules set in .className.

ID selectors

#idName

This is to be used when there is only one instance of a particular element that you wish to apply the style to.

You can also force it to apply only in certain tag conditions as you have earlier with the class definitions.

p#idName

This example will only apply to the paragraph block marked with the ID:

<p id="idName">

If you were to put that id on another element, like this:

<div id="idName"></div>

Then it will not take on the style set out and be ignored.

Comments

1

As to your two first selectors, the first of the two will overwrite the second, as it's more specific. You can calculate the specificity of a selector.

Comments

1

One thing worth noting is that some server side scripting technologies (most notably ASP.NET) don't play well with using IDs for your styling. If there is a chance your design will be used with such a technology, I recommend forgetting about #id selectors and use tag.className instead.

The reason is that ASP.NET actually changes the ID that ends up in the HTML based on a number of criteria, if the tag is output by a server side control.

4 Comments

good point but fwiw, you can almost always get around this by inserting a new (and otherwise redudnant if not for asp.net) wrapper HTML element which does not have runat="server"
@annakata: That depends on your HTML and CSS. You can't just insert wrapper elements anywhere. If you used the very specific tag#id selector it is especially difficult, but technically you're not allowed to put block elements inside inline elements either. It might also break in situations where you use a child selector (>) and various other circumstances.
There's very little that can't be wrapped in a superfluous div or span (block or inline options there) and a child selector is trivially modified to be in relation to that div/span. It's entirely unnecessary and unpleasant, but so is asp.net (webforms)
Good point. I am mostly working in ASP.NET so this could be a factor - irritating.
1

I know this is a pretty old question but for all those who are reading this just now... There are 4 categories of rules in general: ID Rules, Class Rules, Tag Rules, Universal Rules. And it's important to mention that class selectors are faster than tag selectors. So you should always use them in the following order
1. ID Selector
2. Class Selector
3. Tag Selector
4. Universal Selectors

In your case you should never use the tag name before class name.

You can find more information here: Writing efficient CSS

Comments

0

It really depends on the situation:

.error{
  color:red;
}

p.error{
  background-color:yellow;
}

div.error{
  background-color:grey;
}

Always use the cascading effect of CSS to your advantage.

Comments

0

It's good practise to use the least specific rules you can for each rule.

How you structure your CSS will depend on the particular needs of the design.

3 Comments

completely disagree, I'll post why
Your answer, while a better - more complete - answer than mine, starts out with "In general you should be as specific as the item demands" which reads to me like a different way of saying what I'm saying. You follow it up with an argument for one way of structuring CSS, I suggested there are many ways to do things - different scales of projects need approaching in different way. It doesn't seem to me that there is much to disagree on.
Possibly I could have worded that first sentence stronger. The OO guideline is the one I swear by, but if forced to consider a scale of specificity I would encourage more not less (for the pollution reason) and this is where I take exception to your response - the first statement is dangerously misleading. The second statement we agree on :)
0

Yes. You may want to use the same classname for two elements in the future. Be explicit and clear. This will also prevent class-rules from overlapping onto unintended elements.

h1.title { font-size:18px; } /* My h1's are big */
 p.title { font-size:16px; } /* My p's are smaller */

  .title { color:#336699; }  /* All titles are blue */

Use ID's only when necessary, and only once per page.

Comments

0

When to use what depends on what you want to select. img.className (type selector + class selector) selects only IMG elements that’s in the class “className” while .className (just class selector) selects any element that’s in that class and #idName (id selector) any element with the ID “idName”.

But besides that, the selector all have a differente specificity that affects the order in which the properties of that rules overwrite the one of others.

So if you have an IMG element with the ID “idName” that’s in the class “className”:

<img src="…" id="idName" class="className">

The properties of the rules would be applied in the following order (specificity from highest to lowest):

  1. #idName
  2. img.className
  3. .className

But when you use a specific class only for one specific type of elements (e.g. “className” only for IMG element), you can go with only .className.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.