Introduction to HTML

Getting started with HTML

What is HTML?

HTML (Hypertext Markup Language) is not a programming language; it is a markup language used to tell your browser how to structure the web pages you visit.

HTML consists of a series of elements, an element may contain a data item or a chunk of text or an image, or perhaps nothing. A typical element includes an opening tag with some attributes, enclosed text content, and a closing tag.

In HTML a tag is used for creating an element. The name of an HTML element is the name used in angle brackets such as <p> for paragraph. Note that the end tag’s name is preceded by a slash character, </p>.

If attributes are not mentioned, default values are used in each case.

element

Elements can be placed within other elements too — this is called nesting.

Block versus inline elements

There are two important categories of elements in HTML which you should know about. They are block-level elements and inline elements.

  • Block-level elements form a visible block on a page — they will appear on a new line from whatever content went before it, and any content that goes after it will also appear on a new line. Block-level elements tend to be structural elements on the page that represent, for example, paragraphs, lists, navigation menus, footers, and so on. A block-level element wouldn’t be nested inside an inline element, but it might be nested inside another block-level element.
  • Inline elements are those that are contained within block-level elements and surround only small parts of the document’s content, not entire paragraphs and groupings of content. An inline element will not cause a new line to appear in the document; they would normally appear inside a paragraph of text, for example an <a> element (hyperlink) or emphasis elements such as <em> or <strong>.

The terms “block” and “inline”, as used in this topic, should not be confused with the types of CSS boxes with the same names. While they correlate by default, changing the CSS display type doesn’t change the category of the element and doesn’t affect which elements it can contain and which elements it can be contained in.

Empty elements

Not all elements follow the above pattern of an opening tag, content, and a closing tag. Some elements consist only of a single tag, which is usually used to insert/embed something in the document at the place it is included.

Attributes

Attributes contain extra information about the element that you don’t want to appear in the actual content. In this case, the class attribute allows you to give the element an identifying name, that can be used later to target the element with style information and other things.

Boolean attributes

You’ll sometimes see attributes written without values — this is perfectly allowed. These are called Boolean attributes, and they can only have one value, which is generally the same as the attribute name.

1
2
<input type="text" disabled>
<input type="text" disabled="disabled">

Anatomy of an HTML document

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My test page</title>
  </head>
  <body>
    <p>This is my page</p>
  </body>
</html>
  1. <!DOCTYPE html>: The doctype, just a historical artifact that needs to be included for everything to work right.
  2. <html></html> : The <html> element. This element wraps all the content on the entire page, and is sometimes known as the root element.
  3. <head></head>: The <head> element. This element acts as a container for all the stuff you want to include on the HTML page.
  4. <meta charset="utf-8">:This element specifies the character set for your document to UTF-8.
  5. <title></title>: The <title> element. This sets the title of your page
  6. <body></body>: The <body> element. This contains all the content that you want to show to web users when they visit your page.

In HTML, the characters <, >,",' and & are special characters. They are parts of the HTML syntax itself.

Literal character Character reference equivalent
< &lt;
> &gt;
" &quot;
' &apos;
& &amp;

The character reference equivalent could be easily remembered because the words it uses can be seen as less than for ‘<’ , quotation for ’ " ’ and similarly for each. Do checkout the link to the wikipedia page to find more about the available HTML character entity reference.

1
2
3
<p>In HTML, you define a paragraph using the <p> element.</p>  <!-- wrong -->

<p>In HTML, you define a paragraph using the &lt;p&gt; element.</p>  

HTML comments

To turn a section of HTML content into a comment, you need to wrap it in the special markers <!-- and -->

What’s in the head? Metadata in HTML

The head’s content is not displayed on the page. Instead, the head’s job is to contain metadata about the document.

title

We’ve already seen the <title> element in action — this can be used to add a title to the document. This however can get confused with the <h1> element, which is used to add a top level heading to your body content — this is also sometimes referred to as the page title. But they are different things!

  • The <h1> element appears on the page when loaded in the browser — generally this should be used once per page, to mark up the title of your page content (the story title, or news headline, or whatever is appropriate to your usage.)
  • The <title> element is metadata that represents the title of the overall HTML document (not the document’s content.)

Metadata: the <meta> element

Specifying your document’s character encoding
1
<meta charset="utf-8">
Adding an author and description
1
2
<meta name="author" content="">
<meta name="description" content="">

The description is also used on search engine result pages.

Specifying a description that includes keywords relating to the content of your page is useful as it has the potential to make your page appear higher in relevant searches performed in search engines

Other types of metadata

As you travel around the web, you’ll find other types of metadata, too. A lot of the features you’ll see on websites are proprietary creations, designed to provide certain sites (such as social networking sites) with specific pieces of information they can use.

Adding custom icons to your site

The humble favicon has been around for many years. It is the first icon of this type: a 16-pixel square icon used in multiple places. You may see (depending on the browser) favicons displayed in the browser tab containing each open page, and next to bookmarked pages in the bookmarks panel.

A favicon can be added to your page by:

  1. Saving it in the same directory as the site’s index page, saved in .ico format (most browsers will support favicons in more common formats like .gif or .png, but using the ICO format will ensure it works as far back as Internet Explorer 6.)

  2. Adding the following line into your HTML’s <head> block to reference it:

    1
    
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
    

Applying CSS and JavaScript to HTML

The <link> element always goes inside the head of your document. This takes two attributes, rel="stylesheet", which indicates that it is the document’s stylesheet, and href, which contains the path to the stylesheet file:

1
<link rel="stylesheet" href="my-css-file.css">

The <script> element does not have to go in the head; in fact, often it is better to put it at the bottom of the document body (just before the closing </body> tag), to make sure that all the HTML content has been read by the browser before it tries to apply JavaScript to it (if JavaScript tries to access an element that doesn’t yet exist, the browser will throw an error.)

1
<script src="my-js-file.js"></script>

Note: The <script> element may look like an empty element, but it’s not, and so needs a closing tag. Instead of pointing to an external script file, you can also choose to put your script inside the <script> element.

Setting the primary language of the document

It’s worth mentioning that you can (and really should) set the language of your page.

1
<html lang="en-US">

You can also set subsections of your document to be recognised as different languages.

1
<p>Japanese example: <span lang="ja">ご飯が熱い。</span>.</p>

HTML text fundamentals

Why do we need semantics?

One of HTML’s main jobs is to give text structure and meaning (also known as semantics) so that a browser can display it correctly. HTML provides various semantic elements to allow us to mark up textual content with

