logoalt Hacker News

You can make up HTML tags

254 pointsby todsacerdotitoday at 2:47 AM99 commentsview on HN

Comments

dannyetoday at 8:46 AM

<tag-name> are NOT unrecognized tags!

I blogged about this: https://dashed-html.github.io

◄ <tagname> = always an HTMLUnknownElement until the WHATWG adds it as new Element.

◄ <tag-name> = (No JS!) UNDEFINED Custom Element, valid HTMLElement, great for layout and styling

◄ Upgraded with the JavaScript Custom Elements API it becomes a DEFINED Custom Element

---

► This is standard behaviour in all browsers. Chrome (2016) Safari (2017) FireFox (2018) Edge (2020)

► The W3C HTML Validator accepts all <tag-name> Custom Elements with a dash as HTMLElement. It does not accept <tagname> (no dash), those are HTMLUnknownElement

► The UA - UserAgent StyleSheet (Browsers default stylesheet) defines CSS [hidden] { display:none }. But Custom Elements do not inherit the default stylesheet; so you have to add that behaviour yourself in your stylesheet.

► <DIV> is display:block only in the UA StyleSheet You have to set the display property on these Custom Elements yourself (You will forget this 20 times, then you never make the mistake again)

► The CSS :defined pseudo selector targets standard HTML tags and JavaScript defined Custom Elements

► Thus the CSS :not(:defined) pseudo selector targets the UNDEFINED Custom Elements; they are still valid HTMLElement, CSS applies like any element

► DSD - Declarative ShadowDOM: <template shadowrootmode="open"> creates the same undefined Custom Elements with a shadowDOM

show 1 reply
chrismorgantoday at 3:40 AM

  <div class=article>
  <div class=article-header>
  <div class=article-quote>
  <div class=quote-body>
  ... a bunch more HTML ...
  </div>
  </div>
  </div>
  </div>
Just one quibble over this specific example (not the broader concept, which is sound): it probably didn’t have to be div soup to begin with. Something like this may have been more reasonable:

  <article>
  <header>
  <blockquote>
  <p class=quote-body>
  ... a bunch more HTML ...
  </p>
  </blockquote>
  </header>
  </article>
show 1 reply
verisimilidudetoday at 5:21 AM

I've been doing this for about three or four years. Clever idea, tricky in practice. I don't think I'd recommend this approach broadly. But it works for me.

It's definitely possible to take it too far. When most tags in your HTML are custom elements, it creates new readability problems. You can't immediately guess what's inline, what's block, etc. And it's just a lot of overhead for new people to learn.

I've arrived at a more balanced approach. It goes something like this:

If there's a native tag, like <header> or <article>, always use that first.

If it's a component-like thing, like an <x-card> or <x-hero>, then go ahead and use the custom tag. Even if it's CSS only, without JS.

If the component-like thing has sub-components, declare the pieces using slot attributes. There will be a great temptation to use additional custom tags for this, like <x-hero-blurb> inside <x-hero>. In my experience, a <div slot="hero-blurb"> is a lot more readable. The nice thing about this pattern is that you can put slot attributes on any tag, custom or otherwise. And yes, I abuse the slot attribute even when I'm only using CSS, without JS.

Why bother with all of this? I like to limit my classes to alteration, customization. When I see a <div slot="card-content" class="extra-padding-for-xyz">, it's easy to see where it belongs and what makes it unique.

Some of you will likely barf. I accept it. But this has worked well for me.

show 1 reply
tannhaeusertoday at 10:27 AM

Worth noting you can't define special parsing rules using custom elements, such as for inferring omitted tags like is done for predefined elements all the time. The behavior of parsing HTML fragments with customized standard elements using the browser API is basically underspecified since it lacks a context element which however is needed for inferring required omitted elements such as <head> and <body>, or <html> itself. What about custom elements appearing as child content of other custom elements?

