HTML5 Web Components: The Solution to Div Soup?
- select the contributor at the end of the page -
<navigation>. It's great that HTML5 introduced a few new tags to improve markup semantics, but doing so didn't meaningfully resolve a core problem with today's markup: Review the markup of almost any modern web application and you'll find that the vast majority of tags are still
<div>tags. This is known as div soup. Just take a look at Gmail's markup, which nests divs 10 levels deep at various points: The story for Twitter isn't much different: Here's one last example with StackOverflow. Again, the markup is dominated by divs: You can see that StackOverflow has done an admirable job providing useful ID and class names on different elements. This certainly helps the maintenance programmer navigate the markup, but it's still composed of divs at least nine layers deep in this example.
What's the big problem?The problem is simple: Great markup conveys meaning; it tells the story about what's inside. Markup should make the developer's life easier by aiding readability and reducing the amount of work required to stand up a new data structure. Just imagine how frustrating it would be if we didn't have the
<ul>tags. Creating tabular data and bulleted lists via divs would be a big hassle, and the resulting markup wouldn't clearly convey the nature of the data inside. This is one of the big reasons people get so emotional about the misuse of tables for layout; it's semantically the wrong tool for the job. The
<div>tag is a simple, generic placeholder that should only be used when a good alternative can't be found. Just consider this definition from the Mozilla Developer Network:
The HTML <div> element is the generic container for flow content, which does not inherently represent anything. It can be used to group elements for styling purposes…or because they share attribute values ... It should be used only when no other semantic element is appropriate.That last sentence is key. We're using the
<div>tag all over the place because there's often no better alternative. Sure, the new HTML5 tags were a small step in the right direction, but what we really need is a simple way to create our own HTML tags.
The solution: custom elementsToday it's popular to use Angular Directives, Knockout Components, and Ember Components to create custom HTML tags. These options work well, but they're proprietary. Moving between these three options isn't so much a transition as it is a fall off a cliff. They each have their own proprietary methods for declaring, implementing and consuming components. The current technique for creating Angular directives looks nothing like Knockout components. We need a standardized way to declare our own HTML elements. Thankfully, there's good news: HTML5 Web Components specification finally gives us this power on a native level. We can define our own new, rich HTML tags without using third-party libraries. Custom elements make our markup much more descriptive. Which of these would you rather read? If you were working through the markup, looking for an issue with the way user avatars are displayed, which side would be easier to navigate? The answer is clear. That's the beauty of HTML5 Web Components. Each application's specific concepts can be reflected as rich HTML tags. This greatly increases the signal-to-noise ratio of our markup and empowers front-end developers to implement powerful solutions by referencing existing components. No more copy/paste/edit -- no more div soup. Declaring new HTML tags is as simple as registering the element using
document.registerElement('tag-name-here').Of course, there's much more to the story of web components than custom elements. Web components also offer encapsulation of our markup via the shadow DOM, inert templates via the <template> tag and an elegant way to deliver it all via HTML5 imports. With the era of standardized HTML5 Web Components nearly upon us, we finally have a single, canonical API for declaring and consuming reusable components. Sure, browser support might currently hold you back, but there's a web component polyfill library to help fill the gap in the meantime.