Semantics are relied on everywhere around us — we rely on previous experience to tell us what the function of an everyday object is; when we see something, we know what its function will be. So, for example, we expect a red traffic light to mean “stop”, and a green traffic light to mean “go”.

In a similar vein, we need to make sure we are using the correct elements, giving our content the correct meaning, function, or appearance.

Headings and Paragraphs

In HTML, each paragraph has to be wrapped in a <p> element

Each heading has to be wrapped in a heading element.

There are six heading elements — <h1>, <h2>, <h3>, <h4>, <h5>, and <h6>. Each element represents a different level of content in the document. Its semantic value will be used in multiple ways, for example by search engines and screen readers. The <span> element has no semantics.

Lists

Unordered
1
2
3
4
<ul>
  <li>milk</li>
  <li>eggs</li>
</ul>
Ordered
1
2
3
4
<ol>
  <li>Drive to the end of the road</li>
  <li>Turn right</li>
</ol>
Nesting lists
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<ol>
  <li>Remove the skin from the garlic, and chop coarsely.</li>
  <li>Remove all the seeds and stalk from the pepper, and chop coarsely.</li>
  <li>Add all the ingredients into a food processor.</li>
  <li>Process all the ingredients into a paste.
    <ul>
      <li>If you want a coarse "chunky" hummus, process it for a short time.</li>
      <li>If you want a smooth hummus, process it for a longer time.</li>
    </ul>
  </li>
</ol>

Emphasis and importance

Emphasis

When we want to add emphasis in spoken language, we stress certain words, subtly altering the meaning of what we are saying. Similarly, in written language we tend to stress words by putting them in italics. In HTML we use the <em> (emphasis) element to mark up such instances.

Browsers style this as italic by default, but you shouldn’t use this tag purely to get italic styling. To do that, you’d use a <span> element and some CSS, or perhaps an <i> element

1
<p>I am <em>glad</em> you weren't <em>late</em>.</p>
Strong importance

To emphasize important words, we tend to stress them in spoken language and bold them in written language. In HTML we use the <strong> (strong importance) element to mark up such instances.

Italic, bold, underline…

Here’s the best rule of thumb: it’s likely appropriate to use <b>, <i>, or <u> to convey a meaning traditionally conveyed with bold, italics, or underline, provided there is no more suitable element.

A basic link is created by wrapping the text (or other content) you want to turn into a link inside an <a> element, and giving it an href attribute that will contain the web address you want the link to point to.

Adding supporting information with the title attribute
1
2
3
4
5
<p>I'm creating a link to
<a href="https://www.mozilla.org/en-US/"
   title="The best place to find more information about Mozilla's
          mission and how to contribute">the Mozilla homepage</a>.
</p>

This gives us the following result (the title will come up as a tooltip when the link is hovered over):

1
2
3
<a href="https://www.mozilla.org/en-US/">
  <img src="mozilla-image.png" alt="mozilla logo that links to the mozilla homepage">
</a>

A quick primer on URLs and paths

A URL, or Uniform Resource Locator is simply a string of text that defines where something is located on the Web. URLs use paths to find files. Paths specify where in the filesystem the file you are interested in is located.

Document fragments

It is possible to link to a specific part of an HTML document (known as a document fragment), rather than just to the top of the document. To do this you first have to assign an id attribute to the element you want to link to.

1
<h2 id="Mailing_address">Mailing address</h2>

Then to link to that specific id, you’d include it at the end of the URL, preceded by a hash/pound symbol

1
<p>Want to write us a letter? Use our <a href="contacts.html#Mailing_address">mailing address</a>.</p>

You can even use the document fragment reference on its own to link to another part of the same document:

1
<p>The <a href="#Mailing_address">company mailing address</a> can be found at the bottom of this page.</p>
Absolute versus relative URLs

absolute URL: Points to a location defined by its absolute location on the web, including protocol and domain name. just http://www.example.com/projects/, as most web servers just look for a landing page such as index.html to load if it is not specified in the URL.

relative URL: A relative URL will point to different places depending on the actual location of the file you refer from.

  • Use clear link wording

  • Use relative links wherever possible

    With a relative URL on the other hand, the browser just looks up the file that is being requested, on the same server, will not by looking up the real location of the server on the Domain Name System

  • Linking to non-HTML resources — leave clear signposts

  • Use the download attribute when linking to a download

    When you are linking to a resource that is to be downloaded rather than opened in the browser, you can use the download attribute to provide a default save filename.

    1
    2
    3
    4
    
    <a href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=en-US"
       download="firefox-latest-64bit-installer.exe">
      Download Latest Firefox for Windows (64-bit) (English, US)
    </a>
    

It is possible to create links or buttons that, when clicked, open a new outgoing email message rather than linking to a resource or page. This is done using the `` element and the mailto: URL scheme.

In its most basic and commonly used form, a mailto: link simply indicates the email address of the intended recipient.

1
<a href="mailto:nowhere@mozilla.org">Send email to nowhere</a>

In fact, the email address is even optional. If you leave it out (that is, your href is simply “mailto:”), a new outgoing email window will be opened by the user’s mail client that has no destination address specified yet. This is often useful as “Share” links that users can click to send an email to an address of their choosing.

Specifying details

In addition to the email address, you can provide other information. In fact, any standard mail header fields can be added to the mailto URL you provide. The most commonly used of these are “subject”, “cc”, and “body” (which is not a true header field, but allows you to specify a short content message for the new email). Each field and its value is specified as a query term.

1
2
3
<a href="mailto:nowhere@mozilla.org?cc=name2@rapidtables.com&bcc=name3@rapidtables.com&subject=The%20subject%20of%20the%20email&body=The%20body%20of%20the%20email">
  Send mail with cc, bcc, subject and body
</a>

The values of each field must be URL-encoded, that is with non-printing characters (invisible characters like tabs, carriage returns, and page breaks) and spaces percent-escaped. Also note the use of the question mark (?) to separate the main URL from the field values, and ampersands (&) to separate each field in the mailto: URL.

Advanced text formatting

Description lists

Description lists use a different wrapper than the other list types — <dl>; in addition each term is wrapped in a <dt> (description term) element, and each description is wrapped in a <dd> (description definition) element.

Note that it is permitted to have a single term with multiple descriptions.

1
2
3
4
5
6
7
8
<dl>
  <dt>soliloquy</dt>
  <dd>description text</dd>
  <dt>monologue</dt>
  <dd>description text</dd>
  <dt>aside</dt>
  <dd>description text</dd>
