Lesson 18 of 20

HTML5 New Elements

What HTML5 Changed

HTML5 is worth understanding as a response to a problem. By the mid-2000s, the web was being asked to do things HTML could not: play video, draw graphics, validate forms, store data. Every one of those gaps was filled by a browser plugin, and Flash in particular. Plugins had to be installed, they were a constant source of security holes, they did not work on phones, and they were controlled by a single company rather than by an open standard.

HTML5's answer was to bring those capabilities into HTML itself. Video and audio became elements. Drawing became <canvas>. Form validation became attributes. Structure became the semantic elements you met earlier in this course. Nothing needed installing, everything worked on a phone, and the whole thing was a public standard.

One practical note before the details: "HTML5" is no longer a version you target. The specification became a living standard that gains features continuously, so there will be no HTML6. When someone says an element is "HTML5", they mean it arrived in that wave of work rather than in the original language.

  • <video> and <audio> — media without a plugin
  • <canvas> and inline <svg> — graphics drawn by script or described as shapes
  • <details> and <summary> — collapsible content with no JavaScript at all
  • <progress> and <meter> — task progress and scalar measurements
  • <dialog> — a real modal dialog with focus handling built in
  • New input types and validation attributes, covered in the forms lessons
  • The semantic structure elements — <header>, <nav>, <main>, <article>, <footer>

video and audio

<video> and <audio> work the same way. Give either the controls attribute and the browser supplies a play button, a timeline and a volume control. You can point at a file with src, or list several <source> children in different formats and let the browser pick the first one it can play.

Several attributes are worth knowing because each solves a real problem. poster sets the still image shown before playback starts, which stops your video appearing as a black rectangle. preload="none" tells the browser not to download the file until the visitor asks for it, which matters enormously on mobile data. muted, loop and playsinline are the combination used for short background clips.

One behaviour surprises everyone: autoplay on its own usually does nothing. Browsers block video that starts playing with sound, because it was so widely abused. A video will normally autoplay only if it is also muted. That is a deliberate policy, not something you can attribute your way around, and it is a good argument for not autoplaying video at all.

The most important attribute is one people skip. <track kind="captions"> attaches a caption file, and captions are what make your video usable by a deaf viewer — and by everyone watching without sound in a noisy room or a quiet library, which is most viewers on a phone. Hosting a video with no captions excludes people for the sake of a text file.

Example
<video controls
       width="640"
       poster="images/robot-video-poster.jpg"
       preload="none">

  <source src="media/build-walkthrough.webm" type="video/webm">
  <source src="media/build-walkthrough.mp4" type="video/mp4">

  <track kind="captions"
         src="media/build-walkthrough-en.vtt"
         srclang="en"
         label="English"
         default>

  <p>Your browser cannot play this video.
     <a href="media/build-walkthrough.mp4">Download it instead</a>.</p>
</video>

<audio controls src="media/interview.mp3">
  <p>Your browser cannot play this audio file.</p>
</audio>

<!-- Silent background clip: muted is what makes autoplay work at all -->
<video autoplay muted loop playsinline src="media/loop.mp4"></video>
Notes
  • Video files are large. A three-minute clip can easily be fifty megabytes, which is a slow and expensive download on mobile data. For anything more than a short clip, hosting it on a video service and embedding it with an iframe is usually the better choice — that service handles compression, multiple resolutions and streaming for you.

details and summary: An Accordion With No JavaScript

<details> creates a block that is collapsed by default and expands when clicked. <summary>, which must be its first child, is the visible line that stays put and acts as the toggle. That is the entire API — no JavaScript, no library, no state to manage.

What you get for free is the part that is genuinely hard to build yourself. The summary is focusable with the keyboard and can be activated with Enter or Space. A screen reader announces it as expandable and reports whether it is currently open. The collapsed state is handled by the browser. A hand-built accordion made of divs and click handlers has to reproduce all of that, and most attempts miss at least half.

Add the boolean open attribute to have a section start expanded — useful for the first item in a list of questions. Several <details> elements in a row behave independently, which is what you usually want; giving them all the same name attribute makes them behave as an exclusive group where opening one closes the others, though browser support for that is newer than the rest.

This is the right element for frequently-asked-questions blocks, optional detail in a long form, and "show the full specification" toggles. It is not a substitute for good structure: burying essential information behind a click means many visitors never see it.

Example
<h2>Frequently Asked Questions</h2>

<details open>
  <summary>Who can join the club?</summary>
  <p>Any student from any branch and any year. No prior electronics
     experience is needed — most members start with none.</p>
</details>

<details>
  <summary>Do I need to bring my own laptop?</summary>
  <p>For coding sessions, yes. Hardware and components are provided
     by the lab.</p>
</details>

<details>
  <summary>Is there a membership fee?</summary>
  <p>There is a one-time fee of Rs 200 that covers consumables
     for the whole year.</p>
</details>

/* The default triangle marker can be restyled */
summary {
  cursor: pointer;
  font-weight: 600;
  padding: 10px 0;
}
Notes
  • <summary> must be the first child of <details>. If you leave it out entirely, browsers show a default label such as "Details", which is never what you wanted.

progress and meter Are Not the Same Thing

These two look almost identical on screen and are constantly used interchangeably, so it is worth being clear. <progress> represents how far along a task is — a file upload, a multi-step form, a download. It only makes sense while something is happening, and it moves in one direction towards completion.

<meter> represents a measurement within a known range that is not going anywhere — disk space used, a score out of a hundred, today's temperature against the expected range. Nothing is in progress; you are simply showing where a value sits between a minimum and a maximum.