For merely defining custom elements you need JS anyway, so these aren't a technique intended for text authors. Yet as another way to organize code in webapps, custom elements are competing with JS which already has multiple module and namespace and OO import features that are much more flexible.

So as usual, random people on github (aka WHAT working group individuals aka Google shills) reinventing SGML, poorly. Because why not? The end goal always has been to make ad blocking an infeasible arms race and gather "telemetry."

ok123456today at 3:12 AM

By default, they will behave like spans.

You can customize it using the Custom Element API: https://developer.mozilla.org/en-US/docs/Web/API/Web_compone...

show 2 replies
tomberttoday at 4:41 AM

Many years ago, I decided to reinvent the `blink` tag, because the monsters who make browsers removed support for it.

I didn't know you could just make up tags, but I figured I'd give it a shot, and with a bit of jquery glue and playing with visibility settings, I was able to fix browsers and bring back the glorious blinking. I was surprised you could just do that; I would have assumed that the types of tags are final.

I thought about open sourcing it, but it was seriously like ten lines of code and I suspect that there are dozens of things that did the same thing I did.

show 4 replies
aaviator42today at 3:22 AM

I used this to implement <yes-script>, the opposite of <noscript>, to be able to designate sections of a page to be hidden if JS was disabled. You can of course do the same thing with classes, but custom tags are fun.

https://github.com/aaviator42/yes-script

show 1 reply
firefoxdtoday at 7:29 AM

In the olden days, internet explorer couldn't support html5 tags. I found a snippet of code from my 2010 library [0] that I used to use to remedy the problem. You see if you created the tags via JavaScript, IE would somehow recognize them. You could discard them right after. Here was my script:

    (function(d) {
        'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.replace(/\b\w+/g,function (a){
            d.createElement(a);});
    })(document);
It didn't take long before I realized I could just add any random tag, add it to my shim, and render it on any browser.

[0]: https://idiallo.com/blog/revisiting-my-old-javascript

flexagoontoday at 3:39 AM

> <main-article>

> <article-header>

> <article-quote>

> <quote-body>

Not the best example, because in this case, you could just use real HTML tags instead

  <article>
  <header>
  <blockquote>
  <p>
hecanjogtoday at 3:11 AM

You sure can! They all have inline defaults like `<span>` so set some CSS baseline on them as needed, but this is like the best kept secret of HTML or something? Unknown tags will become `HTMLUnknownElement` and behave like a span.

Edit: the reason for avoiding this in the past was name-spacing. But the standard says you can use a hyphen and then you're OK, native elements won't ever use a `-`.

Edit 2: also it's great because it works fine with CSS selectors too. Write stuff like `<image-container>` in plain HTML docs and it's fine.

Edit 3: but also `<albums>` tags and etc which won't be adopted into the HTML standard soon work too if they don't conflict with element names, and the rare case that they might be adopted in the future as an element name can be resolved with a simple text search/replace.

Edit 4: This all really has little to do with javascript, but you can use `querySelector` and `querySelectorAll` with any of these made up names the same as any native name too.

It's very nice to write. I used and liked vue for a little while when it was needed(?) but modern HTML fills that gap.

show 1 reply
rassotoday at 5:27 AM

This is how you can set default styles for all your custom elements:

    :where(:not(:defined)) {
         display: block;
    }
ianbutlertoday at 3:23 AM

https://lit.dev/

That's the premise behind Lit (using the custom elements api)! I've been using it to build out a project recently and it's quite good, simpler to reason about than the current state of React imo.

It started at google and now is part of OpenJS.

show 1 reply
GuB-42today at 9:57 AM

You can, but maybe you shouldn't.

If, for some reason the CSS doesn't load, your site may break completely instead of degrading gracefully. Maybe it will mess with people who have an unusual browser configuration too. It may look nice on your side, but on the user side, I only see disadvantages. It may look like it saves a few bytes, but with compression, it may not.

crazygringotoday at 4:27 AM

