DEV Community

Discussion on: CSS needs a name prefix selector

Collapse
 
besworks profile image
Besworks • Edited

Having a CSS native way to do this would be fantastic. If there is not a proposal for this feature there should be. You can accomplish something equivalent by adding this magic little js snippet before ANY other DOM element is loaded. That is to say, OUTSIDE your <html> element, directly below the <!DOCTYPE html> declaration and before any other element.

<!DOCTYPE html>
<script>
  const style = document.createElement('style');
  document.head.appendChild(style);

  const observer = new MutationObserver((mutations) => {
    for (const mutation of mutations) {
      for (const node of mutation.addedNodes) {
        if (node.nodeType === 1 && node.tagName?.startsWith('CUSTOM-')) {
          style.textContent += `${node.tagName}:not(:defined) { display: none; }`;
        }
      }
    }
  });

  observer.observe(document, {
    childList: true,
    subtree: true
  });
</script>
<title>Custom Elements Partial Name Selector</title>
<custom-element-1> test </custom-element-1>
<custom-element-2> test </custom-element-2>
<script>
  customElements.define(
    'custom-element-1', class extends HTMLElement {}
  );
</script>
Enter fullscreen mode Exit fullscreen mode

This works due to this note in HTML5 - 8.2.5 Tree Construction :

The HTML parser generates implied tokens when parsing elements if they are missing but required by the tree structure. When the parser reaches a script element, even before the tag is encountered, it switches to the "in head" insertion mode. This allows scripts to execute during the "initial" and "before html" insertion modes, which is why scripts can run and manipulate the DOM even before explicit structural elements are parsed.

You can load this from an external file, just make sure it's cached for best performance and do not make it async or type="module" or it will not work.

<!DOCTYPE html>
<script src="./not-defined.js"></script>
<title> External Script Example </title>
<custom-element-1> test </custom-element-1>
Enter fullscreen mode Exit fullscreen mode