← Back to context

Comment by jakelazaroff

16 hours ago

Using custom elements as the article suggests doesn't require JavaScript, so they are "pure" HTML and CSS (though whether they count as "web components" is up to you). More to the point, all of the technologies that the term "web components" includes — custom elements, <template> tags, shadow DOM — can be used without JavaScript.

<div> and <span> are semantically neutral, so I'm not sure what SEO and accessibility challenges custom elements would introduce?

My point is that defining a complex behavior for a custom tag is not possible without js. For example, you can't define a reusable 'host-element' tag and expect some additional elements (or some behavior) to automatically appear inside it each time your html includes or you create <host-element> ... </host-element>. I mean you can use something like <host-element> (html5 allows that), but it will just be an inline element, almost like <span>, but without semantics. It's not a full web component.

> "shadow DOM — can be used without JavaScript" Yes, shadow DOM can be used without JS, but I was talking about web components.

> "I'm not sure what SEO and accessibility challenges custom elements would introduce?" If you replace standard elements (such as 'p', 'a', 'button', etc) with custom ones it can hurt SEO and accessibility. There are very few reasons to use custom element names and attributes if they are not full web components.

What's the point of using selector 'link-button[size="large"] a {...}' when you could do the same with '.link-button.large a {...}'?

  • Right, but the article isn't talking about defining complex behavior; it's talking about using custom element and attribute names as hooks for CSS. I don't think it's suggesting they be used in place of semantically meaningful elements like <p> or <button>, either; it's saying that you can use them instead of class names or data attributes.

  • > My point is that defining a complex behavior for a custom tag is not possible without js.

    Not necessarily. CSS alone can allow for a lot of useful complex behaviour. You can customise how something renders (or not) or is interactable based on parent elements, sibling elements, css variables, or other state.

    > For example, you can't define a reusable 'host-element' tag and expect some additional elements (or some behavior) to automatically appear inside it each time your html includes or you create <host-element> ... </host-element>.

    Actually you can, using <template> and <slot> elements. No JS required.

    > What's the point of using selector 'link-button[size="large"] a {...}' when you could do the same with '.link-button.large a {...}'?

    This is really two questions:

    1. What's the point of using <link-button> instead of a link-button class?

    2. What's the point of using a size="large" attribute instead of a "large" class?

    To answer 1:

    Classes end up being misused compared to custom elements. When you make a custom element (in this example "<link-button>"), you're explicitly saying this is a <link-button>. It is not a <blockquote class="link-button">, it is not a <form class="link-button> and it is most certainly not a <picture class="link-button>. It is a <link-button>.

    Also with what was stated above, you can use <link-button> to declare default internal elements (using <template> and <slot>) without using js to say what should be inside a link-button.

    To answer 2:

    Because you should make impossible states impossible (or at the very least present impossible states as impossible). Size is a state, it could be small, large or any other list of predefined values. If you use classes then you can end up with something like <link-element class="small large">. If you use attributes, you end up with something like <link-button size="small"> or <link-button size="large"> but not <link-button size="small" size="large"> (since that's illegal in html and duplicated attributes are ignored).

    Plus you're already using attributes for interactive aria roles (or you should be).

    So with a basic collapsible menu:

    <nav role="navigation">

    <a href="#">home</a>

    <button id="navbar-toggle" aria-expanded="false" aria-controls="navbar-menu">Menu</button>

    <ul id="navbar-menu">

      <li><a href="#">Login/Logout</a></li>
    
      <li><a href="#">Feedback</a></li>
    
      <li><a href="#">Other links...</a></li>
    
     </ul>
    

    </nav>

    You use css to style the menu being open or not with: `#navbar-toggle[aria-expanded=true] ~ #navbar-menu` and not something inaccessible like: `.navbar-menu.navbar-menu-open`.