High performance HTML

High performance HTML

How can you improve the performance of web pages?

Most developers look to JavaScript and image optimisation, server configuration, file minification and concatenation – even CSS tweaks.

Poor old HTML gets neglected, despite being the core language of the web.

HTML payloads are big and getting bigger. Pages on most top-100 sites require around 40k of HTML per page. Sites such as Amazon and Yahoo use thousands of lines of HTML per page. The youtube.com home page currently clocks in at a whopping 3.5K HTML elements.

Reducing HTML complexity and the number of elements in a page won’t improve parse time much – but well crafted HTML is a crucial foundation for building fast-loading pages and layouts that respond successfully to different viewport sizes.

In this article you’ll find out how to write clean, concise HTML that enables you to create content that loads fast and works well across a variety of devices. In the process, you’ll learn how to build sites and apps that are easier to debug and maintain.

There is always more than one way to write code – especially HTML. Rather than begin every sentence in this article with ‘In general …’ we’ve gone ahead and prescribed what in our experience usually works best. That doesn’t mean that every suggestion is right every time.

tl;dr

Sample HTML document with guidelines

HTML, CSS and JavaScript

HTML is a markup language for adding structure and meaning to content.

HTML should not be used to style content.  Don’t put text in heading tags to ‘make it bigger’ or use blockquotes just for indentation. Instead, use CSS to change the appearance and layout of elements.

The default appearance of HTML elements is defined by a browser’s default stylesheet: Chrome, Firefox, Internet Explorer and Opera each have their own. For example, in Chrome the h1 element by default is rendered as 32px bold Times.

Three general principles:

  • Use HTML for structure, CSS for presentation and JavaScript for behaviour. CSS Zen Garden (12 years old this year!) shows this separation of concerns in action.
  • Use HTML, then turn to CSS if and when required – and, if really necessary, move on to JavaScript. For example: in many cases it’s possible to use HTML for form validation and CSS or SVG for animation – without resorting to JavaScript.
  • Put CSS and JavaScript in files separate from your HTML. This enables caching and makes code easier to debug. In production, CSS and JavaScript can then be minified, concatenated and inlined as part of your build process.

Document structure

  • Use the HTML5 document type. Here’s a barebones document:
<!DOCTYPE html>
<html>

<head>
 <title>Recipes: pesto</title>
</head>

<body>

  <h1>Pesto</h1>

  <p>Pesto is good!</p>

</body>
</html>
  • Link to CSS files at the top of the page, in the head element like this:
<head>
  <title>My pesto recipe</title>

  <link rel="/css/global.css">
  <link rel="css/local.css">

</head>

That way, browsers have CSS information ready before parsing HTML.

  • Put JavaScript at the bottom of the page, before the closing body tag. This speeds up page load – since the browser can render the page before parsing JavaScript – and has the helpful side effect of enabling JavaScript to refer to page elements:
<body>

  ...

  <script src="/js/global.js">
  <script src="js/local.js">

</body>
  • Add handlers in JavaScript code. DON’T add them inline in HTML. For example, this is error prone and hard to maintain:

index.html:

<head>
  
  ...

  <script src="js/local.js">

</head>

<body onload="init()">

  ...

  <button onclick="handleFoo()">Foo</button>

  ...

</body>

This is much better:

index.html

<head>

  ...

</head>

<body>

  ...

  <button id="foo">Foo</button>

  ...

  <script src="js/local.js">

</body>

 js/local.js:

init();
var fooButton =
    document.querySelector('#foo');
fooButton.onclick = handleFoo();

 

Validation

A major reason for the success of the web is that browsers handle invalid HTML. There are even standardised rules for how browsers should render invalid code.

However, this is NOT a reason to be laissez-faire. Valid HTML is easier to debug and often smaller in file size, faster and less resource-hungry to parse and render. Invalid HTML can make successful responsive design difficult to implement.

Writing valid HTML is particular important when working with templates: what seems to work OK in an isolated chunk of code may go horribly wrong in combination with other content.

  • Incorporate validation in your workflow: use validation plugins such as HTMLHint and SublimeLinter with your editor and incorporate validation in your build process using tools such as HTMLHint with Grunt. You can check code online with tools such as the W3C HTML validator, and share configuration files with project contributors.
  • Use the HTML5 document type.
  • Make sure to maintain HTML hierarchy: nest elements correctly, and make sure no elements are left unclosed. It can be helpful for debugging to add a comment to the closing tag of an element that holds a large amount of complex content – especially when using templating:
<div id="foobar">

...

</div> <!-- foobar ends -->
  • Make sure to add closing tags to all elements that aren’t self-closing.

For example, this will work:

<p>Pesto is good to eat...
<p>...and pesto is easy to make.

But this is less likely to go wrong, since the end of each paragraph is made explicit:

<p>Pesto is good to eat...</p>
<p>...and pesto is easy to make.</p>
  • Closing tags are not required for list items and some very clever developers believe you should leave them out. Whatever you do, make sure to close every list element:
<ul>
  <li>Basil
  <li>Pine nuts
  <li>Garlic
</ul>
  • One place you absolutely must include closing tags is with the video and audio elements. These are not ‘self closing':
<!-- wrong: liable to cause layout grief -->
<video src="foo.webm" />

<!-- better -->
<video src="foo.webm">
  <p>Video element not supported.</p>
</video>

Conversely, cut clutter by removing unnecessary code:

  • There is no need to add a slash to ‘self closing’ (void) elements such as <img> and <link>. (There is a full list of self-closing elements here.)
  • Boolean attributes do not have a value: if the attribute is there, it’s true.This works (no autoplay, no controls):
    <video src="foo.webm">

    This doesn’t work, because the presence of an attribute forces a true value:

    <video src="foo.webm" autoplay="false" controls="false">

    This works:

    <video src="foo.webm" autoplay="true" controls="true">

    This is more readable:

    <video src="foo.webm" autoplay controls>
  • Stylesheets and scripts don’t need a type attribute: CSS and JavaScript are the defaults.
  • Omit the protocol when linking to external content: this prevents problems with mixed content. For example:
    <a href="//en.wikipedia.org/wiki/Tag_soup">Tag soup</a>

Code formatting

Consistent formatting makes HTML code easier to understand, optimise and debug.

  • Maintain an HTML style guide for project contributors (or use an existing one like Google’s).
  • Use your editor to automate code beautification. For example, in Sublime Text add a shortcut for Reindent. You can check layout with code linters such as SublimeLinter or online tools such as CSS Beautify and JS Beautifier.
  • Don’t go mad with hierarchical HTML indentation! This can easily get out of hand, so set rational defaults for when to begin an element at the left margin. Conversely, deep hierarchies may mean you need to refactor.
  • Standardise on indentation and use either spaces or tabs, not both.
  • Improve readability with sensible nesting. For example, it’s clear that this is a heading:
      <h2><a href="/contact">Contact</a><h2>

    …whereas at first glance this just looks like a link:

    <a href="/contact"><h2>Contact</h1></a>
  • Order elements in ways that won’t be a surprise to other developers – or you in six months. For example, a footer element should go at the bottom of your .html page, even though (in theory) it could be put anywhere.
  • Standardise on single or double quotes.
  • Use lowercase code for tag and attribute names. UPPERCASE IS TIRESOME:
    <A HREF="/">Home</A>

    Mixed case is EVEN worse:

    <H2>Pesto</h2>

Semantic markup

Semantic means ‘relating to meaning’.

HTML markup adds meaning to content: element and attribute names describe the role of content.

HTML5 introduced a number of new ‘semantic elements’ such as <header>, <footer> and <nav>.

Using the right element for the right content is good for accessibility and helps ensure your code is understandable:

  • Use <h1> (<h2>, <h3>…) for headings,  <ul> or <ol> for lists.
  • Note that <article>  headings should begin with an <h1> (reasoning here).
  • Where appropriate, use the HTML5 semantic elements such as <header>, <footer>, <nav> and <aside>.
  • Use <p> for body text, HTML5 semantic elements (or <div> as  a fallback) to structure content – not vice versa.
  • Use <em> and <strong> rather than <i> and <b>: <em> and <strong> add meaning, not styling hints.
  • With forms use the <label> element, input types, placeholder text, and the required attribute to enforce validation. (Pete LePage’s articles on Web Fundamental show how.)
  • Mixing text and elements, as children of another element, tends to lead to layout bugs. For example, this:
    <div>Name: <input type="text"></div>

    is better expressed as this:

    <div><label>Name:</label><input type="text"></div>

Layout

