HTML fundamentals

HTML fundamentals
HTML icon

Welcome to the HTML Fundamentals article, where we'll explore key HTML elements and concepts that form the foundation of web pages. Whether you're a seasoned developer or just starting your journey, this series aims to provide valuable insights into HTML, the markup language that structures the content of the World Wide Web.

Each chapter provides concise explanations, code snippets, and practical examples to empower you with a solid understanding of HTML fundamentals.

The head elements collectively describe the properties of the document (title, character set, stylesheets, scripts).

    <!-- Mandatory: the title should ideally be smaller than 65 chars  -->
    <!-- to be indexed properly by search engines  -->
    <title>My fantastic website</title>
    <!-- You can add more data about your website in meta tags that'll be -->
    <!-- used by browsers or search engines -->
    <meta charset="utf-8">
    <meta name="author" content="John Smith">
    <meta name="description" content="Presentation of different IoT projects built with Arduino"> 
    <!-- Viewport helps the rendering of your page on mobile devices. You  -->
    <!-- should ideally always have a viewport defined to avoid pinching -->
    <!-- and zooming to read its content. Here, the width is defined to be -->
    <!-- limited to the device-width, at 100% -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- You can define the base address for all relative -->
    <!-- links in the document -->
    <base href="">

    <!-- You can refer to CSS stylsheets -->
    <link rel="stylesheet" href="style.css">
    <!-- or embed styles -->
        body { background-color: YellowGreen; }
        h1 { color: red; }
        p { color: green; }

    <!-- You can refer to javascript files -->
    <script src="coloring-utils.js"></script>
    <!-- or embed javascript -->
    <!-- Note: Ideally, the script tags should be placed at the bottom -->
    <!-- of the html, in the 'body' section to speed up the rendering of the page -->
        document.write("<h1>Hello World!</h1>") 

Page layout

HTML5 introduced new tags to better structure a web page and no longer rely only on div tags:

  • <header>: header of a document or a section
  • <footer>: footer of a document or a section
  • <nav>: section with navigation links
  • <section>: represents a section of a document
  • <article>: self-contained unit of information (such as a blog post)
  • <aside>: content losely related to the page content (such as a section for ads)

Here is how these tags can be applied to a section or a document:

       |                       |
  Nav  |        Section        |  Aside
       |                       |
       |  -------------------- |--------
       |  |      Article     | |
       |  |                  | |
       |  -------------------- |

And here is an example of layout in HTML5:

<div class="container">
        <h1>Sports news</h1>
    <div class="wrapper">
                <li><a href="#">Home</a></li>
                <li><a href="#">Soccer</a></li>
                <li><a href="#">Basketball</a></li>
            <h2>Lakers failed again</h2>
            <p>The desire of success was not...</p>
        <p>copyright &copy; sports news</p>

Note that depending on how you want to wrap elements or how you want to style them, use div tags to create groups.

HTML Element types

There are two groups of elements:

  • block level: used to structure the page (div, p, h1-h6, form, ul, ol, ...). They start by a line break, end with a line break and expand on full width.
  • inline level: used to fill the content (img, a, span, strong, b, input, button ...). They are inserted in place and just take the required space.

Note that the default display type of an element can be overriden with css (display).

Empty elements

Some elements don't need closing tags. Here is an example with <br>

<p>This is <br> great</p>

Note that <br> is different than self-closing tags as it does not end with />. This if fine for HTML, only xHTML always requires />.


General purpose

Some attributes are valid for all HTML elements : id, title, class, style.

Boolean attributes

Several attributes do not consist of name/value pairs but just of a name, such as checked, disabled, readonly ... The shortened syntax is equivalent to checked="true" for instance.


h1 to h6.
Don't use them to display big or bold text. Instead, use them to structure your documents as search engines index the structure and the content of the pages.


Use <p>(paragraph) to publish text on a page. Note that any space or line breaks in the text written within <p> is not taken in consideration when rendering.

<p>The spaces     and line
    breaks      of this paragraph    won't show
    at rendering. Instead,   you'll  se a single line with no   spaces

You can combine <p> with the following tags to customize the output:

  • <br> : line break
  • <hr> : horizontal delimitation with a line between paragraphs
  • &nbsp;: special character (here non-breaking space)
<p>The spaces `&nbsp;&nbsp; and line <br> breaks of this paragraph</p>
<p>will show at rendering</p>

Alternatively, consider <pre> to render a text exactly like it's written:

<pre>The spaces     and line
    breaks      of this paragraph    will show
    at rendering.

Text formatting

<p>This is <b>bold text</b>.</p>
<p>This is <strong>strongly important text</strong>.</p>
<p>This is <i>italic text</i>.</p>
<p>This is <em>emphasized text</em>.</p>
<p>This is <mark>highlighted text</mark>.</p>
<p>This is <code>computer code</code>.</p>
<p>This is <small>smaller text</small>.</p>
<p>This is <sub>subscript</sub> and <sup>superscript</sup> text.</p>
<p>This is <del>deleted text</del>.</p>
<p>This is <ins>inserted text</ins>.</p>

<i> vs <em> and <b> vs <strong>

Both are used to format a text in italic or bold respectively. The only difference is that em emphasizes that its content is important while i is pure styling.
Same goes for b and strong where b is pure styling while strong stresses the importanced of its content.


Use <blockquote> to auto-indent a qutotation block that comes from other sources.

    <p>This text is an extract of an external resources</p>
    <cite>- M. Author</cite>

<cite> is used to describe a reference to a creative work. It must include the author name or the title of the work or eventually an URL.

Inline quotations can also be inserted by using <q>

<p>As once said by a wise man, <q>live your dreams</q></p>

Note that in this case, the text will simply be surrounded with double quotes ".


Not everyone knows all the abbreviations that you could use in your text. <abbr> solves this problem by attaching a description to an abbreviation that the user can see by hovering over it.

<p>The <abbr title="United Nations">UN</abbr> decided to not take action</p>

The abbreviation will have a dotted underline to catch user's attention.


HTML provides a special tag to encapsulate a contact information.

Nico Burger<br>
7 Brooklyn Avenue<br>


Images can be inserted with the inline and empty element <img>.

<p>A drawing made by an artist <img src="url" alt="Artistic drawing"></p>

alt provides an alternative text for the image if it cannot be displayed.

<img> lets you set the image dimensions with height and weight attributes but you can also assign those in the CSS stylesheet.


<img> comes with several limitations:

  • scaling the image to fit different devices is difficult
  • changing height and width attributes does not reduce the file size

HTML5 introduced a new tag <picture> to accomodate these limitations.

    <source media="(min-width: 1000px)" srcset="large.png">
    <source media="(min-width: 500px)" srcset="medium.png">
    <img src ="default.png" alt="Company">

<picture> works like a switch/case. The browser evaluates the best match among the specified source tags and uses the default <img> tag if none matches.
Note that the default <img> tag is mandatory.

Image maps

As often used on facebook, your image can contain clickable links on its surface. This is possible with <map>:

<img src="earth_landscape.png" usemap="#capitals" alt="Capitals on earth">
<map name="capitals">
    <area shape="circle" coords="127, 54, 654" href="paris.html" alt="Paris">
    <area shape="circle" coords="475, 99, 300, 147, 45, 98" href="beyrouth.html" alt="Beyrouth">

<img> references the map by its name. Each area inside the map defines a clickable link.

Since creating these maps manually is not convenient, you could consider using one of the numerous online tools.
Note that <map> is not search-engine-friendly.


Use tables to display tubular data only (never use them to build the layout of a page, they're slow to render and hard to maintain).
A <table> is made of rows <tr>, columns <td> and can eventually contain a caption caption and a header <th>.

    <caption>Users Info</caption>
        <th colspan="2">Phone</th>
        <td>John Carter</td>

In the example above, the header is horizontal (along a row) and we're making use of the colspan attribute to span the header Phone on 2 columns.
Here is another example with a vertical header and the use of rowspan to span the header on 2 rows:

        <td>John Carter</td>
        <th rowspan="2">Phone:</th>

Finally, not that HTML5 introduced additional tags to add more structure into a table woth <thead>, <tbody> and tfoot.




The displayed elements are marked with a bullet.



The displayed elements are marked with a number.

<ol start="5">
    <li>Open the box</li>
    <li>Replace the battery</li>
    <li>Close the box</li>

By default, start attribute equals 1 which the starting number for the ordering. However, you can set it to other values if needed.


A description list <dl> displays items <dt> with a definition or description <dd> for each. The descriptive text is usually automatically indented by browsers.

    <dd>A baked food made of flour.</dd>
    <dd>A drink made from roasted coffee beans.</dd>


Forms are used to collect user inputs and submit them.

<form name="uniqueName" action="url" method="post" target="_self">
    <label>Name: <input type="text"></label>
    <input type="submit" value="Submit">

<form> accepts several types of attributes:

  • name: name of the form. Must be unique in the document and not empty
  • action: url of program or script that will process the inputs
  • method: http verb used to send the data : post (default) or get (means that the data is visible in browser's address bar)
  • target: specifies where the response should be displayed (_blank, _self, _parent, _top)

A form can contain several type of controls depending on what it does.


Most commonly used element, the input can take different forms depending on its type attribute.

    <!-- Text field -->
    <!-- Note that label and input are separate here. 'for' and 'id' -->
    <!-- are used to join the two. The condensed syntax shown above is also possible -->
    <label for="user-name">Username:</label>
    <input type="text" name="username" id="user-name">

    <!-- Text area field -->
    <!-- The input here is multiline -->
    <label for="comment-area">Comment:</label>
    <textarea type="text" name="comment" id="comment-area"></textarea>

    <!-- Password field -->
    <!-- The input here is masked with dots -->
    <label for="user-pwd">Password:</label>
    <input type="password" name="user-password" id="user-pwd">

    <!-- Radio buttons field -->
    <!-- Note tha the 'name' is identical for each input to group them together. -->
    <!-- You can only select one item per group. -->
    <input type="radio" name="gender" id="male">
    <label for="male">Male</label>
    <input type="radio" name="gender" id="female">
    <label for="female">Female</label>
    <!-- Checkboxes field -->
    <!-- You can only select any item per group. -->
    <!-- Here, the attribute 'checked' sets the default state of a checkbox. -->
    <!-- Same attribute is valid for radio buttons -->
    <input type="checkbox" name="options" id="opt-dark" checked>
    <label for="opt-dark">Use dark mode</label>
    <input type="checkbox" name="options" id="opt-hour">
    <label for="opt-hour">Use 24h mode</label>

    <!-- File select field -->
    <!-- Renders a button that will open a file explorer -->
    <label for="file-select">Upload:</label>
    <input type="file" name="upload" id="file-select">

    <!-- Select boxes field -->
    <!-- Renders a combobox with different options -->
    <label for="city">City:</label>
    <select name="city" id="city">
        <option value="sydney">Sydney</option>
        <option value="melbourne">Melbourne</option>
        <option value="cromwell">Cromwell</option>

    <!-- Submit button -->
    <!-- Triggers the processing of submitted data -->
    <!-- Note that you can also use a 'button' here for more -->
    <!-- rendering options -->
    <input type="submit" value="Submit">
    <!-- Reset button -->
    <!-- Clears user inputs -->
    <input type="reset" value="Reset">

There are other inputs as well for colors, email, datetime, number, range, search, phone number, url ...


You can add more structure to your forms by grouping some inputs together in named panels with <fieldset> and legend.

        <label>Firstname: <input type="text" name="firstname"></label>            
        <label>Lastname: <input type="text" name="lastname"></label>
        <legend>Contact Details</legend>
        <label>Email Address: <input type="email" name="email"></label>
        <label>Phone Number: <input type="text" name="phone"></label>


<iframe> lets you display an external html page inside yours. It pretty much acts like a mini web browser within a web browser.

<iframe src="hello.html" width="400" height="200"></iframe>

Note: height and width can be expressed in % as well.

The iFrame can also be used to render a link accessed within the page thanks to target and name attributes.

<iframe src="weather.html" name="weatherFrame"></iframe>
<p><a href="" target="weatherFrame">Show weather in Paris</a></p>

The external link will be rendered inside of the iFrame.


HTML5 only.

The canvas is a two-dimensional rectangular area that can be used to draw graphics on the webpage via Javascript.

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Drawing on Canvas</title>
    window.onload = function() {
        var canvas = document.getElementById("myCanvas");
        var context = canvas.getContext("2d");
        // draw a line
        context.moveTo(50, 150);
        context.lineTo(250, 50);
    <canvas id="myCanvas" width="300" height="200"></canvas>

You can draw many shapes and colors in a canvas. The content of a canvas can be saved into a file.


HTML5 only.

An SVG is an XML-based image format that can be scaled without any loss of quality. The SVG also supports animations and can be edited dynamically with Javascript.

<svg width="300" height="200">
    <!-- Example of a line-->
    <line x1="50" y1="50" x2="250" y2="150" style="stroke:red; stroke-width:3;" />
    <!-- Example of a rectangle-->
    <rect x="50" y="50" width="200" height="100" style="fill:orange; stroke:black; stroke-width:3;" />
    <!-- Example of a circle -->
    <circle cx="150" cy="100" r="70" style="fill:lime; stroke:black; stroke-width:3;" />
    <!-- Example of text -->
    <text x="20" y="30" style="fill:purple; font-size:22px;">
        Welcome to Our Website!


HTML5 only.

<audio> element lets you embed sound in web pages.

<audio controls="controls">
    <!-- You can defined many sources for the same sound -->
    <!-- and the browser will pick the first it supports -->
    <source src="media/birds.mp3" type="audio/mpeg">
    <source src="media/birds.ogg" type="audio/ogg">


HTML5 only.

<audio> element lets you embed videos in web pages.

<video controls="controls">
    <!-- You can defined many sources for the same video -->
    <!-- and the browser will pick the first it supports -->
    <source src="media/shuttle.mp4" type="video/mp4">
    <source src="media/shuttle.ogv" type="video/ogg">

Web storage

HTML5 only.

HTML5's we storage provides you with a solution to store 5MB of data locally on computer whereas a cookie was only capable of storing 4KB and had the inconvenient of being transferred on each request.

There are 2 types of storages with different scope and lifetime as explained below.

Local storage

Stores data permanently for an entire website.

// Store data
localStorage.setItem("first_name", "Peter");
// Retrieve data
console.log("Hi, " + localStorage.getItem("first_name"));

Session storage

Stores data temporarily for a single browser tab and deletes the data when the browser or tab is closed.

// Store data
sessionStorage.setItem("first_name", "Peter");
// Retrieve data
console.log("Hi, " + sessionStorage.getItem("first_name"));

Application cache

HTML5 only.

Caching helps with performances as your browser will store some of the resources accessed for a web page and load them back from storage instead of requesting them againg from the server. In HTML5, a caching manifest can be specified on server side to tell the browser what to cache:

# v1.0 : 10-08-2014
# All the items under CACHE: will be cached
# pages
# styles & scripts
# images
# All the items under CACHE: will not be cached
# meaning that the access to login.php is only
# possible if the user is online

# Fallback URIs. The index of the page will be redirected
# to offline.html when the user is offline
/ /offline.html

The cache manifest needs to be indicated in the html element:

<!DOCTYPE html>
<html lang="en" manifest="mywebsite.appcache">

Web workers

HTML5 only.

The execution of javascript in the web browser is single threaded by default, meaning that any pending execution will prevent the user from interacting with the page.
For intensive computations that can be executed in background, HTML5 has introduced web workers to keep the page responsive.

To use this feature, you must first create a javascript file which will contain the code to be executed in background. Note that this code cannot access the DOM.

// worker.js

var i = 0;
function countNumbers() {
    if(i < 100000) {
        i = i + 1;
    // Wait for sometime before running this script again
    setTimeout("countNumbers()", 500);

Now from the web page, you can control the execution of the worker and/or consume its result as shown below:

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Using Web Worker</title>
    // You can control the execution from the web page
    // Here is how you can start the execution
    function startWorker() {
        // Create a new web worker
        var worker = new Worker("worker.js");
        // Everytime the worker calls postMessage, this function will be executed
        worker.onmessage = function(event) {
            document.getElementById("result").innerHTML =;

    // Here is how you can stop the execution
    function stopWorker() {
    <h1>Web Worker Demo</h1>
    <button type="button" onclick="startWorker();">Start web worker</button>
    <button type="button" onclick="stopWorker();">Stop web worker</button>
    <div id="result">
        <!--Received messages will be inserted here-->

Server sent events

HTML5 only.

When a client communicates with a server, the connection is closed after receiving the response which is sufficient most of the time but does not cover the situations where data needs to be streamed.

In HTML5, a web page can hold a connection open so that the web server can send new responses automatically at any time. Server-Side Events (or SSE) are unidirectional responses delivered from server to client.

// server_time.php

// On server side we set the content-type to text/event-stream 
// to enable SSE
header("Content-Type: text/event-stream");
// We disable caching to prevent the browser from storing the data
header("Cache-Control: no-cache");
// Get the current time on server
$currentTime = date("h:i:s", time());
// Send it in a message
// The SSE sent by the server must start with 'data:'
echo "data: " . $currentTime . "\n\n";

On client side, we simply attach an event handler to the EventSource object.

<!DOCTYPE html>
<html lang="en">
<title>Using Server-Sent Events</title>
    window.onload = function() {
        var source = new EventSource("server_time.php");
        source.onmessage = function(event) {
            document.getElementById("result").innerHTML += "New time received from web server: " + + "<br>";
    <div id="result">
        <!--Server response will be inserted here-->