</dl>

Quotations

HTML also has features available for marking up quotations; which element you use depends on whether you are marking up a block or inline quotation.

Blockquotes

If a section of block level content (be it a paragraph, multiple paragraphs, a list, etc.) is quoted from somewhere else, you should wrap it inside a <blockquote> element to signify this, and include a URL pointing to the source of the quote inside a cite attribute.

1
2
3
4
<blockquote cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote">
  <p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block
  Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p>
</blockquote>
Inline quotations

Inline quotations work in exactly the same way, except that they use the <q> element.

1
2
<p>The quote element — <code>&lt;q&gt;</code> — is <q cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q">intended
for short quotations that don't require paragraph breaks.</q></p>

Browser default styling will render this as normal text put in quotes to indicate a quotation.

Citations

The content of the cite attribute sounds useful, but unfortunately browsers don’t really display the contents of cite. There is a <cite> element, but this is meant to contain the title of the resource being quoted, e.g. the name of the book.

1
<p>Hello and welcome to my motivation page. As <a href="http://www.brainyquote.com/quotes/authors/c/confucius.html"><cite>Confucius' quotes site</cite></a> says:</p>

Abbreviations

Another fairly common element you’ll meet when looking around the Web is <abbr> — this is used to wrap around an abbreviation or acronym, and provide a full expansion of the term (included inside a title attribute.)

1
<p>We use <abbr title="Hypertext Markup Language">HTML</abbr> to structure our web documents.</p>

Marking up contact details

HTML has an element for marking up contact details. This simply wraps around your contact details

1
2
3
<address>
  <p>Chris Mills, Manchester, The Grim North, UK</p>
</address>

Superscript and subscript

You will occasionally need to use superscript and subscript when marking up items like dates, chemical formulae, and mathematical equations so they have the correct meaning. The <sup> and <sub> elements handle this job.

Caffeine's chemical formula is C8H10N4O2.

#### Representing computer code

There are a number of elements available for marking up computer code using HTML:

  • <code>: For marking up generic pieces of computer code.
  • <pre>: For retaining whitespace (generally code blocks) — if you use indentation or excess whitespace inside your text, browsers will ignore it and you will not see it on your rendered page. If you wrap the text in <pre></pre> tags however, your whitespace will be rendered identically to how you see it in your text editor.
  • <var>: For specifically marking up variable names.
  • <kbd>: For marking up keyboard (and other types of) input entered into the computer.
  • <samp>: For marking up the output of a computer program.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<pre><code>var para = document.querySelector('p');

para.onclick = function() {
  alert('Owww, stop poking me!');
}</code></pre>

<p>You shouldn't use presentational elements like <code>&lt;font&gt;</code> and <code>&lt;center&gt;</code>.</p>

<p>In the above JavaScript example, <var>para</var> represents a paragraph element.</p>


<p>Select all the text with <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>A</kbd>.</p>

<pre>$ <kbd>ping mozilla.org</kbd>
<samp>PING mozilla.org (63.245.215.20): 56 data bytes
64 bytes from 63.245.215.20: icmp_seq=0 ttl=40 time=158.233 ms</samp></pre>

Marking up times and dates

HTML also provides the <time> element for marking up times and dates in a machine-readable format.

1
<time datetime="2016-01-20">20 January 2016</time>

Document and website structure

we need to respect semantics and use the right element for the right job.

To implement such semantic mark up, HTML provides dedicated tags that you can use to represent such sections, for example:

  • header: <header>.
  • navigation bar: <nav>.
  • main content: <main>, with various content subsections represented by <article>, <section>, and <div> elements.
  • sidebar: <aside>; often placed inside <main>.
  • footer: <footer>.

It’s good to understand the overall meaning of all the HTML sectioning elements in detail:

  • <main> is for content unique to this page. Use <main> only once per page, and put it directly inside <body>. Ideally this shouldn’t be nested within other elements.
  • <article> encloses a block of related content that makes sense on its own without the rest of the page (e.g., a single blog post).
  • <section> is similar to <article>, but it is more for grouping together a single part of the page that constitutes one single piece of functionality (e.g., a mini map, or a set of article headlines and summaries). It’s considered best practice to begin each section with a heading; also note that you can break <article>s up into different <section>s, or <section>s up into different <article>s, depending on the context.
  • <aside> contains content that is not directly related to the main content but can provide additional information indirectly related to it (glossary entries, author biography, related links, etc.).
  • <header> represents a group of introductory content. If it is a child of <body> it defines the global header of a webpage, but if it’s a child of an <article> or <section> it defines a specific header for that section (try not to confuse this with titles and headings).
  • <nav> contains the main navigation functionality for the page. Secondary links, etc., would not go in the navigation. <footer> represents a group of end content for a page.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">

    <title>My page title</title>
    <link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Sonsie+One" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="style.css">

    <!-- the below three lines are a fix to get HTML5 semantic elements working in old versions of Internet Explorer-->
    <!--[if lt IE 9]>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
    <![endif]-->
  </head>

  <body>
    <!-- Here is our main header that is used across all the pages of our website -->

    <header>
      <h1>Header</h1>
    </header>

    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">Our team</a></li>
        <li><a href="#">Projects</a></li>
        <li><a href="#">Contact</a></li>
      </ul>

       <!-- A Search form is another commmon non-linear way to navigate through a website. -->

       <form>
         <input type="search" name="q" placeholder="Search query">
         <input type="submit" value="Go!">
       </form>
     </nav>

    <!-- Here is our page's main content -->
    <main>

      <!-- It contains an article -->
      <article>
        <h2>Article heading</h2>

        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Donec a diam lectus. Set sit amet ipsum mauris. Maecenas congue ligula as quam viverra nec consectetur ant hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.</p>

        <h3>Subsection</h3>

        <p>Donec ut librero sed accu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor.</p>

        <p>Pelientesque auctor nisi id magna consequat sagittis. Curabitur dapibus, enim sit amet elit pharetra tincidunt feugiat nist imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros.</p>

        <h3>Another subsection</h3>

        <p>Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum soclis natoque penatibus et manis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>

        <p>Vivamus fermentum semper porta. Nunc diam velit, adipscing ut tristique vitae sagittis vel odio. Maecenas convallis ullamcorper ultricied. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, is fringille sem nunc vet mi.</p>
      </article>

      <!-- the aside content can also be nested within the main content -->
      <aside>
        <h2>Related</h2>

        <ul>
          <li><a href="#">Oh I do like to be beside the seaside</a></li>
          <li><a href="#">Oh I do like to be beside the sea</a></li>
          <li><a href="#">Although in the North of England</a></li>
          <li><a href="#">It never stops raining</a></li>
          <li><a href="#">Oh well...</a></li>
        </ul>
      </aside>

    </main>

    <!-- And here is our main footer that is used across all the pages of our website -->

    <footer>
      <p>©Copyright 2050 by nobody. All rights reversed.</p>
    </footer>
  </body>
</html>
Non-semantic wrappers

HTML provides the <div> and <span> elements. You should use these preferably with a suitable class attribute, to provide some kind of label for them so they can be easily targeted.

<span> is an inline non-semantic element, which you should only use if you can’t think of a better semantic text element to wrap your content.

<div> is a block level non-semantic element, which you should only use if you can’t think of a better semantic block element to use, or don’t want to add any specific meaning.

Line breaks and horizontal rules

<br> creates a line break in a paragraph; it is the only way to force a rigid structure in a situation where you want a series of fixed short lines.

<hr> elements create a horizontal rule in the document that denotes a thematic change in the text (such as a change in topic or scene). Visually it just looks like a horizontal line.

Debugging HTML

The way that browsers parse HTML is a lot more permissive than how programming languages are run, which is both a good and a bad thing.

Permissive code

So what do we mean by permissive? Well, generally when you do something wrong in code, there are two main types of error that you’ll come across:

  • Syntax errors: These are usually easy to fix as long as you are familiar with the language’s syntax and know what the error messages mean.
  • Logic errors: These are often harder to fix than syntax errors, as there isn’t an error message to direct you to the source of the error.

HTML itself doesn’t suffer from syntax errors because browsers parse it permissively, meaning that the page still displays even if there are syntax errors. Browsers have built-in rules to state how to interpret incorrectly written markup, so you’ll get something running, even if it is not what you expected. This, of course, can still be a problem!

HTML validation

The best strategy is to start by running your HTML page through the Markup Validation Service — created and maintained by the W3C, the organization that looks after the specifications that define HTML, CSS, and other web technologies. This webpage takes an HTML document as an input, goes through it, and gives you a report to tell you what is wrong with your HTML.

Multimedia and Embedding

Images in HTML

How do we put an image on a webpage?

source

If the image was in an images subdirectory, which was inside the same directory as the HTML page (which Google recommends for SEO/indexing purposes), then you’d embed it using relative URLs.

You could embed the image using its absolute URL, but this is pointless, as it just makes the browser do more work, looking up the IP address from the DNS server all over again, etc. You’ll almost always keep the images for your website on the same server as your HTML.

Alternative text

The value of alt attribute is supposed to be a textual description of the image, for use in situations where the image cannot be seen/displayed.

Width and height

You can use the width and height attributes to specify the width and height of your image. However, you shouldn’t alter the size of your images using HTML attributes. If you do need to alter an image’s size, you should use CSS instead.

Image titles

As with links, you can also add title attributes to images

1
2
3
4
5
6
<img src="images/dinosaur.jpg"
     alt="The head and torso of a dinosaur skeleton;
          it has a large head with long sharp teeth"
     width="400"
     height="341"
     title="A T-Rex on display in the Manchester University Museum">

Annotating images with figures and figure captions

A better solution, is to use the HTML5 <figure> and <figcaption> elements. These are created for exactly this purpose: to provide a semantic container for figures, and to clearly link the figure to the caption.

1
2
3
4
5
6
7
8
9
<figure>
  <img src="images/dinosaur.jpg"
       alt="The head and torso of a dinosaur skeleton;
            it has a large head with long sharp teeth"
       width="400"
       height="341">

  <figcaption>A T-Rex on display in the Manchester University Museum.</figcaption>
</figure>

captions and alt text have distinct roles

A figure could be several images, a code snippet, audio, video, equations, a table, or something else.

CSS background images

You can also use CSS to embed images into webpages (and JavaScript, but that’s another story entirely). The CSS background-image property, and the other background-* properties, are used to control background image placement.

1
2
3
p {
  background-image: url("images/dinosaur.jpg");
}

The resulting embedded image, is arguably easier to position and control than HTML images.

Summing up: if an image has meaning, in terms of your content, you should use an HTML image. If an image is purely decoration, you should use CSS background images.

Video and audio content

Video and audio on the web

In the early days, native web technologies such as HTML didn’t have the ability to embed video and audio on the Web, so proprietary (or plugin-based) technologies like Flash (and later, Silverlight) became popular for handling such content.

A few years later the HTML5 specification had such features added, with the <video> and <audio> elements, and some shiny new JavaScript APIs for controlling them.

The <video> element
1
2
3
<video src="rabbit320.webm" controls>
  <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.webm">link to the video</a> instead.</p> 
</video>
  • the src (source) attribute contains a path to the video you want to embed.
  • You must either use the controls attribute to include the browser’s own control interface, or build your interface using the appropriate JavaScript API.
  • The paragraph inside the <video> tags will be displayed if the browser accessing the page doesn’t support the <video> element.
Using multiple source formats to improve compatibility

different browsers support different video (and audio) formats.

1
2
3
4
5
<video controls>
  <source src="rabbit320.mp4" type="video/mp4">
  <source src="rabbit320.webm" type="video/webm">
  <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
</video>

Here we’ve taken the src attribute out of the actual <video> tag, and instead included separate <source> elements that point to their own sources. In this case the browser will go through the <source> elements and play the first one that it has the codec to support. Including WebM and MP4 sources should be enough to play your video on most platforms and browsers these days.

Each <source> element also has a type attribute. This is optional, but it is advised that you include it. The type attribute contains the MIME type of the file specified by the <source>, and browsers can use the type to immediately skip videos they don’t understand. Iftype isn’t included, browsers will load and try to play each file until they find one that works, which obviously takes time and is an unnecessary use of resources.

Other <video> features
1
2
3
4
5
6
7
<video controls width="400" height="400"
       autoplay loop muted
       poster="poster.png">
  <source src="rabbit320.mp4" type="video/mp4">
  <source src="rabbit320.webm" type="video/webm">
  <p>Your browser doesn't support HTML video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
</video>
  • width and height

    You can control the video size either with these attributes or with CSS. In both cases, videos maintain their native width-height ratio — known as the aspect ratio.

  • autoplay

    Makes the audio or video start playing right away, while the rest of the page is loading.

  • loop

    Makes the video (or audio) start playing again whenever it finishes.

  • muted

    Causes the media to play with the sound turned off by default.

  • poster

    The URL of an image which will be displayed before the video is played. It is intended to be used for a splash screen or advertising screen.

  • preload

    Used for buffering large files; it can take one of three values:

    • "none" does not buffer the file
    • "auto" buffers the media file
    • "metadata" buffers only the metadata for the file
The <audio> element
1
2
3
4
5
<audio controls>
  <source src="viper.mp3" type="audio/mp3">
  <source src="viper.ogg" type="audio/ogg">
  <p>Your browser doesn't support HTML5 audio. Here is a <a href="viper.mp3">link to the audio</a> instead.</p>
</audio>

Other differences from HTML video are as follows:

  • The <audio> element doesn’t support the width/height attributes — again, there is no visual component, so there is nothing to assign a width or height to.
  • It also doesn’t support the poster attribute — again, no visual component.
Restarting media playback

At any time, you can reset the media to the beginning

1
2
const mediaElem = document.getElementById("my-media-element");
mediaElem.load();
Detecting track addition and removal
1
2
3
4
const mediaElem = document.querySelector("video");
mediaElem.audioTracks.onaddtrack = function(event) {
  audioTrackAdded(event.track);
}

Displaying video text tracks

Provide a transcript of the words being spoken in the audio/video. To do so we use the WebVTT file format and the <track> element.

“Transcribe” means “to write down spoken words as text.” The resulting text is a “transcript.”

  • subtitles

    Translations of foreign material, for people who don’t understand the words spoken in the audio.

  • captions

    Synchronized transcriptions of dialog or descriptions of significant sounds, to let people who can’t hear the audio understand what is going on.

  • timed descriptions

    Text which should be spoken by the media player in order to describe important visuals to blind or otherwise visually impaired users.

1
2
3
4
5
<video controls>
    <source src="example.mp4" type="video/mp4">
    <source src="example.webm" type="video/webm">
    <track kind="subtitles" src="subtitles_en.vtt" srclang="en">
</video>

For more details, please read Adding captions and subtitles to HTML5 video.

iframe — other embedding technologies

<iframe> elements are designed to allow you to embed other web documents into the current document. This is great for incorporating third-party content into your website that you might not have direct control over and don’t want to have to implement your own version of — such as video from online video providers, commenting systems like Disqus, maps from online map providers, advertising banners, etc.

1
2
3
4
5
6
7
8
9
<iframe src="https://developer.mozilla.org/en-US/docs/Glossary"
        width="100%" height="500" frameborder="0"
        allowfullscreen sandbox>
  <p> 
    <a href="https://developer.mozilla.org/en-US/docs/Glossary">
       Fallback link for browsers that don't support iframes
    </a>
  </p>
</iframe>

Adding vector graphics to the Web

What are vector graphics?

On the web, you’ll work with two types of image — raster images, and vector images:

  • Raster images are defined using a grid of pixels — a raster image file contains information showing exactly where each pixel is to be placed, and exactly what color it should be. Popular web raster formats include Bitmap (.bmp), PNG (.png), JPEG (.jpg), and GIF (.gif.)
  • Vector images are defined using algorithms — a vector image file contains shape and path definitions that the computer can use to work out what the image should look like when rendered on the screen. The SVG format allows us to create powerful vector graphics for use on the Web.

The difference becomes apparent when you zoom in the page — the PNG image becomes pixellated as you zoom in because it contains information on where each pixel should be (and what color). When it is zoomed, each pixel is simply increased in size to fill multiple pixels on screen, so the image starts to look blocky. The vector image however continues to look nice and crisp, because no matter what size it is, the algorithms are used to work out the shapes in the image, with the values simply being scaled as it gets bigger.

Adding SVG to your pages

The quick way: <img>
1
<img src="equilateral.png" alt="triangle with equal sides" srcset="equilateral.svg">

or

1
2
3
background: url("fallback.png") no-repeat center;
background-image: url("image.svg");
background-size: contain;
include SVG code inside your HTML
1
2
3
<svg width="300" height="200">
    <rect width="100%" height="100%" fill="green" />
</svg>
embed an SVG with an <iframe>
1
2
3
<iframe src="triangle.svg" width="500" height="500" sandbox>
    <img src="triangle.png" alt="Triangle with three unequal sides" />
</iframe>

Responsive images

How do you create responsive images?

We will be focusing on the HTML <img>s for this section, as seen in the content area — the image in the site header is only for decoration, and therefore implemented using CSS background images. CSS arguably has better tools for responsive design than HTML.

Resolution switching: Different sizes
1
2
3
4
5
<img srcset="elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 600px) 480px,
            800px"
     src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

srcset defines the set of images we will allow the browser to choose between, and what size each image is. Each set of image information is separated from the previous one by a comma.

The image’s intrinsic width in pixels (480w) — note that this uses the w unit, not px as you might expect. This is the image’s real size, which can be found by inspecting the image file on your computer.

sizes defines a set of media conditions (e.g. screen widths) and indicates what image size would be best to choose, when certain media conditions are true.

Resolution switching: Same size, different resolutions
1
2
3
4
<img srcset="elva-fairy-320w.jpg,
             elva-fairy-480w.jpg 1.5x,
             elva-fairy-640w.jpg 2x"
     src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">
1
2
3
img {
  width: 320px;
}

In this case, sizes is not needed — the browser simply works out what resolution the display is that it is being shown on, and serves the most appropriate image referenced in the srcset. So if the device accessing the page has a standard/low resolution display, with one device pixel representing each CSS pixel, the elva-fairy-320w.jpg image will be loaded (the 1x is implied, so you don’t need to include it.) If the device has a high resolution of two device pixels per CSS pixel or more, the elva-fairy-640w.jpg image will be loaded.

Art direction

For example, a web page includes a large landscape shot with a person in the middle when viewed on a desktop browser. It would probably be better to show a smaller, portrait image on mobile, which zooms in on the person.

1
2
3
4
5
<picture>
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>

Note: You should use the media attribute only in art direction scenarios; when you do use media, don’t also offer media conditions within the sizes attribute.

<picture> lets us continue catering to older browsers. You can supply MIME types inside type attributes so the browser can immediately reject unsupported file types:

1
2
3
4
5
<picture>
  <source type="image/svg+xml" srcset="pyramid.svg">
  <source type="image/webp" srcset="pyramid.webp"> 
  <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
  • Do not use the media attribute, unless you also need art direction.
  • In a <source> element, you can only refer to images of the type declared in type.
  • Use comma-separated lists with srcset and sizes, as needed.

HTML tables

HTML table basics

When should you NOT use HTML tables?

HTML tables should be used for tabular data — this is what they are designed for. Unfortunately, a lot of people used to use HTML tables to lay out web pages, e.g. one row to contain the header, one row to contain the content columns, one row to contain the footer, etc.

Adding headers with <th> elements
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<table>
    <tr>
        <td>&nbsp;</td>
        <th scope="col">Knocky</th>
        <th scope="col">Flor</th>
    </tr>
    <tr>
        <th scope="row">Breed</th>
        <td>Jack Russell</td>
        <td>Poodle</td>
    </tr>
    <tr>
        <th scope="row">Age</th>
        <td>16</td>
        <td>9</td>
    </tr>
    <tr>
        <th scope="row">Owner</th>
        <td>Mother-in-law</td>
        <td>Me</td>
    </tr>
    <tr>
        <th scope="row">Eating Habits</th>
        <td>Eats everyone's leftovers</td>
        <td>Nibbles at food</td>
    </tr>
</table>
Allowing cells to span multiple rows and columns

table headers and cells have the colspan and rowspan attributes, which allow us to span across rows and columns.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<table>
    <tr>
    	<th colspan="2">Animals</th>
    </tr>
    <tr>
    	<th colspan="2">Hippopotamus</th>
    </tr>
    <tr>
    	<th rowspan="2">Horse</th>
    	<td>Mare</td>
    </tr>
    <tr>
   		<td>Stallion</td>
    </tr>
    <tr>
    	<th colspan="2">Crocodile</th>
    </tr>
    <tr>
    	<th rowspan="2">Chicken</th>
    	<td>Hen</td>
    </tr>
    <tr>
    	<td>Rooster</td>
    </tr>
</table>
Providing common styling to columns

HTML has a method of defining styling information for an entire column of data all in one place — the <col> and <colgroup> elements.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<table>
  <colgroup>
    <col>
    <col style="background-color: yellow">
  </colgroup>
  <tr>
    <th>Data 1</th>
    <th>Data 2</th>
  </tr>
  <tr>
    <td>Calcutta</td>
    <td>Pizza</td>
  </tr>
  <tr>
    <td>Robots</td>
    <td>Jazz</td>
  </tr>
</table>

HTML Table advanced features and accessibility

Adding a caption to your table with <caption>

You should put it just below the opening <table> tag.

1
2
3
4
5
<table>
  <caption>Dinosaurs in the Jurassic period</caption>

  ...
</table>

Adding structure with <thead>, <tfoot>, and <tbody>

The scope attribute

the scope attribute, which can be added to the <th> element to tell screenreaders exactly what cells the header is a header for — is it a header for the row it is in, or the column

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<table>
    <caption>How I chose to spend my money</caption>
    <thead>
        <tr>
            <th scope="col">Purchase</th>
            <th scope="col">Location</th>
            <th scope="col">Date</th>
            <th scope="col">Evaluation</th>
            <th scope="col">Cost (€)</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <td colspan="4">SUM</td>
            <td>118</td>
        </tr>
    </tfoot>
    <tbody>
        <tr>
            <td>Haircut</td>
            <td>Hairdresser</td>
            <td>12/09</td>
            <td>Great idea</td>
            <td>30</td>
        </tr>
        <tr>
            <td>Lasagna</td>
            <td>Restaurant</td>
            <td>12/09</td>
            <td>Regrets</td>
            <td>18</td>
        </tr>
        <tr>
            <td>Shoes</td>
            <td>Shoeshop</td>
            <td>13/09</td>
            <td>Big regrets</td>
            <td>65</td>
        </tr>
        <tr>
            <td>Toothpaste</td>
            <td>Supermarket</td>
            <td>13/09</td>
            <td>Good</td>
            <td>5</td>
        </tr>
    </tbody>
</table>

HTML forms

Forms allow users to enter data, which is generally sent to a web server for processing and storage, or used on the client-side to immediately update the interface in some way (for example, add another item to a list, or show or hide a UI feature).

A web form’s HTML is made up of one or more form controls (sometimes called widgets).

The controls can be single or multi-line text fields, dropdown boxes, buttons, checkboxes, or radio buttons.

Form controls can also be programmed to enforce specific formats or values to be entered (form validation), and paired with text labels that describe their purpose

How to structure an HTML form

The <form> element

All of its attributes are optional, but it’s standard practice to always set at least the action and method attributes

The <label>, <input>, and <textarea> elements
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<form action="/my-handling-form-page" method="post">
 <ul>
  <li>
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name" />
  </li>
  <li>
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_email" />
  </li>
  <li>
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message"></textarea>
  </li>
  <li class="button">
    <button type="submit">Send your message</button>
  </li>
 </ul>
</form>

The <li> elements are there to conveniently structure our code and make styling easier.

For usability and accessibility, we include an explicit label for each form control. Note the use of the for attribute on all <label> elements, which takes as its value the id of the form control with which it is associated — this is how you associate a form with its label.

On the <input> element, the most important attribute is the type attribute. This attribute is extremely important because it defines the way the <input> element appears and behaves.

The input field for the name is a single-line text field.

The input field for the e-mail is an input of type email.

The input field for the message is a <textarea>; a multiline text field.

To define the default value of an <input> element you have to use the value attribute like this:

1
<input type="text" value="by default this element is filled with this text">

if you want to define a default value for a <textarea>

1
2
3
<textarea>
by default this element is filled with this text
</textarea>
The <button> element

The <button> element also accepts a type attribute — this accepts one of three values: submit, reset, or button. You can also use the <input> element with the corresponding type to produce a button, for example <input type="submit">.

Sending form data to your web server

We provide a name to each form control. The names are important on both the client- and server-side; they tell the browser which name to give each piece of data and, on the server side, they let the server handle each piece of data by name. The form data is sent to the server as name/value pairs.

The <fieldset> and <legend> elements

The <fieldset> element is a convenient way to create groups of widgets that share the same purpose, for styling and semantic purposes. You can label a <fieldset> by including a <legend> element just below the opening <fieldset> tag. The text content of the <legend> formally describes the purpose of the <fieldset> it is included inside.

building a form structure

Beyond the structures specific to web forms, it’s good to remember that form markup is just HTML. This means that you can use all the power of HTML to structure a web form.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<form method="post">
    <h1>Payment form</h1>
    <p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
    <section>
        <h2>Contact information</h2>
        <fieldset>
            <legend>Title</legend>
            <ul>
            </ul>
        </fieldset>
        <p>
            <label for="name">
                <span>Name: </span>
                <strong><abbr title="required">*</abbr></strong>
            </label>
            <input type="text" id="name" name="username">
        </p>
    </section>
    <section>
        <p> <button type="submit">Validate the payment</button> </p>
    </section>
</form>

The native form widgets

Text input fields

All basic text controls share some common behaviors:

  • They can be marked as readonly (the user cannot modify the input value but it is still sent with the rest of the form data) or disabled (the input value can’t be modified and is never sent with the rest of the form data).
  • They can have a placeholder; this is text that appears inside the text input box that should be used to briefly describe the purpose of the box.
  • They can be constrained in size (the physical size of the box) and maxlength (the maximum number of characters that can be entered into the box).
  • They can benefit from spell checking (using the spellcheck attribute), if the browser supports it.

HTML form text fields are simple plain text input controls. This means that you cannot use them to perform rich editing (bold, italic, etc.). All rich text editors you’ll encounter are custom widgets created with HTML, CSS, and JavaScript.

Single line text fields
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<label for="comment">Add a comment here:</label>
<input type="text" id="comment" name="comment" value="I'm a text field">

<label for="email">Enter your email address:</label>
<input type="email" id="email" name="email" multiple>

<label for="pwd">Enter your password:</label>
<input type="password" id="pwd" name="pwd">

<label for="search">Search:</label>
<input type="search" id="search" name="search">

<label for="tel">Enter your number:
<input type="tel" id="tel" name="tel">

<label for="url">Web address:</label>
<input type="url" id="url" name="url">

<input type="hidden" id="timestamp" name="timestamp" value="1286705410">
Attribute types Description
multiple email, file Boolean. Whether to allow multiple values

The hidden input type should not have an associated label, and the value can be dynamically set via JavaScript. This is used to create a form control that is invisible to the user, but is still sent to the server along with the rest of the form data once submitted.

Checkable items: checkboxes and radio buttons

There are two kinds of checkable item: the check box and the radio button. Both use the checked attribute to indicate whether the widget is checked by default or not.

In the case of checkable items, their values are sent only if they are checked. If they are not checked, nothing is sent, not even their name.

Any checkboxes and radio buttons with the checked attribute on load match the :default pseudo class, even if they are no longer checked. Any that are currently checked match the :checked pseudoclass.

Check box
1
<input type="checkbox" id="carrots" name="carrots" value="carrots" checked>
Radio button
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<fieldset>
  <legend>What is your favorite meal?</legend>
  <ul>
    <li>
      <label for="soup">Soup</label>
      <input type="radio" id="soup" name="meal" value="soup" checked>
    </li>
    <li>
      <label for="curry">Curry</label>
      <input type="radio" id="curry" name="meal" value="curry">
    </li>
    <li>
      <label for="pizza">Pizza</label>
      <input type="radio" id="pizza" name="meal" value="pizza">
    </li>
  </ul>
</fieldset>

Several radio buttons can be tied together. If they share the same value for their name attribute, they will be considered to be in the same group of buttons. Only one button in a given group may be checked at a time.

Actual buttons

1
2
3
4
5
6
<button type="submit">
    This is a <strong>submit button</strong>
</button>
<input type="submit" value="This is a submit button">
<input type="reset" value="This is a reset button">
<input type="button" value="This is an anonymous button">
Image button

The image button control is rendered exactly like an <img> element, except that when the user clicks on it, it behaves like a submit button.

1
<input type="image" alt="Click me!" src="my-img.png" width="80" height="30">

If the image button is used to submit the form, this control doesn’t submit its value — instead, the X and Y coordinates of the click on the image are submitted.

File picker

The types of files that are accepted can be constrained using the accept attribute.

1
<input type="file" name="file" id="file" accept="image/*" multiple>

On some mobile devices, the file picker can access photos, videos, and audio captured directly by the device’s camera and microphone by adding capture information to the accept attribute like so:

1
2
3
<input type="file" accept="image/*;capture=camera">
<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">

Common attributes

Attribute name Default value Description
autofocus false
disabled false
form
name The name of the element; this is submitted with the form data.
value The element’s initial value.

Sending form data

The action attribute

absolute URL

1
<form action="https://example.com">

use a relative URL — the data is sent to a different URL on the same origin:

1
<form action="/somewhere_else">

When specified with no attributes, the <form> data is sent to the same page that the form is present on

The method attribute

An HTTP request consists of two parts: a header that contains a set of global metadata about the browser’s capabilities, and a body that can contain information necessary for the server to process the specific request.

Viewing HTTP requests

HTTP requests are never displayed to the user (if you want to see them, you need to use tools such as the Firefox Network Monitor or the Chrome Developer Tools).

with a GET request the user will see the data in their URL bar, but with a POST request they won’t, with the data included in the request body instead.

  1. If you need to send a password (or any other sensitive piece of data), never use the GET method or you risk displaying it in the URL bar, which would be very insecure.
  2. If you need to send a large amount of data, the POST method is preferred because some browsers limit the sizes of URLs. In addition, many servers limit the length of URLs they accept.

A special case: sending files

The enctype attribute

If you want to send files:

  • Set the value of enctype to multipart/form-data because the data will be split into multiple parts, one for each file plus one for the text data included in the form body (if text is also entered into the form).
1
2
3
4
5
6
7
8
9
<form method="post" action="https://www.foo.com" enctype="multipart/form-data">
  <div>
    <label for="file">Choose a file</label>
    <input type="file" id="file" name="myFile">
  </div>
  <div>
    <button>Send the file</button>
  </div>
</form>

Form validation

When you enter data, the browser and/or the web server will check to see that the data is in the correct format and within the constraints set by the application. Validation done in the browser is called client-side validation, while validation done on the server is called server-side validation.

Different types of client-side validation

There are two different types of client-side validation that you’ll encounter on the web:

  • Built-in form validation uses HTML5 form validation features, which we’ve discussed in many places throughout this module. This validation generally doesn’t require much JavaScript. Built-in form validation has better performance than JavaScript, but it is not as customizable as JavaScript validation.

  • JavaScript validation is coded using JavaScript. This validation is completely customizable, but you need to create it all (or use a library).

    • library).
Using built-in form validation

When an element is valid, the following things are true:

  • The element matches the :valid CSS pseudo-class, which lets you apply a specific style to valid elements.
  • If the user tries to send the data, the browser will submit the form, provided there is nothing else stopping it from doing so (e.g., JavaScript).

When an element is invalid, the following things are true:

  • The element matches the :invalid CSS pseudo-class, and sometimes other UI pseudo-classes (e.g., :out-of-range) depending on the error, which lets you apply a specific style to invalid elements.
  • If the user tries to send the data, the browser will block the form and display an error message.
  • The required attribute

  • Validating against a regular expression

    Note: The <textarea> element doesn’t support the pattern attribute.

  • Constraining the length of your entries

    For number fields (i.e. <input type="number">), the min and max attributes can be used to provide a range of valid values.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<form>

  <label for="choose">Would you prefer a banana or cherry? (required)</label>
  <input id="choose" name="i_like" required pattern="[Bb]anana|[Cc]herry" minlength="6" maxlength="6">
  
  <div>
    <label for="number">How many would you like?</label>
    <input type="number" id="number" name="amount" value="1" min="1" max="10">
  </div>
  
  <button>Submit</button>
</form>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
input:invalid {
  border: 2px dashed red;
}

input:invalid:required {
  background-image: linear-gradient(to right, pink, lightgreen);
}

input:valid {
  border: 2px solid black;
}
Validating forms using JavaScript

The Constraint Validation API

  • validationMessage
    • validity: :
      • patternMismatch
      • rangeOverflow
      • rangeUnderflow
      • typeMismatch
      • valid
      • valueMissing
    • willValidate

Implementing a customized error message

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<form novalidate>
  <p>
    <label for="mail">
      <span>Please enter an email address:</span>
      <input type="email" id="mail" name="mail" required minlength="8">
      <span class="error" aria-live="polite"></span>
    </label>
  </p>
  <button>Submit</button>
</form>

And add the following JavaScript to the page:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// There are many ways to pick a DOM node; here we get the form itself and the email
// input box, as well as the span element into which we will place the error message.
const form  = document.getElementsByTagName('form')[0];

const email = document.getElementById('mail');
const emailError = document.querySelector('#mail + span.error');

email.addEventListener('input', function (event) {
  // Each time the user types something, we check if the
  // form fields are valid.

  if (email.validity.valid) {
    // In case there is an error message visible, if the field
    // is valid, we remove the error message.
    emailError.innerHTML = ''; // Reset the content of the message
    emailError.className = 'error'; // Reset the visual state of the message
  } else {
    // If there is still an error, show the correct error
    showError();
  }
});

form.addEventListener('submit', function (event) {
  // if the email field is valid, we let the form submit

  if(!email.validity.valid) {
    // If it isn't, we display an appropriate error message
    showError();
    // Then we prevent the form from being sent by canceling the event
    event.preventDefault();
  }
});

function showError() {
  if(email.validity.valueMissing) {
    // If the field is empty
    // display the following error message.
    emailError.textContent = 'You need to enter an e-mail address.';
  } else if(email.validity.typeMismatch) {
    // If the field doesn't contain an email address
    // display the following error message.
    emailError.textContent = 'Entered value needs to be an e-mail address.';
  } else if(email.validity.tooShort) {
    // If the data is too short
    // display the following error message.
    emailError.textContent = `Email should be at least ${ email.minLength } characters; you entered ${ email.value.length }.`;
  }

  // Set the styling appropriately
  emailError.className = 'error active';
}

The difficult part is to make it generic enough to use both cross-platform and on any form you might create. There are many libraries available to perform form validation, such as Validate.js.

How to build custom form widgets

Sending forms through JavaScript

why this requires a different approach

Gaining control of the global interface

Standard HTML form submission loads the URL where the data was sent, which means the browser window navigates with a full page load. Avoiding a full page load can provide a smoother experience by avoiding network lag, and possible visual issues like flickering.

Many modern UIs only use HTML forms to collect input from the user, and not for data submission. When the user tries to send the data, the application takes control and transmits the data asynchronously in the background, updating only the parts of the UI that require changes.

Sending arbitrary data asynchronously is generally called AJAX, which stands for “Asynchronous JavaScript And XML”.

Using XMLHttpRequest and the FormData object

Using a standalone FormData object
1
<button>Click Me!</button>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const btn = document.querySelector('button');

function sendData( data ) {
  const XHR = new XMLHttpRequest(),
        FD  = new FormData();

  // Push our data into our FormData object
  for( name in data ) {
    FD.append( name, data[ name ] );
  }

  // Define what happens on successful data submission
  XHR.addEventListener( 'load', function( event ) {
    alert( 'Yeah! Data sent and response loaded.' );
  } );

  // Define what happens in case of error
  XHR.addEventListener(' error', function( event ) {
    alert( 'Oops! Something went wrong.' );
  } );

  // Set up our request
  XHR.open( 'POST', 'https://example.com/cors.php' );

  // Send our FormData object; HTTP headers are set automatically
  XHR.send( FD );
}

btn.addEventListener( 'click', function() 
  { sendData( {test:'ok'} ); 
} )

HTML forms in legacy browsers

The Modernizr team conveniently maintains a list of great polyfills. Just pick what you need.

Note: Modernizr has other awesome features to help you in dealing with unobstructive JavaScript and graceful degradation techniques. Please read the Modernizr documentation.

Styling HTML forms

Advanced styling for HTML forms

The bad: Some elements are more difficult to style, requiring more complex CSS or some more specific tricks:

The ugly: Some elements can’t be styled thoroughly using CSS.

solution

create a custom solution
use a third party solution

It is easier to just create your own custom solution for these features, if you want to be able to control the styling, or use a third party solution such as progressbar.js.

The road to nicer forms: useful libraries and polyfills

As we’ve mentioned above a few times, if you want to gain full control over the “ugly” control types, you have no choice but to rely on JavaScript. In the article How to build custom form controls you will see how to do it on your own, but there are some very useful libraries out there that can help you:

  • Uni-form is a framework that standardizes form markup, styling it with CSS. It also offers a few additional features when used with jQuery, but that’s optional.
  • Formalize is an extension to common JavaScript frameworks (such as jQuery, Dojo, YUI, etc.) that helps to normalize and customize your forms.
  • Niceforms is a standalone JavaScript method that provides complete customization of web forms. You can use some of the built in themes, or create your own.

The following libraries aren’t just about forms, but they have very interesting features for dealing with HTML forms:

  • jQuery UI offers customizable widgets such as date pickers (with special attention given to accessibility).
  • Twitter Bootstrap can help normalize your forms.
  • WebShim is a huge tool that can help you deal with browser HTML5 support. The web forms part can be really helpful.

Reference

  1. https://developer.mozilla.org/
  2. https://html.spec.whatwg.org/