235

In the past I've always used underscores for defining class and id attributes in HTML. Over the last few years I changed over to dashes, mostly to align myself with the trend in the community, not necessarily because it made sense to me.

I've always thought dashes have more drawbacks, and I don't see the benefits:

Code completion & Editing

Most editors treat dashes as word separators, so I can't tab through to the symbol I want. Say the class is "featured-product", I have to auto-complete "featured", enter a hyphen, and complete "product".

With underscores "featured_product" is treated as one word, so it can be filled in one step.

The same applies to navigating through the document. Jumping by words or double-clicking on class names is broken by hyphens.

(More generally, I think of classes and ids as tokens, so it doesn't make sense to me that a token should be so easily splittable on hyphens.)

Ambiguity with arithmetic operator

Using dashes breaks object-property access to form elements in JavaScript. This is only possible with underscores:

form.first_name.value='Stormageddon';

(Admittedly I don't access form elements this way myself, but when deciding on dashes vs underscores as a universal rule, consider that someone might.)

Languages like Sass (especially throughout the Compass framework) have settled on dashes as a standard, even for variable names. They originally used underscores in the beginning too. The fact that this is parsed differently strikes me as odd:

$list-item-10
$list-item - 10

Inconsistency with variable naming across languages

Back in the day, I used to write underscored_names for variables in PHP, ruby, HTML/CSS, and JavaScript. This was convenient and consistent, but again in order to "fit in" I now use:

  • dash-case in HTML/CSS
  • camelCase in JavaScript
  • underscore_case in PHP and ruby

This doesn't really bother me too much, but I wonder why these became so misaligned, seemingly on purpose. At least with underscores it was possible to maintain consistency:

var featured_product = $('#featured_product'); // instead of
var featuredProduct = $('#featured-product');

The differences create situations where we have to translate strings unnecessarily, along with the potential for bugs.

So I ask: Why did the community almost universally settle on dashes, and are there any reasons that outweigh underscores?

There is a related question from back around the time this started, but I'm of the opinion that it's not (or shouldn't have been) just a matter of taste. I'd like to understand why we all settled on this convention if it really was just a matter of taste.

Community
  • 1
  • 1
Andrew Vit
  • 18,961
  • 6
  • 77
  • 84
  • 14
    Curious why this was closed... were there votes to close it? I'm not soliciting opinions in this question. I gave specific reasons against using dashes, but there must good reasons for them if everyone seemingly agreed on this trend. There are some good answers and good info here. Can I improve the question? – Andrew Vit Sep 27 '11 at 15:04
  • 12
    I'm nominating my question for reopening: all the answers below include "facts, references, or specific expertise"... so I don't see how it was "not constructive". – Andrew Vit Sep 27 '11 at 15:19
  • 14
    I think closing this thread as non constructive was a stupid decision. If there is a style of coding that is preferred because of something other than preference (easier for IDEs to deal with, easier code completion, better integration with tools) I think it would be quite a constructive question/answers/discussion. – Jake Wilson May 15 '12 at 04:34
  • 9
    @AndrewVit: this is a very good question, well-formatted, informative and highlights multiple aspects. +1 for that. Btw., I agree that it was senseless to close this topic as _"not constructive"_. Actually it IS constructive. – Sk8erPeter May 18 '13 at 17:36
  • 3
    I'm truly against close it as non-constructive, does not make sense do that. There's a small but important difference between asking for "Why do you prefer XX" and "Why are XX preferred". The first asks for a opinion, the second is to understand why this convention is so acceptable, even though it have XX drawbacks – Andre Figueiredo Jan 03 '14 at 15:43
  • possible duplicate of [Naming "class" and "id" HTML attributes - dashes vs. underlines](http://stackoverflow.com/questions/1696864/naming-class-and-id-html-attributes-dashes-vs-underlines) – Ciro Santilli OurBigBook.com Jul 06 '14 at 15:16
  • As of 2015, [Bootstrap 4 uses camelCase for ids and dashes for class names](https://github.com/twbs/bootstrap/issues/17417). – Dan Dascalescu Aug 31 '15 at 23:45
  • "Jumping by words or double-clicking on class names is broken by hyphens." > at least the double-cllicking issue can be ruled out in editors like sublime (by modifying settings) – sasha Sep 03 '17 at 22:50

7 Answers7

145

Code completion

Whether dash is interpreted as punctuation or as an opaque identifier depends on the editor of choice, I guess. However, as a personal preference, I favor being able to tab between each word in a CSS file and would find it annoying if they were separated with underscore and there were no stops.

Also, using hyphens allows you to take advantage of the |= attribute selector, which selects any element containing the text, optionally followed by a dash:

span[class|="em"] { font-style: italic; }

This would make the following HTML elements have italic font-style:

<span class="em">I'm italic</span>
<span class="em-strong">I'm italic too</span>

Ambiguity with arithmetic operator

I'd say that access to HTML elements via dot notation in JavaScript is a bug rather than a feature. It's a terrible construct from the early days of terrible JavaScript implementations and isn't really a great practice. For most of the stuff you do with JavaScript these days, you'd want to use CSS Selectors for fetching elements from the DOM anyway, which makes the whole dot notation rather useless. Which one would you prefer?

var firstName = $('#first-name');
var firstName = document.querySelector('#first-name');
var firstName = document.forms[0].first_name;

I find the two first options much more preferable, especially since '#first-name' can be replaced with a JavaScript variable and built dynamically. I also find them more pleasant on the eyes.

The fact that Sass enables arithmetic in its extensions to CSS doesn't really apply to CSS itself, but I do understand (and embrace) the fact that Sass follows the language style of CSS (except for the $ prefix of variables, which of course should have been @). If Sass documents are to look and feel like CSS documents, they need to follow the same style as CSS, which uses dash as a delimiter. In CSS3, arithmetic is limited to the calc function, which goes to show that in CSS itself, this isn't an issue.

Inconsistency with variable naming across languages

All languages, being markup languages, programming languages, styling languages or scripting languages, have their own style. You will find this within sub-languages of language groups like XML, where e.g. XSLT uses lower-case with hyphen delimiters and XML Schema uses camel-casing.

In general, you will find that adopting the style that feels and looks most "native" to the language you're writing in is better than trying to shoe-horn your own style into every different language. Since you can't avoid having to use native libraries and language constructs, your style will be "polluted" by the native style whether you like it or not, so it's pretty much futile to even try.

My advice is to not find a favorite style across languages, but instead make yourself at home within each language and learn to love all of its quirks. One of CSS' quirks is that keywords and identifiers are written in lowercase and separated by hyphens. Personally, I find this very visually appealing and think it fits in with the all-lowercase (although no-hyphen) HTML.

Asbjørn Ulsberg
  • 8,721
  • 3
  • 45
  • 61
  • 5
    "Whether dash is interpreted as punctuation or as an opaque identifier depends on the editor of choice" I don't think this is generally true, though there may be some exceptional editors. Double-clicking on a hyphenated word will only select part of it, not the whole token: this seems to be OS-wide. – Andrew Vit Sep 26 '11 at 21:32
  • 14
    Good point about the `|=` selector, I saw that in the other answer, and it's a fair point. Was the language convention designed around this, or the other way around? (Hyphens as a universal trend seem to be relatively recent, these could have emerged around the same time.) – Andrew Vit Sep 26 '11 at 21:34
  • 1
    @AndrewVit, there are CLI based editors where double-clicking isn't relevant (since there's usually no mouse) and that can be configured to have this kind of behavior. But in general, you're right. The `|=` attribute selector is made specifically for the `lang` attribute, but its use can be extended. I've always used hyphens in my CSS, so I can't speak for the general public, but there's definitely been a convergence towards hyphends from pascal case, camel case and underscores. The `|=` selector and hyphen as delimiter are as far as I can tell unrelated, though. – Asbjørn Ulsberg Sep 27 '11 at 13:28
  • 3
    I don't see dot notation as a bug, it is CSS which shouldn't have used hyphens. Also, what is pleasing to eyes is variable. – vivek Jul 22 '14 at 20:38
  • @vivek, nobody really uses the dot notation in JavaScript anymore. It's always been bad practice, never well supported across browsers (since it's never been part of any standard) and has loads of issues since the naming of `id` attributes is less restrictive than that of JavaScript identifiers. Why shouldn't CSS have used hyphens? Because your eyes are used to reading C-based languages? Try writing XSLT for a few months and you'll get used to hyphens quickly enough. Enforcing one language's naming conventions on another is a practice I find strange and unappealing. – Asbjørn Ulsberg Jan 08 '15 at 21:47
  • I never said using hyphens is not pleasing to my eyes, it doesn't matter to me if something is pleasing or not. It is more because, '-', like '+', '/' & '*', is a basic math operator, that I don't like using it in Identifiers. – vivek Jan 13 '15 at 10:32
  • I favour the third because it resembles a *real* language... Anyway, none of these seem like good defences to using '-' given the points made in the OP... – Deji Jul 27 '15 at 13:52
  • js dot notation is not a bug - it is a feature :D – Kamil Kiełczewski Mar 02 '16 at 18:14
  • You can emulate this: `span[class|="em"] { font-style: italic; } with this:` `span[class^='em'] { font-style: italic; }` – Kamil Kiełczewski Mar 02 '16 at 18:27
  • 3
    @KamilKiełczewski That's useful, but it works slightly differently. – gcampbell Jun 19 '16 at 07:42
77

Perhaps a key reason why the HTML/CSS community aligned itself with dashes instead of underscores is due to historical deficiencies in specs and browser implementations.

From a Mozilla doc published March 2001 @ https://developer.mozilla.org/en-US/docs/Underscores_in_class_and_ID_Names

The CSS1 specification, published in its final form in 1996, did not allow for the use of underscores in class and ID names unless they were "escaped." An escaped underscore would look something like this:

    p.urgent\_note {color: maroon;}

This was not well supported by browsers at the time, however, and the practice has never caught on. CSS2, published in 1998, also forbade the use of underscores in class and ID names. However, errata to the specification published in early 2001 made underscores legal for the first time. This unfortunately complicated an already complex landscape.

I generally like underscores but the backslash just makes it ugly beyond hope, not to mention the scarce support at the time. I can understand why developers avoided it like the plague. Of course, we don't need the backslash nowadays, but the dash-etiquette has already been firmly established.

user193130
  • 8,009
  • 4
  • 36
  • 64
  • 7
    Thanks! I love finding out the 'etymology' of a convention like this. It helps me remember to use the convention since I can associate the language with it. Having the association helps me with priming my subconscious into using the convention as a result. – Ape-inago Nov 05 '14 at 15:43
  • I think this is the best answer thus far. It isn't an opinion; it actually answers the question using historical context. – rokejulianlockhart Jun 06 '23 at 18:56
42

I don't think anyone can answer this definitively, but here are my educated guesses:

  1. Underscores require hitting the Shift key, and are therefore harder to type.

  2. CSS selectors which are part of the official CSS specifications use dashes (such as pseudo-classes like :first-child and pseudo-elements :first-line), not underscores. Same thing for properties, e.g. text-decoration, background-color, etc. Programmers are creatures of habit. It makes sense that they would follow the standard's style if there's no good reason not to.

  3. This one is further out on the ledge, but... Whether it's myth or fact, there is a longstanding idea that Google treats words separated by underscores as a single word, and words separated by dashes as separate words. (Matt Cutts on Underscores vs. Dashes.) For this reason, I know that my preference now for creating page URLs is to use-words-with-dashes, and for me at least, this has bled into my naming conventions for other things, like CSS selectors.

Mason G. Zhwiti
  • 6,444
  • 11
  • 61
  • 97
  • 2
    Good point about the SEO with regard to dashes in URLs and for semantic markup (whether or not this is actually true)... Can you clarify which "CSS selectors which are part of the official CSS specifications use dashes"? – Andrew Vit Sep 26 '11 at 21:24
  • I expanded on point 2 in my answer to give a few examples, though I was thinking more about CSS properties like text-decoration rather than "selectors," so that was somewhat of a typo, although there are a few selectors that do, as noted above. – Mason G. Zhwiti Sep 27 '11 at 03:33
  • 1
    Thanks @albert, that would make a fine answer in its own right... at least for historical context. I didn't know the original spec didn't allow underscores! (But it doesn't make sense why they should be disallowed.) – Andrew Vit Sep 27 '11 at 07:34
  • Thanks @albert, I had that reason in the back of my mind (I was remembering it as a browser compatibility issue of some sort), but couldn't find any documentation to back it up. – Mason G. Zhwiti Sep 27 '11 at 15:15
  • 4
    Point #2 convinced me, especially given properties like background-color, text-decoration, etc. – Big McLargeHuge Feb 15 '13 at 20:16
  • 2
    FYI for the curious, the devedge-temp url referenced in @albert's comment above (http://devedge-temp.mozilla.org/viewsource/2001/css-underscores/) is now at https://developer.mozilla.org/en-US/docs/Underscores_in_class_and_ID_Names – aponzani Aug 20 '13 at 20:51
20

There are many reasons, but one of the most important thing is maintaining consistency.

I think this article explains it comprehensively.

CSS is a hyphen-delimited syntax. By this I mean we write things like font-size, line-height, border-bottom etc.

So:

You just shouldn’t mix syntaxes: it’s inconsistent.

simhumileco
  • 31,877
  • 16
  • 137
  • 115
15

There's been a clear uptick in hyphen-separated, whole-word segments of URLs over recent years. This is encouraged by SEO best practices. Google explicitly "recommend that you use hyphens (-) instead of underscores (_) in your URLs": http://www.google.com/support/webmasters/bin/answer.py?answer=76329.

As noted, different conventions have prevailed at different times in different contexts, but they typically are not a formal part of any protocol or framework.

My hypothesis, then, is that Google's position anchors this pattern within one key context (SEO), and the trend to use this pattern in class, id, and attribute names is simply the herd moving slowly in this general direction.

Faust
  • 15,130
  • 9
  • 54
  • 111
6

I think it's a programmer dependent thing. Someones like to use dashes, others use underscores.
I personally use underscores (_) because I use it in other places too. Such as:
- JavaScript variables (var my_name);
- My controller actions (public function view_detail)
Another reason that I use underscores, is this that in most IDEs two words separated by underscores are considered as 1 word. (and are possible to select with double_click).

Ali Farhoudi
  • 5,350
  • 7
  • 26
  • 44
-2
point of refactoring only btn to bt

case: btn_pink
search btn in word
result btn

case: btn-pink
search btn in word
result btn | btn-pink

case: btn-pink
search btn in regexp
\bbtn\b(?!-) type to hard
result btn
boulder
  • 1
  • 1
  • 1
    Please add some comments to your code to help the users understand your answer. I would suggest you also reading some guidelines, this will help to get your answers more clear, not deleted and get more votes up. https://stackoverflow.com/help/how-to-answer – Davide Casiraghi Feb 09 '21 at 12:00