Escaping your CSS selectors in the easiest way possible

When working a lot on dynamic Web Component apps I have often stumbled on cases where the element properties will be defined by the end-users. To prevent errors when selecting these elements they need to be properly escaped to work with any character.

At first, I had the approach of filtering out forbidden characters for these properties (like .replace(/[^a-z\d-]/g, '')) but this will always increase the risk for collisions where two values that were inserted differently for the user gets converted to the same string (my id and my.id might both be converted to myid).

It's easy to start thinking about different RegExp patterns to escape all the # and . characters, but there is a much simpler and better way.

CSS.escape() to the rescue:

function setValueById(id, value) {
  const element = document.querySelector(`#${CSS.escape(id)}`);
  if (element) {
      element.value = value;
  }
}

setValueById('v-3.0.5', 'lorem ipsum');

In the example above instead of the selector becoming #v-3.0.5 that would select an element with the id v-3, and then require it to have both the class 0 and 5 will escape the selector to become v-3\\.0\\.5 that then works well for selecting an element like <div id="v-3.0.5"></div>.

Although HTML5 has been around for many years now there are still places where my mind still is stuck in the now ancient XHTML patterns, one being that ids basically should only consist of a-z and -. Since HTML5 any UTF-8 character is valid, and therefore CSS.escape() becomes such a useful tool.

For a more in-depth explanation see MDN CSS.escape() documentation.

That is all for this time!