What is the <form> tag in HTML?

Discover the HTML <form> tag: create interactive forms, collect user data, and master the action, method, and enctype attributes.
10 min read
Believemy logo

Definition of the <form> tag

The <form> tag is one of the most fundamental elements in HTML. It allows you to create an interactive form that collects data entered by the user and sends it to a server for processing. Without it, no registration, no login, no online payment would be possible. It is truly the bridge between the user and the server.

If you want to fully master HTML forms and all the subtleties of the language, we recommend following our complete HTML course which covers this topic in depth.

An HTML form acts as a container for different interactive elements: text fields (<input>), dropdown menus (<select>), text areas (<textarea>), buttons (<button>), checkboxes, radio buttons, and many more. When the user submits the form, the data contained in these elements is sent to the server using the specified HTTP method.

 

Basic syntax

The syntax of the <form> tag is relatively simple. It opens with <form> and closes with </form>. All form elements must be placed between these two tags.

HTML
<form action="/processing" method="post">
  <label for="name">Your name:</label>
  <input type="text" id="name" name="name">

  <label for="email">Your email:</label>
  <input type="email" id="email" name="email">

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

In this example, we have a simple form with two fields and a submit button. The action attribute indicates the URL to which the data will be sent, and the method attribute specifies the HTTP method used.

 

Essential attributes of  <form>

The <form> tag has many attributes that control its behavior. Understanding these attributes is essential for creating functional and secure forms.

The action attribute

The action attribute defines the URL to which the form data will be sent upon submission. If this attribute is omitted, the data is sent to the current page URL.

HTML
<!-- Sending to a specific URL -->
<form action="https://example.com/api/registration">
  ...
</form>

<!-- Sending to the current page (action omitted) -->
<form>
  ...
</form>

<!-- Sending to a relative path -->
<form action="/users/create">
  ...
</form>

 

The method attribute

The method attribute specifies the HTTP method used to send the data. The two main values are GET and POST.

MethodDescriptionUse case
GETData is appended to the URL as query parametersSearch, filters, non-sensitive data
POSTData is sent in the body of the HTTP requestRegistration, login, file uploads, sensitive data
HTML
<!-- Search form with GET -->
<form action="/search" method="get">
  <input type="text" name="q" placeholder="Search...">
  <button type="submit">Search</button>
</form>
<!-- The resulting URL will be: /search?q=keyword -->

<!-- Login form with POST -->
<form action="/login" method="post">
  <input type="text" name="username">
  <input type="password" name="password">
  <button type="submit">Log in</button>
</form>
Warning

Never use the GET method to send sensitive data such as passwords. GET parameters are visible in the URL, in the browser history, and in server logs.

 

The enctype attribute

The enctype attribute defines the encoding type used when sending data. It is particularly important when you need to upload files.

ValueDescription
application/x-www-form-urlencodedDefault value. Encodes special characters.
multipart/form-dataRequired for file uploads. Does not modify data encoding.
text/plainSends data as plain text. Rarely used.
HTML
<!-- File upload form -->
<form action="/upload" method="post" enctype="multipart/form-data">
  <label for="avatar">Choose a profile picture:</label>
  <input type="file" id="avatar" name="avatar" accept="image/*">
  <button type="submit">Upload</button>
</form>
Good to know

If you forget to add enctype="multipart/form-data" on a form containing a file type field, the file will not be correctly transmitted to the server.

 

Other important attributes

Here are other attributes you can use on the <form> tag:

AttributeDescription
targetSpecifies where to display the response (_self, _blank, _parent, _top)
autocompleteEnables (on) or disables (off) browser autocomplete
novalidateDisables native browser validation on submission
nameGives the form a name to reference it in JavaScript
relSpecifies the relationship between the current document and the target
HTML
<!-- Form without native validation, with autocomplete disabled -->
<form action="/registration" method="post" novalidate autocomplete="off">
  <input type="email" name="email" required>
  <input type="password" name="password" minlength="8" required>
  <button type="submit">Sign up</button>
</form>

 

Practical form examples

Let's now look at concrete examples of forms that you will frequently encounter in your web projects.

Complete registration form

Here is a typical registration form using different field types, <label> for accessibility, and a <fieldset> to logically group fields:

