Why Are Dashes Preferred for CSS Selectors/HTML Attributes

Why are dashes preferred for CSS selectors / HTML attributes?

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.

Why is lower-case with dashes the standard for HTML classes?

Just like you mentioned in your own question but I realise that's just my opinion.

Coding-conventions are:

  • guidelines for making code more readable (amount of spaces for identation, naming of variables, ..)
  • in no way a limit in your coding
  • different for every language

In short, it's only a proposed way of coding which you don't need to follow but it's more readable for other people if you do.

If you come across one set of conventions, it means a lot of people agree with that set and adopt it for themselves (with or without some modifications =) )

Some languages restrict conventions a bit (like class names having to start with an uppercase letter, ..), that's why it's different for every language.

Why hyphen (-) separated class names are widely used in CSS

Readability:

ui-helper-reset readable,

uiHelperReset unreadable.

Safe delimiter:

When using attribute selectors like [class^="icon-"], [class*=" icon-"] to specifically and safely target the specific classname styles by prefix, while preventing i.e: .iconography to be matched.

Ease of use:

In every decent code editor, if you use - to separate combined-class-name you can easily highlight a desired portion by double-clicking it like: col-md-3, and replace it (or even document globally) to col-sm-3. On the other hand, if you use underscore _ like class_name_here, if you double-click it you'll end up highlighting the whole class-name like: class_name_here. Such will force you to manually drag-select the desired portion instead.

CSS Naming Convention Methodology

You can adopt a CSS naming concept like:

  • SUIT CSS
  • BEM (Block, Element, Modifier),
  • OOCSS (Object-Oriented CSS)
  • SMACSS (Scalable and Modular Architecture for CSS)
  • Atomic CSS
  • Your Own Concept CSS :)

They all help a team speak "the same language", by adopting a stricter "Naming things" such as:

SUIT CSS

/* Block */
.Chat{}

/* -element (child) */
.Chat-message{}

/* --modifier */
.Chat-message--me{} /* Style my messages differently from other messages */

/* .is-state */
.Chat.is-active{} /* Multiple chats - active state handled by JS */

or

BEM:

/* block */
.chat{}

/* __element (child) */
.chat__message{}

/* --modifier */
.chat__message--me{} /* Style my messages differently from other messages */
.chat--js-active{} /* Multiple chats - active state handled by JS */

If your .chat is part of the page you're viewing, you could use general Block classes like .btn and Modifier .btn--big like <a class="btn btn--big">Post</a>, otherwise if your buttons need a stricter styling specific to your chat application than you'd use .chat__btn and .chat__btn--big classes. Such classnames can also be preprocessed.

SCSS

I.e: by using Sass SCSS, a superset of CSS3 sintax you can do stuff like:

(Example using SUIT CSS)

.Chat {
font: 14px/1.4 sans-serif;
position: relative;
overflow-y: scroll;
width: 300px;
height: 360px;

&-message { // refers to .Chat-message
padding: 16px;
background: #eee;

&--me { // refers to .Chat-message--me
background: #eef; // Style my messages differently from other messages */
text-align: right;
}
}

&.is-active { // refers to .Chat.is-active (JS)
outline: 3px solid lightblue;
}
}

HTML:

<div class="Chat is-active">
<div class="Chat-message">Hi lt;/div>
<div class="Chat-message Chat-message--me">Ciao!<br>How are you? lt;/div>
<div class="Chat-message">Fine thx! Up for a ☕?</div>
</div>

jsFiddle example


Conclusion:

Adopting a stricter naming format among a team is important. Prevents and minimizes dead legacy classes bloating your HTML, helps code re-usability, readability and speeds up your workflow. Additionally, it forces you and your team to think in a much more modular way about your HTML structure - as components or atoms.

Whatever you decide to use is up to you - just, be consistent.

CSS trends with naming class and id with dash underscore?

The double underscore follows the BEM methodology. It is basically a way of naming classes so that later it becomes easy for the user to understand.

The guiding principle behind BEM seems to be "when designing a page, think in terms of reusable widgets". Which is pretty much the standard way you should be writing your semantic HTML.

Learn more about BEM here: BEM methoodology

Is it okay to mix underscores and dashes (hyphens) in CSS ID naming conventions?

