Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange backslash and behavior in CSS

Tags:

css

I've come across a piece of CSS code like this:

p {
  color: white;
}
\p {
  background: green;
}
\* {
  background: #bcc;
}
body \2a {
  background: red;
}
.recover {
  background: #6ea;
  color: black;
}
div {
  border: 2px solid blue;
}
ul,
li,
a {
  background: none;
}
<p>This should have a green background</p>
<div>This should have no background color</div>
<p class="recover">CSS has recovered</p>

In Firefox and Internet Explorer 10 the result is as described in the HTML. But in Chrome it's totally different.

What is the usage of the backslashes in this example?

like image 654
fabregaszy Avatar asked Nov 02 '22 12:11

fabregaszy


1 Answers

The slashes in this instance are used to escape characters.

body \2a is effectively body * as \2a is the encoded version of *. W3C states that (bold added for clarity):

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

Characters and case (https://www.w3.org/TR/CSS2/syndata.html#characters)

The following table shows that 2a is the hex code for *:

Unicode code point   character   UTF-8 (hex.)    name
U+002A               *           2a              ASTERISK

UTF-8 encoding table and Unicode characters (http://www.utf8-chartable.de/)

\* and \p is another method of escaping characters as mentioned by W3C (bold added for clarity):

Second, it cancels the meaning of special CSS characters. Any character (except a hexadecimal digit, linefeed, carriage return, or form feed) can be escaped with a backslash to remove its special meaning. For example, "\"" is a string consisting of one double quote. Style sheet preprocessors must not remove these backslashes from a style sheet since that would change the style sheet's meaning.

Characters and case (https://www.w3.org/TR/CSS2/syndata.html#characters)

p is not a hexadecimal digit (they are the numbers 0-9 and the letters A-F) so it treats \p as a standard rule. If the rule were \a it would be ignored as a is a hexadecimal digit while \s would be honoured as it is not (see \a and \s in the snippet below).

Firefox accepts escaped characters in class identifiers (see .B\26 W\3F in the snippet below), but seems to ignore it as a universal selector (*) which is why the styles are not being applied. Both Chrome and Firefox ignore escaped adjacent selectors (+).

This is why in Chrome it is causing:

  • The background-colour of <p>This should have a green background</p> to be red as body * has equal specificity to p but is placed after it in the stylesheet
  • The background-colour of <div>This should have no background color</div> to be red as it matches the rule and there are no others to override the background-colour of this element
  • The background-colour of html, body etc to be #bcc as the \* rule is being matched

Difficult to say which is the correct behaviour, it would simply appear that the spec has been interpreted in slightly different ways.

As to why these rules are used, the only feasible explanation would be that the author is trying to target specific browsers with certain styles.

p {
  color: white;
}
\p {
  background: green;
}
\* {
  background: #bcc;
}
body \2a {
  background: red;
}
.recover {
  background: #6ea;
  color: black;
}
.recover:after {
  content: '\2a';
  display: block;
}
div {
  border: 2px solid blue;
}
.B\26 W\3F {
  background: black;
  color: white;
}
.B\26 W\3F \2b div {
  background: purple;
  color: white;
}
\a {
  border: 2px solid blue;
}
\s {
  border: 2px solid blue;
}
<p>This should have a green background</p>
<div>This should have no background color</div>
<p class="recover">CSS has recovered</p>
<p class="B&W?">Encoded test</p>
<div>Encoded adjacent test</div>
<a href="#">Hexadecimal digit</a>
<s>Non hexadecimal digit</s>
like image 52
Hidden Hobbes Avatar answered Dec 15 '22 04:12

Hidden Hobbes