<meter> also understands whether a value is good or bad. The low, high and optimum attributes tell the browser which parts of the range are favourable, and browsers colour the bar accordingly — green in the good region, amber or red outside it. <progress> has no such concept, because progress is progress.

Both need a label, because a bar on its own is meaningless to anyone who cannot see it, and neither element announces a number by itself. Put the value in the text next to it, or associate a <label>. A <progress> with no value at all is a special case: it renders as an indeterminate animation, which is the correct way to say "something is happening but we do not know how long it will take".

Example
<!-- A task in progress -->
<label for="upload">Uploading your project photos</label>
<progress id="upload" value="64" max="100">64%</progress>
<span>64%</span>

<!-- Unknown duration -->
<progress></progress>

<!-- A measurement in a range, with good and bad regions -->
<label for="storage">Lab server storage used</label>
<meter id="storage"
       value="0.82"
       min="0" max="1"
       low="0.5" high="0.8" optimum="0.2">82%</meter>
<span>82% of 500 GB</span>

<!-- A score out of a fixed total -->
<label for="score">Quiz score</label>
<meter id="score" value="37" min="0" max="50">37 out of 50</meter>
Notes
  • The text between the opening and closing tags of <progress> and <meter> is a fallback for very old browsers and is not shown today. Do not treat it as the accessible name — that is what the label and the visible number are for.

canvas, svg and dialog

<canvas> gives you a blank rectangle of pixels that JavaScript draws on, instruction by instruction. It is how browser games, image editors and some charting libraries work. The important consequence is that a canvas has no content — once something is drawn, it is just coloured pixels, invisible to a screen reader and unsearchable. Anything on a canvas that carries meaning must also be described in real HTML nearby.

<svg> takes the opposite approach: you describe shapes as markup, and the browser draws them. Because the shapes are elements, they can be styled with CSS, animated, given a <title> that screen readers announce, and scaled to any size without blurring. For logos, icons, diagrams and most charts, inline SVG is the better choice; reach for canvas when you need to redraw thousands of things many times a second.

<dialog> is a proper modal dialog box. Opened with showModal() from JavaScript, it moves keyboard focus inside itself, traps Tab so focus cannot wander behind it, closes on the Escape key, and dims the rest of the page. Those behaviours are exactly what hand-built modals get wrong, so it is worth using the real element.

Example
<!-- Canvas: pixels only, so describe the meaning in HTML as well -->
<canvas id="chart" width="400" height="300">
  Attendance rose steadily from 12 members in January to 41 in June.
</canvas>

<!-- SVG: real elements, styleable and describable -->
<svg width="120" height="120" viewBox="0 0 120 120" role="img"
     aria-labelledby="logo-title">
  <title id="logo-title">Robotics Club logo</title>
  <circle cx="60" cy="60" r="50" fill="#7a0060" />
  <rect x="40" y="40" width="40" height="40" fill="#ffffff" />
</svg>

<!-- A real modal dialog -->
<dialog id="confirm">
  <h2>Confirm your entry</h2>
  <p>Your team will be registered for the Robotics Challenge.</p>
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="confirm">Confirm</button>
  </form>
</dialog>

<button type="button" onclick="document.getElementById('confirm').showModal()">
  Register
</button>
HTML5 Elements With No JavaScript
HTML
<h2>Robotics Club — Member Dashboard</h2>

<h3>Frequently Asked Questions</h3>

<details open>
  <summary>Who can join the club?</summary>
  <p>Any student from any branch and any year. Most members start
     with no electronics experience at all.</p>
</details>

<details>
  <summary>Do I need my own laptop?</summary>
  <p>For coding sessions, yes. Components and tools are provided.</p>
</details>

<details>
  <summary>Is there a fee?</summary>
  <p>A one-time fee of Rs 200 covers consumables for the year.</p>
</details>

<h3>This semester</h3>

<p>
  <label for="build">Project build completion</label><br>
  <progress id="build" value="64" max="100">64%</progress>
  <strong>64%</strong>
</p>

<p>
  <label for="storage">Lab server storage used</label><br>
  <meter id="storage" value="0.82" min="0" max="1"
         low="0.5" high="0.8" optimum="0.2">82%</meter>
  <strong>82% of 500 GB</strong>
</p>

<p>
  <label for="score">Safety quiz score</label><br>
  <meter id="score" value="44" min="0" max="50">44 out of 50</meter>
  <strong>44 / 50</strong>
</p>

<h3>Club logo (inline SVG)</h3>
<svg width="100" height="100" viewBox="0 0 120 120" role="img"
     aria-labelledby="logo-title">
  <title id="logo-title">Robotics Club logo</title>
  <circle cx="60" cy="60" r="50" fill="#7a0060" />
  <rect x="42" y="42" width="36" height="36" fill="#ffffff" rx="6" />
</svg>

<p><small>Open and close the questions using only the Tab and Enter keys —
   all of that behaviour is built into &lt;details&gt;.</small></p>
CSS
body {
  font-family: system-ui, Arial, sans-serif;
  line-height: 1.6;
  padding: 24px;
  max-width: 560px;
}
details {
  border: 1px solid #e2e2e6;
  border-radius: 8px;
  padding: 8px 14px;
  margin-bottom: 10px;
}
details[open] {
  background: #faf6f9;
}
summary {
  cursor: pointer;
  font-weight: 600;
  padding: 6px 0;
}
label {
  font-size: 0.9rem;
  color: #555;
}
progress, meter {
  width: 260px;
  height: 18px;
  vertical-align: middle;
}
Notes
  • Try the example with the keyboard alone. Tab moves between the three questions, Enter or Space opens and closes each one, and a screen reader would announce whether each is expanded — none of which you had to write. That is the argument for using the real element instead of building your own.
Ask AI