📖 Deeper dive reading: MDN Input element
From the very early days of HTML it contained elements for accepting the input of user data. These elements include the following:
| Element | Meaning | Example |
|---|---|---|
form |
Input container and submission | <form action="form.html" method="post"> |
fieldset |
Labeled input grouping | <fieldset> ... </fieldset> |
input |
Multiple types of user input | <input type="" /> |
select |
Selection dropdown | <select><option>1</option></select> |
optgroup |
Grouped selection dropdown | <optgroup><option>1</option></optgroup> |
option |
Selection option | <option selected>option2</option> |
textarea |
Multiline text input | <textarea></textarea> |
label |
Individual input label | <label for="range">Range: </label> |
output |
Output of input | <output for="range">0</output> |
meter |
Display value with a known range | <meter min="0" max="100" value="50"></meter> |
The <form> element is a container used to collect user input and send that data to a specified destination, typically a web server. It acts as the foundational structure for interactive components like login screens, search bars, and contact forms.
Before JavaScript was introduced the form container element was essential because it was the only way for the browser to send the input data to a web server as part of a request to process the input and generate a new web page displaying the result of the input. With modern HTML, the form element is still important because it gives meaning to user input, works well with accessibility tools like screen readers, and relies on built-in browser features that handle input and submission reliably.
To function correctly, a form relies on two primary attributes:
action: Defines the URL of the server-side resource (e.g., an API endpoint) that will process the submitted data.method: Specifies the HTTP method used to send the data.GET: Appends form data to the URL in name/value pairs. Used for non-sensitive data like search queries.POST: Sends data inside the body of the HTTP request. Used for sensitive information (like passwords) or when sending large amounts of data.
The form element wraps various interactive controls that allow users to enter data:
<label>: Provides a caption for an input. It improves accessibility and increases the clickable area for the associated field.<input>: The most versatile element, used for text fields, checkboxes, radio buttons, and more, depending on itstypeattribute.<textarea>: Used for multi-line text input.<select>: Creates a drop-down list of options.<button>: Used to submit the form (whentype="submit") or reset it (whentype="reset").
For data to be sent to the server, every input within the form must have a name attribute. The name acts as the key, and the user's input acts as the value (e.g., username=JohnDoe). Without the name attribute, the browser will not include that specific input's data in the submission.
Here is an example of a simple form that submits the value of a textarea element.
<form action="submission.html" method="post">
<label for="ta">TextArea: </label>
<textarea id="ta" name="ta-id">
Some text
</textarea>
<button type="submit">Submit</button>
</form>Try this out by modifying the text and pressing the submit button to simulate sending data to a web server. The browser generates the data by combining the textarea's name attribute with the current value of the textarea.
{"id":"c069b636-4426-4d32-b19f-1ef2379b5a72", "title":"Web page", "type":"web-page", "height":190}
<form id="messageForm">
<label for="ta">TextArea: </label>
<textarea id="ta" name="ta-id">Some text</textarea>
<button type="submit">Submit</button>
</form>
<div id="message">... </div>
<style>
form { border: thin solid #efefef; padding: 1em;}
textarea { display:block; margin: .5em 0;}
#message { margin-top:1em;padding:1em;background:black;color:white;font-family:monospace; border:thin black solid; }
</style>
<script>
const form = document.getElementById('messageForm');
form.addEventListener('submit', function(event) {
event.preventDefault(); // stop page reload
const text = document.getElementById('ta').value.replace(' ', '+');
const output = document.getElementById('message');
output.innerText = `ta-id=${text}`;
});
</script>
With JavaScript we have much more control over input data and what is done with it. For example, in a single page application the JavaScript will dynamically rebuild the HTML elements to reflect the results of the user interaction. With this ability the data may not even be sent to the server. This greatly reduces the necessity of the form element, but it is often still used simply as a container. Just remember that you are not required to have a form element to use input elements.
- Accessibility: Always associate labels with inputs using the
forattribute on the<label>and a matchingidon the<input>. - Validation: Use attributes like
required,minlength, andpatternto ensure data is formatted correctly before submission. - Security: Always use the
POSTmethod for forms that handle sensitive user data.
Inside of your form elements you can include input element that represent many different input types. You set the type of input with the type attribute. There are several different types to choose from. This includes different flavors of textual, numeric, date, and color inputs.
| Type | Meaning |
|---|---|
| text | Single line textual value |
| password | Obscured password |
| Email address | |
| tel | Telephone number |
| url | URL address |
| number | Numerical value |
| checkbox | Inclusive selection |
| radio | Exclusive selection |
| range | Range limited number |
| date | Year, month, day |
| datetime-local | Date and time |
| month | Year, month |
| week | Week of year |
| color | Color |
| file | Local file |
| submit | button to trigger form submission |
In order to create an input you specify the desired type attribute along with any other attribute associated with that specific input. Here is an example of a checked radio button and its associated label.
<label for="checkbox1">Check me</label> <input type="checkbox" name="varCheckbox" value="checkbox1" checked />Most input elements share some common attributes. These include the following.
| Attribute | Meaning |
|---|---|
| name | The name of the input. This is submitted as the name of the input if used in a form |
| disabled | Disables the ability for the user to interact with the input |
| value | The initial value of the input |
| required | Signifies that a value is required in order to be valid |
Several of the input elements have validation built into them. This means that they will not accept a value that is not for example, a number, a URL, outside of a range, or an email address. You can also specify the required attribute on an input element to mark it as requiring a value before it can be submitted. The pattern attribute exists on text, search, url, tel, email, and password inputs. When present, the pattern attribute provides a regular expression that must match for the input to be considered as valid.
You should also have validation built into your JavaScript that checks input data to ensure everything is valid before it is submitted. All of the input elements support functions for determining their validation state. Additionally, there are CSS style selectors for visualizing the validity of the input. In order to have a good user experience, it is critical that you provide sufficient user feedback early in the input process. A good design will give feedback as, or before, the user begins to input. A poor design will keep the user guessing as to why the data is not being accepted, or even if it was accepted.
{"id":"0875ed29-b9fb-4b47-a3bf-05cd622d574b", "title":"Form assignment", "type":"ai-web-page", "allowAiPrompt":false, "syncGrade":false, "autoGrade":false, "gradingCriteria":"Replace the text input's placeholder with 'your name here'. Add an additional optgroup. Add an additional checkbox. Add an additional radio button. Change the color input to default to red.", "height":1000 }
Experiment with the form inputs.
1. Replace the text input's placeholder with "your name here".
2. Add an additional optgroup.
3. Add an additional checkbox.
4. Add an additional radio button.
5. Change the color input to default to red.
~~~html
<body>
<h1>Example Form</h1>
<form id="messageForm">
<ul>
<li>
<!-- Includes validation-->
<label for="text">Text: </label>
<input type="text" id="text" name="vText" placeholder="text that starts with A" required pattern="[Aa].*" />
</li>
<li>
<label for="password">Password: </label>
<input type="password" id="password" name="vPassword" />
</li>
<li>
<label for="email">Email: </label>
<input type="email" id="email" name="vEmail" />
</li>
<li>
<label for="textarea">TextArea: </label>
<textarea id="textarea" name="vTextarea"></textarea>
</li>
<li>
<label for="select">Select: </label>
<select id="select" name="vSelect">
<option>option1</option>
<option selected>option2</option>
<option>option3</option>
</select>
</li>
<li>
<label for="optgroup">OptGroup: </label>
<select id="optgroup" name="vOptGroup">
<optgroup label="group1">
<option>option1</option>
<option selected>option2</option>
</optgroup>
<optgroup label="group2">
<option>option3</option>
<option>option4</option>
</optgroup>
</select>
</li>
<li>
<fieldset>
<legend>checkbox</legend>
<label for="checkbox1">checkbox1</label>
<input type="checkbox" id="checkbox1" name="vCheckbox" value="checkbox1" checked />
<label for="checkbox2">checkbox2</label>
<input type="checkbox" id="checkbox2" name="vCheckbox" value="checkbox2" />
<label for="checkbox3">checkbox3</label>
<input type="checkbox" id="checkbox3" name="vCheckbox" value="checkbox3" />
</fieldset>
</li>
<li>
<fieldset>
<legend>radio</legend>
<label for="radio1">radio1</label>
<input type="radio" id="radio1" name="vRadio" value="radio1" checked />
<label for="radio2">radio2</label>
<input type="radio" id="radio2" name="vRadio" value="radio2" />
<label for="radio3">radio3</label>
<input type="radio" id="radio3" name="vRadio" value="radio3" />
</fieldset>
</li>
<li>
<!-- Submit form with POST method and enctype="multipart/form-data" to send file contents. -->
<label for="file">File: </label>
<input type="file" id="file" name="vFile" accept="image/*" multiple />
</li>
<li>
<label for="search">Search: </label>
<input type="search" id="search" name="vSearch" />
</li>
<li>
<label for="tel">Tel: </label>
<input type="tel" id="tel" name="vTel" placeholder="###-####" pattern="\d{3}-\d{4}" />
</li>
<li>
<label for="url">URL: </label>
<input type="url" id="url" name="vUrl" />
</li>
<li>
<label for="number">Number: </label>
<input type="number" name="vNumber" id="number" min="1" max="10" step="1" />
</li>
<li>
<label for="range">Range: </label>
<input type="range" name="vRange" id="range" min="0" max="100" step="1" value="0" />
<output id="rangeOutput" for="range">0</output>
<!-- Range requires some JavaScript in order to make it work. Ignore this for now. -->
<script>
const range = document.querySelector('#range');
const rangeOutput = document.querySelector('#rangeOutput');
range.addEventListener('input', function() {
rangeOutput.textContent = range.value;
});
</script>
</li>
<li>
<label for="progress">Progress: </label>
<progress id="progress" max="100" value="75"></progress>
</li>
<li>
<label for="meter">Meter: </label>
<meter id="meter" min="0" max="100" value="50" low="33" high="66" optimum="50"></meter>
</li>
<li>
<label for="datetime">DateTime: </label>
<input type="datetime-local" name="vDatetime" id="datetime" />
</li>
<li>
<label for="time">Time: </label>
<input type="time" name="vTime" id="time" />
</li>
<li>
<label for="month">Month: </label>
<input type="month" name="vMonth" id="month" />
</li>
<li>
<label for="week">Week: </label>
<input type="week" name="vWeek" id="week" />
</li>
<li>
<label for="color">Color: </label>
<input type="color" name="vColor" id="color" />
</li>
<!-- This doesn't show up to the user, but allows the form to send associated data. -->
<input type="hidden" id="secretData" name="vSecretData" value="1989 - the web was born" />
</ul>
<button type="submit">Submit</button>
</form>
<div id="message">... </div>
</body>
<style>
* {font-family: Arial;}
body { padding: 0 1em;}
li { list-style-type: none; padding: 0.25em 0;}
form { border: thin solid #efefef; padding: 1em;}
textarea { display:block; margin: .5em 0;}
#message { margin-top:1em;padding:1em;background:black;color:white;font-family:monospace; border:thin black solid; white-space: pre-wrap; word-break: break-all;}
</style>
<script>
const form = document.getElementById('messageForm');
form.addEventListener('submit', function(event) {
event.preventDefault(); // stop page reload
const formData = new FormData(form);
const params = new URLSearchParams();
for (const [key, value] of formData) {
if (value instanceof File) {
params.append(key, value.name);
} else {
params.append(key, value);
}
}
const output = document.getElementById('message');
output.innerText = params.toString();
});
</script>
~~~