Can CSS Identifiers Begin with Two Hyphens

Can CSS identifiers begin with two hyphens?

Standard

Effectively, a change in CSS Syntax Module now allows identifiers to start with two hyphens:

4.3.9. Check if three code points would start an identifier

Look at the first code point:

  • U+002D HYPHEN-MINUS

    If the second code point is a name-start code point or a U+002D HYPHEN-MINUS, or the second and third code points are a valid escape,
    return true. Otherwise, return false.

This change appeared in the 21 Mar 2014 Editor's Draft (changelog), and is still not present in the current Candidate Recomendation, which is the 20 Feb 2014 CR.

It's also described in Changes:

11.1. Changes from the 20 February 2014 Candidate Recommendation

  • Change the definition of ident-like tokens to allow "--" to start an ident.

Reason

In www-style, the ...let's change the syntax thread proposed to change the syntax of CSS Variables:

  1. Tab Atkins Jr. proposed changing the syntax of Custom Properties to "any ident starting with/containing an underscore".
  2. Chris Eppstein disagreed because _property is a common IE6 hack.
  3. Brian Kardell proposed --.
  4. Zack Weinberg warned:

    Unfortunately, "--" would require a change to Syntax. IDENT isn't
    allowed to start with two dashes in a row.

  5. There was a long discussion of what should be done.

  6. Tab Atkins Jr. informed they resolved to use a -- prefix to indicate custom properties and other custom things.

So the following day he commited the change of CSS Syntax to github (he is an editor of the spec).

Implementations

Firefox

Firefox allows identifiers to start with -- since Nightly 31 2014-04-03 (pushlog). The behavior was changed in bug 985838:

Bug 985838 - change var- prefix of CSS Variables to --

Recently decided changes to the CSS Variables spec:

  • the prefix of the custom property change from var- to --
  • inside the var() you use the full custom property name (i.e. with the -- prefix)
  • a custom property consisting only of the prefix, --, is allowed
  • idents in the CSS parser now allow things like -- and --0

The change landed on Firefox 31.0. Since then, [id=--] works.

However, #-- still does not work even on latest Nightly 41.
I filed bug 1175192 in order to fix that.

Chrome

Chromium built a new CSS parser:

We now allow idents to start with --

It was shipped in this commit, which was part of this commitlist, which was rolled in this commit. So it was finally implemented in build 44.0.2370.0 325166 (pushlog since 325152).

Since then, Chromium allows both [id=--] and #--.

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".

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.

Allowed characters for CSS identifiers

The charset doesn't matter. The allowed characters matters more. Check the CSS specification. Here's a cite of relevance:

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".

Update: As to the regex question, you can find the grammar here:

ident      -?{nmstart}{nmchar}*

Which contains of the parts:

nmstart    [_a-z]|{nonascii}|{escape}
nmchar [_a-z0-9-]|{nonascii}|{escape}
nonascii [\240-\377]
escape {unicode}|\\[^\r\n\f0-9a-f]
unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])?
h [0-9a-f]

This can be translated to a Java regex as follows (I only added parentheses to parts containing the OR and escaped the backslashes):

String h = "[0-9a-f]";
String unicode = "\\\\{h}{1,6}(\\r\\n|[ \\t\\r\\n\\f])?".replace("{h}", h);
String escape = "({unicode}|\\\\[^\\r\\n\\f0-9a-f])".replace("{unicode}", unicode);
String nonascii = "[\\240-\\377]";
String nmchar = "([_a-z0-9-]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String nmstart = "([_a-z]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String ident = "-?{nmstart}{nmchar}*".replace("{nmstart}", nmstart).replace("{nmchar}", nmchar);

System.out.println(ident); // The full regex.

Update 2: oh, you're more a PHP'er, well I think you can figure how/where to do str_replace?

Which characters are valid in CSS class names/selectors?

You can check directly at the CSS grammar.

Basically1, a name must begin with an underscore (_), a hyphen (-), or a letter(az), followed by any number of hyphens, underscores, letters, or numbers. There is a catch: if the first character is a hyphen, the second character must2 be a letter or underscore, and the name must be at least 2 characters long.

-?[_a-zA-Z]+[_a-zA-Z0-9-]*

In short, the previous rule translates to the following, extracted from the W3C spec.:

In CSS, identifiers (including element names, classes, and IDs in
selectors) can contain only the characters [a-z0-9] and ISO 10646
characters U+00A0 and higher, plus the hyphen (-) and the underscore
(_); they cannot start with a digit, 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".

Identifiers beginning with a hyphen or underscore are typically reserved for browser-specific extensions, as in -moz-opacity.

1 It's all made a bit more complicated by the inclusion of escaped unicode characters (that no one really uses).

2 Note that, according to the grammar I linked, a rule starting with TWO hyphens, e.g. --indent1, is invalid. However, I'm pretty sure I've seen this in practice.

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

HTML ID with numerical value not recognized by CSS

Although it's allowed to set a class or id to begin with a digit in HTML5, but it's not allowed in CSS, see the spec:

HTML5: 3.2.5.1 The id attribute

... There are no other restrictions on what form an ID can take; in particular, IDs can consist of just digits, start with a digit, start with an underscore, consist of just punctuation, etc. ...


CSS: 4.1.3 Characters and case

... 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 ...

i.e.

<div id="1"> is valid HTML, but you cannot target it with #1 {...} in CSS.

However, you can use [id="1"] {...} or escape it #\31 {...}

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.

Why in CSS, #1 (as id of a div element) styling doesn't work?

Its CSS's rule that you can't use Number as starting character or a class or id. That is why it wont work. You at least have to put 1 alphabet before the number!

This is what said in w3c -

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”.

http://www.w3.org/TR/CSS21/syndata.html#characters



Related Topics



Leave a reply



Submit