Skip to main content Accessibility Feedback

Why wrap native elements in a Web Component?

Yesterday, I wrote about why I like HTML as a baseline, and how I use Web Components to progressively enhance my HTML.

<ajax-form>
	<form action="/path/to/login.php" method="post">
		<!-- ... -->
	</form>
</ajax-form>

One common question I get with this approach is:

Why use the native form element at all? If you’re going to replace its functionality with JavaScript anyways, why not skip the form just wrap your fields in a custom element?

Great question, and makes a lot of sense if you think about interactivity as primarily a JavaScript thing.

Let’s dig in!

Enhance, not replace

The most important thing about this technique is that we’re not replacing the <form>. We’re enhancing it when—and only when—JavaScript is available.

If the JavaScript hasn’t loaded (because it’s still downloading, because you messed up the URL path, because it timed out, because an aggressive firewall or ad blocker blocked it, or any other reason), the page still functions perfectly fine.

If you remove the <form>, that’s no longer the case.

So what we’re doing with JS is not seeking to recreate the <form>, but hook into what it’s already doing and make it just a little better. It’s optional, not required.

Could we do the same thing with JS and data attributes? Sure! But why write custom data attributes when there’s already native HTML that does the same thing.

HTML super powers!

Including the <form> provides some other great benefits, too!

For starters, removing the <form> means that you have to listen for a click on the <button> instead of a submit event. But the submit event doesn’t just first on a <button> click. It also fires when someone presses return when focused on a form field.

It’s an accessibility heuristic that we’d either lose or have to recreate.

Using a <form> also means we can pass the entire element into the new FormData() constructor to get back an object of field names and values with just a single line of code, and send that along to our server.

All of which is to say, the whole point of this is to take advantage of what HTML gives you out of the box and (optionally) make it just a little nicer when you can.