简体   繁体   中英

Escaping characters in CSS class selectors

I'm trying to implementthis W3 description of character escapes in CSS class selectors.

I'm running into problems with the abc\20 def syntax that puts a space after the escape sequence to ensure def is not misread as part of the character code.

Specifically, trying to put abc\XY def into an HTML class attribute or into a command like jQuery().addClass('abc\\20 def') (the \\ here is part of the JS string literal syntax; the string value itself has one slash) will both give the element two classes, abc\20 and def .

Is this syntax just badly implemented, and I should stick with the six-digit leading zero form? Or does that document only refer to the escape format in CSS code, and the HTML attribute / jQuery argument require some different form of escaping the space character?

Edit : Thank you very much for explaining, everyone!

I now understand that this syntax only applies to CSS code - not the class names themselves as set in HTML attributes or Javascript.

This also means that characters designated as whitespace can't occur in CSS class values, and no kind of escape mechanism allows them to be added. (Specifically, if I understand correctly, the CSS selector .abc\20 def is valid and selects elements with the class abc def , but is meaningless because no element can have this class.)

For my concrete use case, which involves mapping arbitrary values (which can have white space) to valid class names , I need to define my own escape scheme. Replacing whitespace with - or _ (thanks Praveen) is one possibility; if the mapping needs to be one-to-one, replacing them with six-digit Unicode hex values (eg. "abc def" -> "abc\000020def" is a more robust one.

The important thing to keep in mind is that this replacement affects the class name itself - to refer to the class abc\000020def in CSS, the backslash must be escaped again, to form the selector .abc\\000020def .

Short answer: DOM parses whatever selector you pass to it as string. If the (parsed by DOM) result contains spaces or non-breaking-spaces, they will count as class separators.


You shouldn't worry about jQuery, or any other ECMAScript misinterpreting the spaces meant for ending an escape block as a class delimiter.

Simply put, because they are not in charge of this matching . Document Object Model is. The same DOM that interprets the escaped CSS classes. So if an escaped class name works in your stylesheet, it will work as a selector if passed by any JavaScript library.

On one condition: that it gets passed to DOM in a form that it understands. A form that works in CSS .

Now, let's assume that, for semantics reasons, you'd like to use the class 100% on an element. You'll need to escape at least the first and last characters for your selector to work. The ones in the middle may or may not be escaped. Possible selectors, all translating at DOM level to the 100% class name, would be:

  • .\31 00\25
  • .\31 0\30\25
  • .\31\30 0\25
  • .\31\30\30\25
  • .\31 \30 \30 \25

As you already know, there are more escaping CSS methods . However, this applies to all.

When you pass a selector to jQuery or JavaScript it will treat it as a string and pass it to the DOM parser. However, these libraries have their own escaping mechanisms, allowing us to do fancy stuff. So, to allow any of the above selectors to make it to the DOM parser you need to escape the backslashes, so they are not misinterpreted by JavaScript as escape characters and removed from string.

Basically you need to double your backslashes. Any of the following will do:

  • .\\31 00\\25 ,
  • .\\31 0\\30\\25 ,
  • .\\31\\30 0\\25
  • .\\31\\30\\30\\25
  • .\\31 \\30 \\30 \\25

Here's a snippet. Test it out. Add elements with class 0% and you will see they don't get selected. Because the DOM parser will turn any of the above selectors into 100% and match them against the 100% class you have put to the element.

 $('.\\31\\30\\30\\25>div').on('click', function(){ var positions = ['first','second','third']; alert('You clicked the ' + positions[$(this).index()] + ' div.'); })
 .\31 0\30\25 > div{ padding: 20px; }.\31 00\25 > *:first-child { color: red; }.\31\30 0\25 > *:nth-child(2) { color: blue; }.\31\30\30\25 > *:last-child { color: green; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="100%"> <div>first</div> <div>second</div> <div>third</div> </div>


Getting back to your example ( abc\\20 def ) it will parse and behave exactly like abc def . Spaces , when present in the final result of the class name string, will be interpreted as class delimiters . This goes for both \x20 and \xa0 (space and non-breaking-space) and it is the expected behaviour.

As an interesting (trivial) note, if for some evil reason you wanted to make it hard for people to style up your app, you could always add a command type character to a class name. Here's an example:

 $('.space').removeClass('\x73\x70\x61\x63\x65').addClass('\x1a\x73\x70\x61\x63\x65');
 .space { color: red; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="space"> inspect me, i should be red! </div>

You are getting confused between the class name as present in the DOM, and the escaped version required in CSS. The class name is just specified as is:

elt.classList.add('foo:bar')

It is when this is referenced in a CSS file (or other CSS selector context, such as querySelector ) that it must be escaped:

.foo\:bar { color: red; }

The same applies to the case where you choose to use a numeric escape:

elt.classList.add('1234');

.\31 234 { color: red; }

However, no amount of escaping will permit you to have spaces in class names. Spaces are absolutely reserved for delimiting multiple class names on the DOM className attribute.

I think you can use class="abc&amp;#x0020;def" to solve that problem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM