25 HTML5 Features, Tips, and Techniques You Must Know

This industry moves fast—really fast! If you're not careful, you'll be left in its dust. So, if you're feeling a bit overwhelmed with all the features in HTML5, use this as a primer on the things you must know.
Before browsing through these techniques, have a look at our HTML5 templates, as a quality theme might be a good option for your next project.
1. New Doctype
In the past, we had to use the impossible-to-memorize XHTML doctype like the one below:
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2 |
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
The newer HTML5 doctype is a lot easier to use. It is also case-insensitive, which means that you could capitalize HTML
and make doctype
lowercase.
1 |
<!DOCTYPE html>
|
2 |
|
3 |
<!-- Also Valid -->
|
4 |
<!doctype HTML>
|
In fact, did you know that it isn't even really necessary for HTML5? However, it's used for current and older browsers that require a specified doctype
. Browsers that do not understand this doctype will simply render the contained markup in standards mode. So, without worry, feel free to throw caution to the wind and embrace the new HTML5 doctype.
2. No More Types for Scripts and Links
You might add the type
attribute to your link
and script
tags.
1 |
<link rel="stylesheet" href="path/to/stylesheet.css" type="text/css" /> |
2 |
<script type="text/javascript" src="path/to/script.js"></script> |
This is not necessary. It's implied that both of these tags refer to stylesheets and scripts respectively. As such, we can remove the type
attribute altogether.
1 |
<link rel="stylesheet" href="path/to/stylesheet.css" /> |
2 |
<script src="path/to/script.js"></script> |
3. To Quote or Not to Quote
That is the question. Remember, HTML5 is not XHTML. You don't have to wrap your attributes in quotation marks if you don't want to. You don't have to close your elements. With that said, there's nothing wrong with doing so, if it makes you feel more comfortable. I find that this is true for me.
1 |
<p class=myClass id=someId> Start the reactor. |
Make up your own mind on this one. If you prefer a more structured document, by all means stick with the quotes.
I personally prefer using quotes and closing tags to keep everything consistent. For example, if an element has multiple classes, you will have to use quotes anyway.
4. The Figure Element
Consider the following markup for an image:
1 |
<img src="path/to/image" alt="About image" /> |
2 |
<p>Image of Mars. </p> |
There unfortunately isn't any easy or semantic way to associate the caption, wrapped in a paragraph tag, with the image element itself. HTML5 rectifies this, with the introduction of the <figure>
element. When combined with the <figcaption>
element, we can now semantically associate captions with their image counterparts.
1 |
<figure>
|
2 |
<img src="path/to/image" alt="About image" /> |
3 |
<figcaption>
|
4 |
<p>This is an image of something interesting. </p> |
5 |
</figcaption>
|
6 |
</figure>
|
While the figure element is usually used with an image or video, you can use it with other kinds of self-contained content like a quote or code snippet as well.
5. <small>
Redefined
The <small>
element will render the text it contains at one smaller size than the current one. For example, if the containing element has normal font size, then <small>
would render it at small font size. If the containing element has small font size, then <small>
would render it at x-small font size.
Due to its size-shrinking ability, the <small>
element was earlier used as a presentational element. The <small>
element has been redefined, more appropriately, to refer to small print. Imagine a copyright statement in the footer of your site; according to the new HTML5 definition of this element, <small>
would be the correct wrapper for this information.
6. The Semantic Header and Footer
Gone are the days of:
1 |
<div id="header"> |
2 |
... |
3 |
</div>
|
4 |
|
5 |
<div id="footer"> |
6 |
... |
7 |
</div>
|
Divs, by nature, have no semantic structure—even after an id
is applied. Now, with HTML5, we have access to the <header>
and <footer>
elements. The markup above can now be replaced with:
1 |
<header>
|
2 |
... |
3 |
</header>
|
4 |
|
5 |
<footer>
|
6 |
... |
7 |
</footer>
|
It's fully appropriate to have multiple header
s and footer
s in your projects.
Try not to confuse these elements with the "header" and "footer" of your website. They simply refer to their container. As such, it makes sense to place, for example, meta information at the bottom of a blog post within the footer
element. The same holds true for the header
.
7. Make Your Content Editable
Newer browsers have a nifty attribute that can be applied to elements, called contenteditable
. As the name implies, this allows the user to edit any of the text contained within the element, including its children. There are a variety of uses for something like this, including an app as simple as a to-do list, which also takes advantage of local storage.
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
<head>
|
4 |
<meta charset="utf-8"> |
5 |
<title>Making Content Editable</title> |
6 |
</head>
|
7 |
<body>
|
8 |
<h2>Editable To-Do List</h2> |
9 |
<ol contenteditable="true"> |
10 |
<li>Break mechanical cab driver.</li> |
11 |
<li>Drive to abandoned factory.</li> |
12 |
<li>Watch video of self.</li> |
13 |
</ol>
|
14 |
</body>
|
15 |
</html>
|
Here are some tutorials for you to read to learn how to use the contentEditable
attribute practically.
- Create an Inline Text Editor With the contentEditable AttributeMonty Shokeen29 Jun 2022
- Create a WYSIWYG Editor With the contentEditable AttributeMonty Shokeen26 Apr 2016
8. Local Storage
Thanks to local storage (not officially HTML5, but grouped in for convenience's sake), we can make advanced browsers "remember" what we type, even after the browser is closed or refreshed.
There are a few things that you should keep in mind when using localStorage
. First, the keys and values in localStorage
are always stored in the utf-16 format, where each character takes up the space of two bytes. Second, localStorage
returns different objects based on the protocol of the document, even if you are visiting the same URL.
9. Email Inputs
If we apply a type
of email to form inputs, we can instruct the browser to only allow strings that conform to a valid email address structure. That's right, you now get built-in form validation in browsers. In older browsers that do not understand this email type, the input will simply fall back to a regular textbox.
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
<head>
|
4 |
<meta charset="utf-8"> |
5 |
<title>Multiple Inputs Type Attributes</title> |
6 |
</head>
|
7 |
<body>
|
8 |
<form action="" method="get"> |
9 |
<label for="email">Email:</label> |
10 |
<input id="email" name="email" type="email" /> |
11 |
<button type="submit">Submit Form</button> |
12 |
</form>
|
13 |
</body>
|
14 |
</html>
|
There are a lot of other input type
attribute values that you can use such as month, number, tel, and url. Some of them are well-supported in all browsers, while others are not. On devices with dynamic keyboards, even the keyboard layout will adapt to let you fill in specific input values.
Take a look at our tutorial on form input validation using only HTML5 and Regex to learn more.
10. Placeholders
Before, we had to use a bit of JavaScript to create placeholders for textboxes. Sure, you can initially set the value
attribute how you see fit, but, as soon as the user deletes that text and clicks away, the input will be left blank again. The placeholder
attribute remedies this.
1 |
<input name="email" type="email" placeholder="doug@givethesepeopleair.com" /> |
Here is a CodePen demo that illustrates the use of both the input type
attribute and the placeholder
attribute:
11. More HTML5 Form Features
Working with forms has become a lot easier with the introduction of new features that help with input validation among other things. Learn about more helpful HTML5 form features in this quick video tip.
You can also read this post with over 20 best practices for working with HTML5 forms.
12. Required Attribute
Forms allow for a required
attribute, which specifies, naturally, whether a particular input is required. Dependent upon your coding preference, you can declare this attribute in one of two ways:
1 |
<input type="text" name="someInput" required> |
Either method will do. With this code, and within browsers that support this attribute, a form cannot be submitted if that "someInput" input is blank. Here's a quick example; we'll also add the placeholder attribute as there's no reason not to.
1 |
<form action="" method="get"> |
2 |
<label for="email">Email:</label> |
3 |
<input id="email" name="email" type="email" required placeholder="monty@tutsplus.com" /> |
4 |
<br>
|
5 |
<label for="website">Website:</label> |
6 |
<input id="website" name="website" type="url" placeholder="https://code.tutsplus.com" /> |
7 |
<br>
|
8 |
<button type="submit">Submit Form</button> |
9 |
</form>
|
Any input elements that have the required
attribute will also get a :required
pseudo-class that you can use to style those inputs in order to differentiate them from optional inputs. Here is an example:
If the input is left blank, and the form is submitted, the textbox will be highlighted.
13. Autofocus Attribute
Again, HTML5 removes the need for JavaScript solutions. If a particular input should be "selected," or focused, by default, we can now use the autofocus
attribute.
1 |
<input type="text" name="someInput" placeholder="Douglas Quaid" required autofocus> |
There are some important points that you need to keep in mind while using the autofocus
attribute. Use of this attribute can cause behavior such as auto-scrolling of the page on load or the appearance of dynamic keyboards on smartphones.
14. Regular Expressions
How often have you found yourself writing some quickie regular expression to verify a particular textbox? Thanks to the new pattern
attribute, we can insert a regular expression directly into our markup.
1 |
<form action="" method="post"> |
2 |
<label for="username">Create a Username: </label> |
3 |
<input type="text" |
4 |
name="username" |
5 |
id="username" |
6 |
placeholder="4 to 10 alphabetic characters." |
7 |
pattern="[A-Za-z]{4,10}" |
8 |
autofocus
|
9 |
required> |
10 |
<button type="submit">Go </button> |
11 |
</form>
|
If you're moderately familiar with regular expressions, you'll be aware that the pattern [A-Za-z]{4,10}
accepts only upper and lowercase letters. This string must also have a minimum of four characters, and a maximum of ten.
Notice that we're beginning to combine all of these awesome attributes!
- JavaScript Regex Cheat SheetMonty Shokeen23 Mar 2022
- 9 Regular Expressions You Should KnowVasili23 Oct 2022
15. Audio Support
No longer do we have to rely upon third-party plugins to render audio. HTML5 offers the <audio>
element.
1 |
<audio controls> |
2 |
<source src="file.mp3" /> |
3 |
</audio>
|
Alternatively, you could also use the src
attribute to specify the source of the audio file.
1 |
<audio controls src="file.mp3" /> |
2 |
</audio>
|
Earlier, different browsers needed different file formats in order to play audio. However, now you can simply add an .mp3 source file and be good to go in any browser.
16. Video Support
Much like the <audio>
element, we also, of course, have HTML5 video as well in the new browsers! You can provide the source file either using the source
tags or using the src
attribute.
1 |
<video controls preload> |
2 |
<source src="video_file.mp4" /> |
3 |
<p> Your browser is old. <a href="video_file.mp4">Download this video instead.</a> </p> |
4 |
</video>
|
We have also added a paragraph inside the <video>
element. Any content placed inside the video tags is only shown if the browser doesn't support the <video>
element. The same thing applies to the <audio>
element.
17. Preload Videos
The preload
attribute does exactly what you'd guess. With that said, you should first decide whether or not you want the browser to preload the video. Is it necessary? Perhaps, if the visitor accesses a page that's specifically made to display a video, you should preload the video and save the visitor a bit of waiting time. Videos can be preloaded by setting preload="preload"
, or by simply adding preload
.
1 |
<video preload> |
You can also set the value of this attribute to metadata
to indicate that only the video metadata should be fetched. Keep in mind that the browser is not required to actually follow the value of this attribute.
18. Display Controls
If you're following each of these tips and techniques, you might have noticed that, with the code above, the video above appears to be only an image, without any controls. To render these play controls, we must specify the controls
attribute within the video
element.
1 |
<video preload controls> |
The controls that show up while you play any audio or video are browser-specific and will change when you use a different browser.
19. Mark Element
Think of the <mark>
element as a highlighter. A string wrapped within this tag should be relevant to the current actions of the user. For example, if I searched for "Open your Mind" on a blog, I could then use some JavaScript to wrap each occurrence of this string within <mark>
tags.
1 |
<h3> Search Results </h3> |
2 |
<p> They were interrupted, just after Quato said, <mark>"Open your Mind"</mark>. </p> |
20. When to Use a <div>
When HTML5 came out, many of us initially questioned when we should use plain-ole div
elements. Now that we have access to header
, article
, section
, and footer
tags, is there ever a time to use a div
? Absolutely.
div
s should be used when there's no better element for the job.
For example, if you find that you need to wrap a block of code within a wrapper element specifically for the purpose of positioning the content, a <div>
makes perfect sense. However, if you're instead wrapping a new blog post or a list of links in your footer, consider using the <article>
and <nav>
elements, respectively. They're more semantic.
21. The Data Attribute
We now officially have support for custom attributes within all HTML elements. Before, we could still get away with things like:
1 |
<h1 id=someId customAttribute=value> Thank you, Tony. </h1> |
But the validators would kick up a fuss! But now, as long as we preface our custom attribute with data
, we can officially use this method. If you've ever found yourself attaching important data to something like a class
attribute, probably for JavaScript usage, this will come as a big help!
HTML Snippet
1 |
<section class="text-data" data-slide-index="1"> |
2 |
<h2 data-slide-tip="Explanatory Text">Slide Title</h2> |
3 |
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> |
4 |
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> |
5 |
</section>
|
6 |
|
7 |
<p class="slide-index"></p> |
Retrieve the Value of the Custom Attribute
1 |
let slide_section = document.querySelector("section.text-data"); |
2 |
let slide_idx = slide_section.dataset.slideIndex; |
3 |
|
4 |
document.querySelector("p.slide-index").textContent = slide_idx; |
It can also be used in your CSS, as in this example that shows a simple tooltip:
1 |
h2 { |
2 |
cursor: pointer; |
3 |
} |
4 |
|
5 |
h2:hover:after { |
6 |
content: attr(data-slide-tip); |
7 |
color: black; |
8 |
margin-left: 1rem; |
9 |
background: black; |
10 |
color: white; |
11 |
padding: 0.5rem 1rem; |
12 |
font-size: 75%; |
13 |
} |
The following CodePen shows our CSS and JavaScript in action:
22. The output
Element
As you've probably guessed, the output
element is used to display some sort of calculation. For example, if you'd like to display the coordinates of the mouse cursor or the sum of a series of numbers, this data should be inserted into the output
element.
As a simple example, let's insert the total cost of all items into an empty output
with JavaScript, when the submit
button is pressed. We begin with the following HTML:
1 |
<form action="" method="get"> |
2 |
<label for="items">Total Items</label> |
3 |
<input id="items" name="items" placeholder="0"/> |
4 |
<br>
|
5 |
<label for="price">Item Price</label> |
6 |
<input id="price" name="price" placeholder="0"/> |
7 |
<p>Total Cost <output name="cost">0</output></p> |
8 |
<button type="submit">Calculate</button> |
9 |
</form>
|
Now, let's write some JavaScript that will get the value from our input elements and then calculate the total cost once we click the Calculate button.
1 |
let calcButton = document.querySelector("button"); |
2 |
|
3 |
let items_input = document.querySelector("input#items"); |
4 |
let price_input = document.querySelector("input#price"); |
5 |
|
6 |
let outputElem = document.querySelector("output"); |
7 |
|
8 |
calcButton.addEventListener("click", (event) => { |
9 |
let item_count = items.value; |
10 |
let price = price_input.value; |
11 |
|
12 |
let total_cost = item_count * price; |
13 |
|
14 |
outputElem.value = "$" + total_cost; |
15 |
|
16 |
event.preventDefault(); |
17 |
});
|
It's important to remember that the value of the output
element or its name or contents are not sent anywhere during form submission.
This element can also receive a for
attribute, which reflects the name of the element that the output
relates to, similar to the way that a label
works.
23. Create Sliders With the Range Input
HTML5 introduces the new range
type of input.
1 |
<input type="range"> |
Most notably, it can receive min
, max
, step
, and value
attributes, among others.
For a quick demonstration, let's build a gauge that will allow users to decide how awesome the movie Total Recall is. We won't build a real-world polling solution, but we'll review how it could be done quite easily.
Step 1: Markup
First, we create our markup.
1 |
<form method="post"> |
2 |
<h1> Total Recall Awesomeness Gauge </h1> |
3 |
<input type="range" name="range" min="0" max="10" step="1" value=""> |
4 |
<output name="result"> </output> |
5 |
</form>
|
Notice that, in addition to setting min
and max
values, we can always specify what the step
for each transition will be. If the step
is set to 1
, there will then be 10 values to choose. We also take advantage of the new output
element that we learned about in the previous tip.
Step 2: CSS
Next, we'll style it just a bit.
1 |
body { |
2 |
margin: 20px auto; |
3 |
font-family: system-ui; |
4 |
font-weight: 300; |
5 |
text-align: center; |
6 |
}
|
7 |
|
8 |
output { |
9 |
display: block; |
10 |
font-size: 5.5rem; |
11 |
font-weight: bold; |
12 |
}
|
Step 3: The JavaScript
Lastly, we:
- Update the
output
element dynamically as the user moves the slider. - Listen for when the user mouses off the slider, grab the value, and save it to local storage.
- Then, the next time the user refreshes the page, the range and output will automatically be set to what they last selected.
1 |
let formElem = document.forms[0], |
2 |
rangeElem = formElem["range"], |
3 |
resultElem = formElem["result"], |
4 |
cachedRangeValue = localStorage.rangeValue ? localStorage.rangeValue : 5; |
5 |
|
6 |
rangeElem.value = cachedRangeValue; |
7 |
resultElem.value = cachedRangeValue; |
8 |
|
9 |
rangeElem.addEventListener( |
10 |
"mouseup", |
11 |
function () { |
12 |
localStorage.rangeValue = rangeElem.value; |
13 |
},
|
14 |
false
|
15 |
);
|
16 |
|
17 |
rangeElem.addEventListener( |
18 |
"change", |
19 |
function () { |
20 |
resultElem.value = rangeElem.value; |
21 |
},
|
22 |
false
|
23 |
);
|
You can see the final result in the following CodePen demo:
24. The canvas
Element
The canvas
element is yet another interesting addition to HTML5. It allows you to draw graphics or animations by using either the canvas scripting API or the WebGL API. You can also specify a width or height for your canvas using the width
and height
attributes, which default to 300 and 150 pixels respectively. You can also change your canvas dimensions in CSS, but that can make the final result distorted.
Here is a simple script that draws around 8200 circles with a random radius value within our range:
1 |
const canvas = document.getElementById("canvas"); |
2 |
const ctx = canvas.getContext("2d"); |
3 |
|
4 |
for(let i = 1; i <= 200; i++) { |
5 |
for(let j = 0; j <= 40; j++) { |
6 |
let pos_x = Math.floor(Math.random() * 800); |
7 |
let radius = Math.floor(2 + Math.random() * 2); |
8 |
|
9 |
ctx.beginPath(); |
10 |
ctx.arc(pos_x, 10*j, radius, 0, 2 * Math.PI); |
11 |
ctx.stroke(); |
12 |
}
|
13 |
}
|
You can see the final result in the following CodePen demo:
Want to see what is possible with the HTML5 canvas? Read our post on 25 impressive HTML5 canvas experiments.
25. What Is Not HTML5
People can be forgiven for assuming that awesome JavaScript-less transitions are grouped into the all-encompassing HTML5. Even Apple has inadvertently promoted this idea. For non-developers, who cares—it's an easy way to refer to modern web standards. However, for us, though it may just be semantics, it's important to understand exactly what is not HTML5.
- SVG: Not HTML5. It's an older standard.
- CSS3: Not HTML5. It's... CSS.
- Geolocation: Not HTML5.
- Client Storage: Not HTML5. It was at one point, but it was removed from the spec because many worried that it, as a whole, was becoming too complicated. It now has its own specification.
- Web Sockets: Not HTML5. Again, it was exported to its own specification.
Regardless of how many distinctions you require, all of these technologies can be grouped into the modern web stack. In fact, many of these branched specifications are still managed by the same people.
Thanks for reading! We've covered a lot, but have still only scratched the surface of what's possible with HTML5. I hope this served as a helpful primer!
If you're looking for a quick way to get started, have a look at our HTML5 templates, as a quality theme from ThemeForest may be just what your next project needs.