But there's no real reason to, and it just adds confusion around which elements are semantic -- bringing formatting, functionality, meaning to screen readers and search engines, etc. -- vs which are custom and therefore carry no semantic meaning.

If there's no native semantic tag that fits my purposes, I'd much rather stick to a div or span as appropriate, and identify it with one (or more) classes. That's what classes are for, and always have been for.

Support for custom HTML elements seems more appropriate for things like polyfills for actual official elements, or possibly more complicated things like UX widgets that really make sense conceptually as an interactive object, not just CSS formatting.

Using custom element names as a general practice to replace CSS classes for regular formatting just feels like it creates confusion rather than creating clarity.

show 3 replies
veqqtoday at 6:46 AM

That's how https://janetdocs.org/ does syntax highlighting:

``` <pre><code class="janet">(<special>defn</special> <symb>bench</symb> <str>`Feed bench a wrapped func and int, receive int for time in ns`</str> [<symb>thunk</symb> <symb>times</symb>] (<special>def</special> <symb>start</symb> (<built-in>os&#x2F;clock</built-in> <keyword>:cputime</keyword> <keyword>:tuple</keyword>)) ```

show 1 reply
matt7340today at 5:16 AM

This is what Angular does, where an Angular component is typically rendered as a custom tag. I find it to be one of the (very) few nice things about Angular, as it can be helpful to track down components in a large codebase. I haven’t used React for many years, but makes me wonder if custom tags as a convention would be similarly useful.

hollowturtletoday at 8:34 AM

> If you include hyphens in the name, you can guarantee that your tag won’t appear in any future versions of HTML.

Which future version? Is there something I'm missing? I'd like to have html6 that has feature parity with native, but I'm afraid we got html5 and just stopped there. And if there will be an html6 why can't we just state "use version 5 in this document" so there won't be any name clashing between supported and custom tags?

show 2 replies
flanbiscuittoday at 7:35 AM

I learned this back when HTML5 was brand new around 15-ish years ago. If you wanted to use the new tags like <article>, the only “polyfill” needed was some css styles. You can see it in the early versions of the HTML5 Boilerplate:

https://github.com/h5bp/html5-boilerplate/blob/v0.9/css/styl...

I realized that I could just make up tags and style them and it was work.

benruttertoday at 6:50 AM

This is cool! I was actually wondering about how to make this work recently and obviously did a bad job of researching it because I didn't realise it already existed[0].

One place I'd love to see this is in a classless html framework. My experience is you always wind up wanting something like cards, and then either writing classes, or having a slightly magic "use these elements in this order" incantation[1].

It would be great to have a minimal framework that peppers in a couple elements of the kind <card>, <accordian> etc.

[0] I did ask an LLM at one stage too, and it also didn't mention this behaviour exists.

[1] pico css does this.for.example for cards/accordians

kcrwfrd_today at 6:07 AM

I find this fun and whimsical, but surely it’s an accessibility nightmare.

show 3 replies
mgtoday at 7:32 AM

My problem with custom tags is that they require a hyphen, and that makes it impossible to have consistency between tag names and variable names.

With classes, I can do:

    carList = document.querySelector('.carList')
With custom tags, that is not possible because variable names cannot have hyphens in them.
donatjtoday at 6:25 AM

I was there like fifteen - twenty years ago before the hyphen standard and shadow dom and all that when JS libraries briefly leaned into just making up their own elements. I think everyone collectively agreed that it was a bad idea and it fell out of popularity.

If I were going to use them, I'd be inclined to vendor them just to prevent any sort of collision proactively

    <donatj-fancy-element>
        <donatj-input />
    </donatj-fancy-element>
macintuxtoday at 3:08 AM

Huh. That led me to wonder whether anyone has created CSS for DocBook, and it appears it exists.

http://www.badgers-in-foil.co.uk/projects/docbook-css/

callctoday at 3:46 AM

Wow, this is great, unlocks lots of freedom. I was under the impression that this was not possible, maybe through web components or <slot>.