HTML
<form action="/api/registration" method="post">
  <fieldset>
    <legend>Personal information</legend>

    <label for="firstname">First name:</label>
    <input type="text" id="firstname" name="firstname" required>

    <label for="lastname">Last name:</label>
    <input type="text" id="lastname" name="lastname" required>

    <label for="birthdate">Date of birth:</label>
    <input type="date" id="birthdate" name="birthdate">
  </fieldset>

  <fieldset>
    <legend>Login credentials</legend>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>

    <label for="password">Password:</label>
    <input type="password" id="password" name="password" minlength="8" required>

    <label for="password-confirm">Confirm password:</label>
    <input type="password" id="password-confirm" name="password_confirm" minlength="8" required>
  </fieldset>

  <label>
    <input type="checkbox" name="terms" required>
    I accept the terms and conditions
  </label>

  <button type="submit">Create my account</button>
</form>

 

Contact form

A contact form is another very common use case. It combines standard text fields with a larger text area for the message:

HTML
<form action="/contact" method="post">
  <label for="contact-name">Your name:</label>
  <input type="text" id="contact-name" name="name" required>

  <label for="contact-email">Your email:</label>
  <input type="email" id="contact-email" name="email" required>

  <label for="contact-subject">Subject:</label>
  <select id="contact-subject" name="subject">
    <option value="">-- Choose a subject --</option>
    <option value="support">Technical support</option>
    <option value="sales">Sales inquiry</option>
    <option value="other">Other</option>
  </select>

  <label for="contact-message">Your message:</label>
  <textarea id="contact-message" name="message" rows="6" required></textarea>

  <button type="submit">Send message</button>
</form>

 

Search form

Search forms are generally short and use the GET method, because search terms are not sensitive and it is useful to be able to share the results URL:

HTML
<form action="/search" method="get" role="search">
  <label for="search">Search:</label>
  <input type="search" id="search" name="q" placeholder="Type your search..." required>
  <button type="submit">Search</button>
</form>
Good to know

The role="search" attribute improves accessibility by indicating to assistive technologies that this form is a search form.

 

Form validation

HTML5 introduced a very powerful native validation system that allows you to check user-entered data before it is even sent to the server. This client-side validation improves the user experience, but should never replace server-side validation.

Validation attributes

Here are the main validation attributes available on form elements:

AttributeDescriptionExample
requiredThe field must be filled in<input required>
minlengthMinimum number of characters<input minlength="3">
maxlengthMaximum number of characters<input maxlength="50">
minMinimum numeric value<input type="number" min="0">
maxMaximum numeric value<input type="number" max="100">
patternRegular expression to match<input pattern="[A-Za-z]{3,}">
typeAutomatic validation based on type<input type="email">
HTML
<form action="/validate" method="post">
  <!-- Required field with minimum length -->
  <label for="username">Username (3-20 characters):</label>
  <input type="text" id="username" name="username"
         required minlength="3" maxlength="20"
         pattern="[a-zA-Z0-9_]+"
         title="Only letters, numbers, and underscores">

  <!-- Email field with automatic validation -->
  <label for="email">Email:</label>
  <input type="email" id="email" name="email" required>

  <!-- Numeric field with limits -->
  <label for="age">Age (18-120):</label>
  <input type="number" id="age" name="age" min="18" max="120">

  <!-- Phone field with pattern -->
  <label for="tel">Phone:</label>
  <input type="tel" id="tel" name="phone"
         pattern="[0-9]{10}"
         title="Enter a 10-digit number">

  <button type="submit">Validate</button>
</form>
Warning

Client-side validation (HTML or JavaScript) should never be your only line of defense. A malicious user can easily bypass this validation. Always validate data on the server side as well.

 

Form accessibility

Accessibility is a crucial aspect of form design. A poorly structured form can be completely unusable for people using assistive technologies such as screen readers.

Essential accessibility rules

Here are the best practices to follow systematically:

  • Always associate a <label> with each field: use the for attribute on the <label> that matches the field's id.
  • Use <fieldset> and <legend>: group logically related fields (for example, radio buttons for the same choice).
  • Provide clear error messages: clearly indicate what needs to be corrected.
  • Use ARIA attributes when necessary: aria-describedby, aria-required, aria-invalid.
  • Ensure keyboard navigation: the user must be able to fill out the entire form using the Tab key.
HTML
<form action="/registration" method="post">
  <!-- Correctly associated label -->
  <label for="user-email">Email address:</label>
  <input type="email" id="user-email" name="email"
         required aria-describedby="email-help">
  <span id="email-help">Example: user@domain.com</span>

  <!-- Radio button group with fieldset -->
  <fieldset>
    <legend>Your HTML level:</legend>
    <label>
      <input type="radio" name="level" value="beginner">
      Beginner
    </label>
    <label>
      <input type="radio" name="level" value="intermediate">
      Intermediate
    </label>
    <label>
      <input type="radio" name="level" value="advanced">
      Advanced
    </label>
  </fieldset>

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

 