To reiterate: HTML should be used to add meaning and structure to content, not for styling.

  • Use <p> elements for text, not for layout. By default, <p> has margins and other styles applied by the built-in browser stylesheet.
  • Avoid using <br> for line breaks: use block elements or the CSS display property instead. The <br> should only ever be seen within text – and even then, only very rarely (for example, as a form of punctuation within poetry).
  • Avoid using the humble <hr> to add horizontal lines: CSS border-bottom is a better option. It may make sense to use <hr> to denote a thematic break.
  • Don’t use divs unnecessarily: the W3C HTML spec describes the div as ‘an element of last resort, for when no other element is suitable’ (sixrevisions.com). Style inline elements such as links and img elements with display: block, rather than putting them in divs or (worse) using <br>.
  • Learn which elements are block level, to avoid unnecessarily putting block level elements inside divs. For example, there is no need to put a list inside a div element.
  • Do not use tables for layout. Do use tables for tabular data.
  • Flex box is now widely implemented: use it.
  • Use CSS padding for padding and margin for margins: understand the box model.
  • Standardise on margins: it’s often best to add margins to the bottom and the right of elements, rather than the top or left. Whatever you do, avoid mixing top and bottom or left and right. Use the last-of-type selector to avoid redundant margins.

HTML emails

Coding for email is nothing like coding for the modern web.

We won’t go into the gruesome details here – suffice to say that best practice for HTML email coding resembles web development from the late 1990s: tables, shim GIFs, inconsistent and minimal CSS, patchy image and media support, little or no support for JavaScript, and lots of minor hacks. (For an unpleasant taster, take a look at MailChimp’s most basic template.)

More information here, here and here.

CSS

This article is about HTML, but here are some basic CSS tips:

  • Avoid inline CSS. For performance optimisation, CSS files can be inlined as part of your build process.
  • Use an ID once and once only: there should only be a single element with id=”foo”, id=”bar”, or any other ID.
  • Use classes when you want to refer to multiple elements – and take a look at BEM syntax. Where possible, use class attributes on a parent rather than children. For example:
<!-- verbose :( -->
<ul>
  <li class="ingredient">Basil</li>
  <li class="ingredient">Pine nuts</li>
  <li class="ingredient">Garlic</li>
</ul>
<!-- better :) -->
<ul class="ingredients">
  <li>Basil</li>
  <li>Pine nuts</li>
  <li>Garlic</li>
</ul>

Accessibility

Consider the range of devices, contexts and input methods that will be used to interact with your HTML:

  • Use semantic elements.
  • Provide fallbacks: add captions and subtitles with the track element, include fallback text and/or images in video and audio elements; use poster images for video; add alt attributes to every image (give the alt attribute an empty value if the image is only for decoration).
  • Add title attributes to links – but only if the title adds meaning and doesn’t just repeat the link text.
  • Use type and placeholder elements in input elements.
  • Use ARIA attributes.

Random bonus extra suggestions

  • Make sure to encode characters with special meaning in HTML, such as < and &. For example:  <title>HTML &amp; JavaScript</title>.
  • Conversely, do not unnecessarily encode characters such as en dashes (for example, 4–5 weeks) or currency symbols such as ¢ and €.
  • Add comments if and only if it’s not obvious what’s happening in code. (And bear in mind that code commenting often shows a need for refactoring – good HTML, even when it’s complex, is generally self-explanatory.)
  • Where it makes sense – with all-capitalised headings, for example – apply text case via the CSS text-transform and font-variant properties, not by entering uppercase text. You may change your mind later!  Also, if users copy text, they probably want upper and lower case. The following <h4> is displayed in small caps, but when copied will be upper and lower case.HTML:
    <h4>W3C Web Accessibility Initiative ARIA guidance</h4>

    CSS:

    h4 {
      font-variant: small-caps;
    }

And finally…

Whatever you do, test!

Build HTML testing into your workflow, toolchain and deployment processes.

Test page load on a variety of devices, on large and small screens, in a variety of connectivity contexts. Try interacting with your page with a text-only browser such as Lynx, or with a screenreader such as ChromeVox. Use emulators such as Chrome Dev Tools device mode to monitor changes. Page Speed, Web Page Test and other tools can be integrated with your workflow to automate testing before or after deployment.

For more information about how to write high performance HTML, follow the links in HTML, CSS and JavaScript resources and check out the guidance on Web Fundamentals.

Posted in html5 | Tagged , , , | 18 Comments

Media Newsletter: audio, video and realtime communications

I’ll be publishing a monthly roundup of news about media tech.

Sign up at bit.ly/signupmedia.