As a side note, I’ve been going through all the HTML elements slowly to learn the fundamentals, and it turns out that lots of elements are just a <div> or <span>, with different default styles and default ARIA things.

And a <div> is just a <span> with display block…

This and TFA both help me to realize HTML is pretty darn simple.

show 2 replies
gkobergertoday at 3:13 AM

I probably wouldn't do this for a lot of reasons.

That being said, if you read through that post and were intrigued, you might also like custom web components: https://web.dev/articles/custom-elements-v1

It's a simple way to add more to your "made up" HTML tags. So you could have a tag called <my-code>, for example, that automatically has a copy button and syntax highlights the code.

cheeauntoday at 5:00 AM

Many years ago, IE requires `document.createElement`.

HTML5 Shiv was needed, with added history https://www.paulirish.com/2011/the-history-of-the-html5-shiv... (2011)

ycombireddtoday at 3:31 AM

As someone who writes html only rarely (I'm more of a "backend" guy, and even use that term loosely.. most of my webdev experience dates back to the CGI days and often the html was spat out by Perl scripts) and usually in vim, I am pleased to know there is an in-built solution outside of me properly indenting or manually counting divs. Thanks for enlightening me.

show 1 reply
singpolyma3today at 4:12 AM

You can but you never ever should. Do not do this. Use the `class` attribute to provide extra context about the kind of data your tag represents, that is what it is for.

show 2 replies
superkuhtoday at 3:31 AM

https://blog.jim-nielsen.com/2023/html-web-components/ - Jim Nielsen has a series of posts on how to use made up HTML tags in a way that doesn't just fail to nothing when the javascript defining the custom-element doesn't get successfully executed.

why-o-whytoday at 5:54 AM

Isn't this the basis for every web framework? E.g., Vue Templates?

show 1 reply
zkmontoday at 6:03 AM

That is ... XML without schema but with CSS support. Cool.

system2today at 9:17 AM

I will refuse this idea until it is widely known, accepted, and used by everyone. Div with class is easier to inspect and modify with pseudo. I wonder what would happen with JS getting the element with this, too.

orliesaurustoday at 4:06 AM

If this works, then the point of having standards, is just for screen readers??

evikstoday at 7:35 AM

> Good luck trying to insert something inside of “article-heading” but after “article-quote” on the first try.

You don't need much, but an editor - collapse the sections to get the view as small as in the blog snippet, and then you'll have both opening and closing of the tag you're in highlighted, so you won't miss and won't need any luck

nektrotoday at 3:52 AM

the comments here informing us they default to behaving like <span> instead of like <div> is the biggest disappointment of my day so far

show 2 replies
cubefoxtoday at 7:51 AM

I was forced to use this years ago because there is only a :nth-of-type selector, but no :nth-of-class. So whenever you need nth-of-class, switch to made-up tags and use nth-of-type. (A tag is a type.)

rascultoday at 5:53 AM

> Good luck trying to insert something inside of “article-heading” but after “article-quote” on the first try.

Indentation can help.

sitzkriegtoday at 5:49 AM

i'm very curious how screen readers would handle this. what a terrible idea

show 1 reply
coreyzzptoday at 4:21 AM

[dead]

shevy-javatoday at 4:46 AM

Hmmmm.

On the one hand I kind of want to use any random tag and have it work.

On the other hand ...

    <div class=main-article> # or <div class="main-article">

    versus

    <main-article>
I am not 100% sure, but I think I kind of prefer the div tag.

I understand that it is not the same semantically, but I am using div tags and p tags a LOT. I avoid the new HTML tags for more semantic meaning as this adds cognitive load to my brain. I'd rather confine myself to div and p tags though - it is just easier. And I use proper ids to infer additional information; it is not the same, but I kind of want to keep my HTML simple too. So I don't want to add 500 new custom HTML tags really. Even though I think having this as a FEATURE, can be useful.

show 2 replies