What is the purpose of the html form tag

Form tags are still necessary if you want to be able to submit the form without AJAX (which may be useful in the early stages of development). But even though it's possible to use javascript to submit data without a form tag, a few benefits still come to mind:

  1. Using form tags can help people read and understand you code in some cases, by showing them your intentions.
  2. The 'submit' method is available on forms. If you have a form with an input[type=submit], and it's not disabled, then when someone hits 'enter' while filling out one of the other form inputs, the form will submit. You can still do that by listening for the 'keydown' event on the input elements, but it's a nice bit of ui that you get for free with form tags.
  3. There are be a few other things that only work with a form tag, or are easier with a form tag. Developers will eventually run into these cases, and decide it's easier just to always use them everywhere and avoid problems. Really, the real question is, why not use a form tag?

What you are missing is an understanding of semantic markup, and the DOM.

Realistically, you can pretty much do whatever you want with HTML5 markup, and most browsers will parse it. Last time I checked, WebKit / Blink even allows pseudo-elements inside <input> elements, which is a clear violation of the spec - Gecko not so much. However, doing whatever you like with your markup will undoubtably invalidate it as far as semantics are concerned.

Why do we put <input> elements inside of <form> elements? For the same reason we put <li> tags inside of <ul> and <ol> elements - it's where they belong. It's semantically correct, and helps to define the markup. Parsers, screen readers, and various software can better understand your markup when it is semantically correct - when the markup has meaning, not just structure.

The <form> element also allows you to define method and action attributes, which tell the browser what to do when the form is submitted. AJAX isn't a 100% coverage tool, and as a web developer you should be practicing graceful degradation - forms should be able to be submitted, and data transferred, even when JS is turned off.

Finally, forms are all registered properly in the DOM. We can take a peek at this with JavaScript. If you open up your console on this very page, and type:

document.forms

You'll get a nice collection of all the forms on the page. The searchbar, the comment boxes, the answer box - all proper forms. This interface can be useful for accessing information, and interacting with these elements. For example, forms can be serialized very easily.

Here's some reading material:

  • Semantic HTML
  • HTML forms guide

Note: <input> elements can be used outside of forms, but if your intention is to submit data in any way, you should be using a form.


This is the part of the answer where I flip the question around.

How am I making my life harder by avoiding forms?

First and foremost - container elements. Who needs 'em, right?!

Certainly your little <input> and <button> elements are nested inside some kind of container element? They can't just be floating around in the middle of everything else. So if not a <form>, then what? A <div>? A <span>?

These elements have to reside somewhere, and unless your markup is a crazy mess the container element can just be a form.

No? Oh.

At this point the voices in my head are very curious as to how you create your event handlers for all these different AJAX situations. There must be a lot, if you need to cut down on your markup to save bytes. Then you must create custom functions for each AJAX event that corresponds to each 'set' of elements - which you must have to target individually or with classes, right? Theres no way to really group these elements generically, since we've established that they just kind of roam around the markup, doing whatever until they are needed.

So you custom code a few handlers.

$('#searchButton').on('click', function (e) {
  e.preventDefault();

  var search = $('#mySearch');

  $.ajax({
    url: 'http://example.com/text',
    type: 'GET',
    dataType: 'text',
    data: 'query=' + search.val(),
    success: function (data) {
      console.log(data);
    }
  });
});


$('#login').on('click', function (e) {
  e.preventDefault();
  var user = $('#username'),
      pass = $('#password'),
      rem = $('#remember');
  
  $.ajax({
    url: 'http://example.com/login',
    type: 'POST',
    data: user.add(pass, rem).serialize(),
    dataType: 'text',
    success: function (data) {
      console.log(data);
    }
  });
});
<!-- No containers, extra markup is silly. -->

<input type="text" id="mySearch" value="query" />
<button id="searchButton">Search</button>
<input type="text" id="username" name="username" value="user" />
<input type="password" id="password" name="password" value="pass" />
<input type="checkbox" id="remember" name="remember" checked /> stay logged in
<button id="login">Login</button>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

This is the part where you say something like:

'I totally use reusable functions though. Stop exaggerating.'

Fair enough, but you still need to create these sets of unique elements, or target class sets, right? You still have to group these elements somehow.

Lend me your eyes (or ears, if you're using a screen reader and need some assistance - good thing we could add some ARIA to all this semantic markup, right?), and behold the power of the generic form.

function genericAjaxForm (e) {
  e.preventDefault();
  var form = $(this);
  
  return $.ajax({
    url: form.attr('action'),
    type: form.attr('method'),
    dataType: form.data('type'),
    data: form.serialize()
  });
}

$('#login-form').on('submit', function (e) {
  genericAjaxForm.call(this, e).done(function (data) {
    console.log(data);
  });
});
<form action="http://example.com/login" method="POST" data-type="text" id="login-form">
  <input type="text" name="username" value="user" />
  <input type="password" name="password" value="mypass" />
  <label>
    <input type="checkbox" name="remember" /> Remember me
  </label>

  <button type="submit">Login</button>
</form>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

We can use this with any common form, maintain our graceful degradation, and let the form completely describe how it should function. We can expand on this base functionality while keeping a generic style - more modular, less headaches. The JavaScript just worries about its own things, like hiding the appropriate elements, or handling any responses we get.

And now you say:

'But I wrap my pseudo-forms in <div> elements that have specific IDs - I can then target the inputs loosely with with .find, and .serialize them, and ...'

Oh, what's that? You actually wrap your <input> elements in a container?

So why isn't it a form yet?