Yes, that's no problem. Per the W3C, the top two rules of naming CSS classes are:

  • All CSS syntax is case-insensitive within the ASCII range (i.e.,
    [a-z] and [A-Z] are equivalent), except for parts that are not under
    the control of CSS. For example, the case-sensitivity of values of
    the HTML attributes "id" and "class", of font names, and of URIs lies
    outside the scope of this specification. Note in particular that
    element names are case-insensitive in HTML, but case-sensitive in
    XML.
  • In CSS, identifiers (including element names, classes, and IDs in
    selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646
    characters U+00A0 and higher, plus the hyphen (-) and the underscore
    (_); they cannot start with a digit, two hyphens, or a hyphen
    followed by a digit. Identifiers can also contain escaped characters
    and any ISO 10646 character as a numeric code (see next item). For
    instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26
    W\3F".

Naming class and id HTML attributes - dashes vs. underlines

Use Hyphens to ensure isolation between your HTML and JavaScript.

Why? see below.

Hyphens are valid to use in CSS and HTML but not for JavaScript Objects.

A lot of browsers register HTML Ids as global objects on the window/document object, in big projects, this can become a real pain.

For this reason, I use names with Hyphens this way the HTML ids will never conflict with my JavaScript.

Consider the following:

message.js

message = function(containerObject){
this.htmlObject = containerObject;
};
message.prototype.write = function(text){
this.htmlObject.innerHTML+=text;
};

html

<body>
<span id='message'></span>
</body>
<script>
var objectContainer = {};
if(typeof message == 'undefined'){
var asyncScript = document.createElement('script');
asyncScript.onload = function(){
objectContainer.messageClass = new message(document.getElementById('message'));
objectContainer.messageClass.write('loaded');
}
asyncScript.src = 'message.js';
document.appendChild(asyncScript);
}else{
objectContainer.messageClass = new message(document.getElementById('message'));
objectContainer.messageClass.write('loaded');
}
</script>

If the browser registers HTML ids as global objects the above will fail because the message is not 'undefined' and it will try to create an instance of the HTML object. By making sure an HTML id has a hyphen in the name prevents conflicts like the one below:

message.js

message = function(containerObject){
this.htmlObject = containerObject;
};
message.prototype.write = function(text){
this.htmlObject.innerHTML+=text;
};

html

<body>
<span id='message-text'></span>
</body>
<script>
var objectContainer = {};
if(typeof message == 'undefined'){
var asyncScript = document.createElement('script');
asyncScript.onload = function(){
objectContainer.messageClass = new message(document.getElementById('message-text'));
objectContainer.messageClass.write('loaded');
}
asyncScript.src = 'message.js';
document.appendChild(asyncScript);
}else{
objectContainer.messageClass = new message(document.getElementById('message-text'));
objectContainer.messageClass.write('loaded');
}
</script>

Of course, you could use messageText or message_text but this doesn't solve the problem and you could run into the same issue later where you would accidentally access an HTML Object instead of a JavaScript one

One remark, you can still access the HTML objects through the (for example) window object by using window['message-text'];

Why should I use data- in my attributes or dashes in my tags?

The data-* attributes have two advantages:

  1. It is a convention meaning other programmers will understand quickly that it is a custom attribute.
  2. You get a DOM Javascript API for free: HTMLElement.dataset. If you use jQuery, it leverages this to populates the keys and values you find with .data().

The reason for the - in custom element names is for two basic reasons:

  1. It is a quick way for the HTML parser to know it is a custom element instead of a standard element.
  2. You don't run into the issue of a new standard element being added with the same name which would cause conflict if you register a custom Javascript prototype for the DOM element.

Should you use your own custom element name? Right now it is so new that don't expect it to be fully supported. Let's say it does work. You have to balance the issue of the extra complexity with the benefit. If you can get away with a classname, then use a classname. But if you need a whole new element with a custom Javascript DOM prototype for the element, then you may have a valid usage of it.

Javascript and CSS, using dashes

Having dashes and underscores in the ID (or class name if you select by that) that won't have any negative effect, it's safe to use them. You just can't do something like:

var some-element = document.getElementByID('css-dash-name');

The above example is going to error out because there is a dash in the variable you're assigning the element to.

The following would be fine though since the variable doesn't contain a dash:

var someElement = document.getElementByID('css-dash-name');

That naming limitation only exists for the javascript variables themselves.

Why are dashes preferred for CSS selectors / HTML attributes?

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.



Related Topics



Leave a reply



Submit