Styling a form with CSS

HTML forms are notoriously difficult to style consistently across browsers. Here is an example of basic CSS to give your forms a professional look:

CSS
form {
  max-width: 500px;
  margin: 0 auto;
  padding: 2rem;
}

label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: bold;
}

input[type="text"],
input[type="email"],
input[type="password"],
textarea,
select {
  width: 100%;
  padding: 0.75rem;
  margin-bottom: 1rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 1rem;
  box-sizing: border-box;
}

input:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: #4a90d9;
  box-shadow: 0 0 0 3px rgba(74, 144, 217, 0.25);
}

input:invalid:not(:placeholder-shown) {
  border-color: #e74c3c;
}

input:valid:not(:placeholder-shown) {
  border-color: #2ecc71;
}

button[type="submit"] {
  background-color: #4a90d9;
  color: white;
  padding: 0.75rem 2rem;
  border: none;
  border-radius: 4px;
  font-size: 1rem;
  cursor: pointer;
}

button[type="submit"]:hover {
  background-color: #357abd;
}

This CSS uses the :focus, :valid, and :invalid pseudo-classes to provide visual feedback to the user. The :placeholder-shown pseudo-class prevents fields from being marked as invalid before the user has even started filling them in.

 

Best practices

To create efficient, accessible, and secure forms, here are the best practices you should systematically apply:

  • Always use the POST method for sensitive data (passwords, personal information).
  • Add a name attribute to each form field, as this name will be used as the key when sending data to the server.
  • Use the right input types: email, tel, url, number, date, etc. This enables native validation and displays the correct keyboard on mobile.
  • Don't forget the enctype="multipart/form-data" attribute when your form contains file input fields.
  • Favor HTML semantics: use <fieldset>, <legend>, <label>, <datalist>, and appropriate input types rather than rebuilding everything with <div>.
  • Implement CSRF protection (Cross-Site Request Forgery) on the server side for your sensitive forms.
  • Add appropriate autocomplete attributes on each field to improve the user experience.
  • Test your forms with the keyboard: make sure the tab order is logical and the form is entirely navigable without a mouse.

 

Interaction with JavaScript

The <form> tag interacts closely with JavaScript to offer advanced user experiences. Here is how to intercept a form submission:

JAVASCRIPT
const form = document.querySelector('form');

form.addEventListener('submit', function(event) {
  // Prevent the default form submission
  event.preventDefault();

  // Retrieve the form data
  const data = new FormData(form);

  // Asynchronous submission with fetch
  fetch('/api/registration', {
    method: 'POST',
    body: data
  })
  .then(response => response.json())
  .then(result => {
    console.log('Success:', result);
  })
  .catch(error => {
    console.error('Error:', error);
  });
});

The FormData object is extremely convenient: it automatically collects all form data (including files) and formats it correctly for sending. This approach with fetch() is now the recommended method for submitting forms asynchronously, without page reload.

 

Frequently asked questions

Question

What is the difference between GET and POST methods in a form?

The GET method appends form data directly to the URL as parameters (for example /search?q=html). It is visible, limited in size, and suitable for searches or filters. The POST method sends data in the body of the HTTP request, so it is invisible in the URL. Use POST for sensitive data, files, or large volumes of data.

 

Question

Can you nest forms in HTML?

No, it is forbidden to nest <form> tags inside each other according to the HTML specification. If you need multiple actions on the same page, you can use the form attribute on <input> or <button> elements to associate them with a specific form without them being physically inside it.

 

Question

How do you submit a form without reloading the page?

To submit a form without reloading, you need to use JavaScript. Intercept the submit event with addEventListener, call event.preventDefault() to prevent the default behavior, then use the fetch() API or XMLHttpRequest to send the data asynchronously (AJAX). The FormData object greatly simplifies collecting form data.

 

Question

How can I learn to create complete HTML forms?

Mastering HTML forms requires practice and a good understanding of the various elements available (<input>, <select>, <textarea>, <fieldset>, <button>, <datalist>, etc.). To progress efficiently, we recommend following our HTML course on Believemy, which will guide you step by step through creating accessible, secure, and professional forms, with hands-on practical exercises.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.