Search code examples
htmlcsscustom-elementhtmlelements

Can I use my own optionally namespaced HTML tags if I'm setting the CSS for each one?


I'd like to my own HTML tags but I don't want new tags that might use the same name to cause them to break in the future.

Is this a good idea? Could I use a namespace to avoid conflicts?


Example:

HTML :

<b:HGroup>
    <span>item 1</span><span>item 2</span><span>item 3</span>
</b:HGroup>

CSS:

@namespace b "library://ns.example.com/framework/1";

b|HGroup {
   display:inline-block;
   vertical-align: middle;
}

I read a related question and it suggests DTD. I'd rather not create a DTD but if it's necessary, then I'd like to define it inline. Also, I'd like it to be run as HTML5, not XHTML.


Note:

I do NOT want to use div plus a class.

As far as I understand it, it looks like custom elements I've written will not be overwritten by future elements of the same name if I explicitly register my custom element. Here is a quote from the W3:

Because element registration can occur at any time, a non-custom element could be created that might in the future become a custom element after an appropriate definition is registered. Such elements are called undefined potentially-custom elements. If such a definition is ever registered, the element will be upgraded, becoming a custom element.


I've included a full page prototype based on the answers and I can't get it to attach any CSS to any element with a namespace. I've included some JS I found on one of the links but commented out part of it that was giving me errors. My main concern is getting elements with namespaces to be styled by the CSS with namespaces. From how I understand it that should work without JS.

<!DOCTYPE html>
<html xmlns:xhtml="http://www.w3.org/1999/xhtml"
  xmlns:s="http://www.w3.org/2002/spark"
  xmlns:space="http://www.w3.org/2002/space"
  xmlns:spaced="http://www.w3.org/2002/spaced">
<head>

<script>
  "use strict";
 
  const inDocument = document.querySelector("example-element");
  const outOfDocument = document.createElement("example-element");
  // Before the element definition, both are HTMLElement:
  //console.assert(inDocument instanceof HTMLElement);
  //console.assert(outOfDocument instanceof HTMLElement);

  //class ExampleElement extends HTMLElement {};
  //customElements.define("example-element", HTMLElement);
  
  //class ExampleElement3 extends HTMLElement {}
  //customElements.define("element3", ExampleElement3);

  //document.body.appendChild(outOfDocument);
  
</script>
<style>

@namespace s url(http://www.w3.org/2000/spark);
@namespace space url(http://www.example.com/2000/spark-space);
@namespace spaced "http://www.example.com/2002/spark-spaced";

example-element {
    color: red;
    display:block;
}
element2 {
    color:green;
    font-weight:bold;
}
s|element3 {
    color:yellow;
}
space-element {
    color:yellow;
}
space|space-element {
    display:block;
    color:yellow;
}
spaced|spaced-element {
    display:block;
    color:yellow;
}
</style>
</head>

    <body>
        <example-element>example-element</example-element>
        <element2>element 2</element2>
        <space-element>space element</space-element>
        <s:element3>s namespace element 3</s:element3>
        <space:space-element>space namespace el</space:space-element>
        <spaced:spaced-element>spaced namespace el</spaced:spaced-element>
    </body>

</html>

Solution

  • You have a well researched question here. In doing so, you've eliminated all of the "valid" solutions.

    You can definitely do what you have proposed, which (harmlessly*) breaks the standards. To be future proof, all HTML standards allow for unknown elements, instructing browsers to ignore them (essentially, they all become <span> elements) since there's no indication of what to do with them, though CSS can indeed affect them. This will work in ALL browsers, even Mosaic and the original IE (though CSS won't work in such ancient browsers).

    As you already noted, the "proper" way to do this would be to define your own Document Type Definition (DTD) that can then be included at the top of your ~HTML document with the <!DOCTYPE> tag. This is probably overkill, but it is technically the right approach.

    Another solution (that you've also eliminated) would be to use <span class="HGroup"> for inline elements and <div class="HGroup"> for block elements since these elements don't actually do anything by default.

    A variant of that solution is to override the action of some otherwise useless tag and disable its standard properties in CSS, <s> for example:

    s {
      text-decoration: none; /* remove line-through */
      display: inline-block;
      vertical-align: middle;
    }
    

    (* The "harm" you can run into with custom element names is that if you don't specify a DTD (your own or else an existing one with an exact version), a future version of the HTML standard could theoretically define some undesired property for your custom element.)