Archive at medianews.me.

Media Newsletter

Media Newsletter

Posted in Uncategorized | Leave a comment

Fundamentals of video on mobile

Watch my Google I/O video: Fundamentals of video on mobile:

  • Responsive media
  • Coping with variable connectivity
  • Accessibility and fallbacks
  • Formats and codecs
Video with captions on Chrome for Android

Video with captions on Chrome for Android

 

 

Posted in Uncategorized | Leave a comment

WebRTC in the real world: signaling, TURN and STUN

New on HTML5 Rocks: a detailed look at building servers for WebRTC.

html5rocks.com/en/tutorials/webrtc/infrastructure

New on HTML5 Rocks: WebRTC infrastructure

Posted in Uncategorized | Leave a comment

simpl.info: simplest possible examples of HTML, CSS and JavaScript

I’ve built a site to provide simplest possible examples of HTML, CSS and JavaScript:

simpl.info

github.com/samdutton/simpl

Motivations:

  • ‘Show me the code!’
  • ‘Does technology X work on platform Y?’
  • ‘Where the heck is that Foo example I saw?’
  • A minimum of ‘huh?’
  • Short, consistent, guessable URLs with sensible shortcuts, for example simpl.info/v redirects to simpl.info/video.
  • Easy to maintain.
  • Works well on mobile devices.

Caveats:

  • Oriented to modern browsers.
  • No templating.

I hope it’s useful – comments and suggestions much appreciated.

Posted in Uncategorized | Tagged , , , | 3 Comments

WebRTC in Internet Explorer with Chrome Frame

It’s now possible to use WebRTC – PeerConnection and MediaStream – in Internet Explorer with Chrome Frame.

Best of all, getUserMedia no longer requires a flag to work with the Chrome stable channel – so, if Chrome Frame is installed, getUserMedia just works!

I’ve recorded a screencast that shows how to install Chrome Frame and configure Chrome in order to use WebRTC in Internet Explorer:

First, an explanation of how Chrome Frame works.

Google Chrome Frame is an open source plug-in that seamlessly brings Google Chrome’s open web technologies and speedy JavaScript engine to Internet Explorer 6, 7, 8, or 9.

When web developers add the Chrome Frame meta element to their web page, Internet Explorer will use Chrome Frame to render the page.

There’s more information about Chrome Frame for developers at developers.google.com/chrome/chrome-frame.

To try out WebRTC with Chrome Frame today, you will need to use Chrome’s Dev Channel. In the future, the WebRTC APIs will be available in both Chrome and Chrome Frame’s stable channels, without requiring any flags or other user intervention.

Installation steps

1. Download Chrome’s Dev Channel browser from dev.chromium.org/getting-involved/dev-channel. (This does not work with Canary.)

2. Quit all of your browsers.

3. Install Chrome’s Dev Channel.

4. Start Internet Explorer and install Chrome Frame from google.com/chromeframe?quickenable=true.

5. To enable PeerConnection, you need to set a flag by using regedit to create the following entry in your registry (as ever, be careful when using regedit!):

[HKEY_CURRENT_USER\Software\Policies\Google\Chrome]
"AdditionalLaunchParameters"="--enable-peer-connection"

Just to reiterate: the WebRTC APIs will be ‘flagless’ in future versions of Chrome and won’t need this kind of intervention.

6. Re-start Internet Explorer.

One tip: you need 32-bit Internet Explorer to use Chrome Frame. It’s normal to have 32-bit Internet Explorer, even for 64-bit Windows, but you may want to check. Just look in All Programs for the version named Internet Explorer!

Once you’ve set up Chrome Frame in Internet Explorer, try out the getUserMedia demo at simpl.info/getusermedia or the WebRTC video chat application at apprtc.appspot.com.

If you want to know more about how to implement real-time communication in your web apps, take a look at the detailed introduction to WebRTC and getUserMedia at html5rocks.com: html5rocks.com/en/tutorials/webrtc/basics, html5rocks.com/en/tutorials/getusermedia/intro.

Let us know how it goes!

Posted in Uncategorized | Tagged , , , , , | 1 Comment

Introduction to WebRTC – now on HTML5 Rocks

I’ve written a detailed introduction to WebRTC on HTML5 Rocks.

I’ve tried to explain some of the more difficult concepts – please let me know if anything is still mystifying!

WebRTC NAT traversal

Posted in Uncategorized | Leave a comment