Bulletproof HTML: 37 Steps to Perfect Markup

This article highlights and answers some of the most frequently asked questions about HTML. HTML is the foundation of the Web, and both developers and designers need to understand it.

1. What is HTML?

HTML, or Hypertext Markup Language, is a markup language that’s primarily used for Web documents. Any document that’s written in a markup language is interspersed with tags that indicate the meanings of certain passages. Since version 2.0, HTML has been an application of a more generic markup language: SGML (Standard Generalized Markup Language).

HTML defines a number of element types. An element type assigns some semantic meaning to its content. For example, the em element type gives its content emphasis over the surrounding text. An element is a concrete instance of an element type. An element usually consists of a start tag (<em>), some content, and an end tag (</em>).

This HTML stuff is really, <em>really</em> nifty!

HTML allows some end tags (and even a few start tags) to be omitted. Don’t confuse tags with elements; a body element will be present even if the <body> and </body> tags are omitted. Certain element types must not have an end tag. One example is br, which signifies a line break.

Baa baa black sheep, have you any wool?<br> 
Yes sir, yes sir, three bags full

A start tag can contain attributes, comprising an attribute name, an equal sign (=), and an attribute value. For example, we can use the lang attribute to specify the language of an element’s content.

Jean-Claude often exclaimed <em lang="fr"> bon sang</em> despite the fact that no-one understood him.

Attribute values must be quoted in some instances, so it’s good practice always to quote all attribute values. Some boolean attributes are allowed to be minimised in HTML, which means the name and the equal sign are omitted (e.g. selected instead of selected="selected"). Some attributes are required for some element types, e.g., the alt attribute in an img element.

<img src="/images/sitepoint.gif" alt="SitePoint">

Beginners often use phrases like "alt tag", but this is incorrect nomenclature; alt is an attribute, not a tag. Tags are surrounded by <...>.

2. What are the different versions of HTML?

The first version of HTML (1989) didn’t have a version number; it was just "HTML". The first "standardised" version of HTML, released by the Internet Engineering Task Force (IETF) in 1995, was called HTML 2.0.

Then the World Wide Web Consortium (W3C) was formed. It presented its first "standard" version in 1997: HTML 3.2. Its successor, HTML 4.0, came out in 1998, and was quickly replaced by HTML 4.01 in 1999. That is the latest and current version of HTML. The W3C has announced that it will not create further versions of HTML. HTML 4.01 is recommended for creating HTML documents.

However, the Web Hypertext Application Technology Working Group (WHATWG) are working on what is referred to as HTML5, hoping that it will eventually be accepted as a W3C recommendation.

3. What about XHTML?

A few months after HTML 4.01 became a final recommendation, W3C released XHTML 1.0. This was seen as the "next version of HTML," but that perception’s not entirely correct. XHTML 1.0 is a "reformulation of HTML 4 as an application of XML 1.0", as the specification puts it. In other words, it’s XML with a predefined set of element types and attributes (and semantics) that correspond to the elements types and attributes of HTML 4.01. It even comes in the same three flavours as HTML.

Many designers and developers embraced XHTML, as it was seen as the way forward. Few understood the profound differences between XHTML and HTML, as they looked so similar. The reality is that the most commonly used browser, Internet Explorer, does not support XHTML in any way, shape or form. More modern browsers like Opera, Firefox and Safari do support XHTML, but their market shares are too low for their support to have any significant impact when it comes to publicly accessible web sites.

By adhering to a number of guidelines put forth in the famous Appendix C of the XHTML 1.0 specification, it is possible to serve an XHTML document as HTML. This approach allows HTML-only browsers to be able to "handle" the document, but it is, for all intents and purposes, nothing more than HTML. We cannot use any of the features of XHTML when serving it this way, because we are not really using XHTML at all — we’re only pretending to.

4. Is HTML case-sensitive?

No, but XHTML is. In XHTML, all tags and attributes must be in lowercase. Traditionally, HTML element names and tags were written in uppercase, but with the advent of XHTML, this convention has slowly given way to the XHTML standard of lowercase element names.

5. What does the DOCTYPE declaration do?

The DOCTYPE declaration, which must precede any other markup in a document, usually looks something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"http://www.w3.org/TR/html4/strict.dtd">

It specifies the element type of the document’s root element (HTML), a public identifier and a system identifier.

The public identifier (-//W3C//DTD HTML 4.01//EN) shows who has issued the document type definition, or DTD, (W3C); the name of the DTD (DTD HTML 4.01); and the language in which the DTD is written (EN, for English). Note that it doesn’t say anything about the language of the web page itself; it is the language of the DTD that is specified here.

The system identifier (http://www.w3.org/TR/html4/strict.dtd) is the URI (uniform resource identifier, or "web address") for the actual DTD.

The DOCTYPE declaration tells a validator (a program that checks the syntactic validity of a web page) against which DTD it should test the page for compliance. Browsers didn’t used to care about the DOCTYPE declaration, but modern browsers use it to decide whether the page is "modern" (and presumably expect the behaviour detailed in the W3C HTML documentation) or old-school (and expect the browser to render the page with all the bugs and quirks exhibited by older browsers). A document’s DOCTYPE affects the rendering mode used by Internet Explorer, Opera, Firefox (and other Mozilla-based browsers), Safari, and most other modern web browsers. A complete DOCTYPE declaration — including the system identifier — tells the browser that this is a modern document. If the system identifier is missing, or if there is no DOCTYPE declaration at all, browsers assume that this is an old document and render it in "quirks mode".

6. What is a DTD?

A DTD, or document type definition, specifies the element types and attributes that we can use in our web page. It also defines the rules of how we can use these elements together — it’s the specification for our markup language. The DTD can also declare the character entities we can use; more about those later.

A validator will test a web page for compliance with the DTD specified in the DOCTYPE declaration either explicitly, via the system identifier, or implicitly, using the public identifier. Browsers use non-validating parsers and do not actually read the DTD. They have built-in knowledge about the various element types, and usually a hard-coded list of character entities as well.

For HTML 4.01, which is the latest and greatest version, there are three different DTDs: Strict, Transitional and Frameset.

7. What is the difference between Strict, Transitional and Frameset DTDs?

The differences between these DTDs include the element types and attributes they declare, and how they allow or require element types to nest.

  • The HTML 4.01 Strict DTD emphasises the separation of content from presentation and behaviour. This is the DTD that the W3C recommends for all new documents.
  • The HTML 4.01 Transitional DTD is meant to be used transitionally when converting an old-school (pre-HTML4) document into modern markup. It isn’t intended to be used to create new documents. It contains 11 presentational element types and a plethora of presentational attributes that are deprecated in the Strict DTD. The Transitional DTD is also often necessary for pages that reside within a frameset, because it declares the TARGET attribute required for opening links in another frame.
  • The HTML 4.01 Frameset DTD is used for frameset pages. Frames are deprecated by the W3C. For modern web sites, using server-side scripting technologies is usually regarded as a far better solution.
8. Which DOCTYPE should I use?

If we are creating a new web page, the W3C recommends that we use HTML 4.01 Strict.

If we are trying to convert older HTML 2.0 or HTML 3.2 documents to the modern world, we can use HTML 4.01 Transitional until we have managed to transfer all presentational issues to CSS, and all behavioural issues to JavaScript.

9. Why should I validate my markup?

Why should we spell-check our text before publishing it on the web? Because mistakes and errors can confuse readers and detract from the important information. The same can be said for markup. Invalid markup can confuse browsers, search engines and other user agents. The result can be improper rendering, dysfunctional pages, pages that remain unindexed by the search engines, program crashes or the end of the universe as we know it!

If our page doesn’t display the way we intended, we should always validate our markup before we start looking for other problems (or asking for help on SitePoint). With invalid markup, there are no guarantees.

Use the HTML validator at W3C to check your pages’ compliance. Don’t forget to include a DOCTYPE declaration, so the validator knows against which standards it should check your document.

HTML Tidy is a free tool that can help us tidy sloppy markup, format it nicely and make it easier to read.

10. Why does HTML allow sloppy coding?

It doesn’t, but it recommends that user agents handle and try to recover markup errors.

It is sometimes alleged that HTML allows improperly nested elements like <b><i>foo</b></i>. That isn’t true; the validator will complain about improperly nested tags because they don’t constitute valid HTML. However, browsers will usually guess what the author meant, so the error may go undetected.

Some dislike that HTML allows the omission of certain (but not all!) end tags. That’s not a problem for browsers, because valid markup can always be parsed unambiguously. In the early years it was very common to omit certain end tags, (e.g. </p> and </li>). Nowadays it’s usually considered good practice to use explicit end tags for all elements except those, like br and img, for which it is forbidden.

11. Why does the validator complain about my <embed> tag?

embed has never been part of any HTML recommendation. It’s a non-standard extension which, although supported by most browsers, is not part of HTML.

During the "browser wars" of the late 1990s, browser vendors like Microsoft and Netscape competed by adding lots of "cool" features to HTML to make it possible to style web pages. The problem with those additions was that they weren’t standardised, and were mostly incompatible between browsers.

There are other elements that used to be quite common (marquee, anyone?), but which have never been included in an HTML recommendation. Don’t use them if you can possibly avoid doing so.

A number of other attributes were very common in the 1990s, but have never been included in an official HTML recommendation. marginwidth is one example.

12. What does character encoding (charset) mean?

Computers can only deal with numbers. What we see on the screen as letters or images are transmitted over the Internet and around the various parts of your computer as numeric codes, which the computer sees as groups of binary digits (ones and zeros).

In order to make sense of these numbers, we need to define a minimum unit that’s capable of conveying some sort of information. When we’re dealing with text, this unit is called a character. This is a rather abstract concept. The character known as "uppercase A" has no defined visual appearance; it’s more like "the idea of an A".

Next, we need to establish a set of such abstract characters that we will use. That’s called a character set. A character set is the total set of abstract characters that we have at our disposal. For HTML, the standard character set is ISO 10646, which is virtually the same thing as Unicode. It is a set of tens of thousands of characters representing most of the written languages on the planet.

The visual appearance of a character is called a glyph. A certain set of glyphs is known as a font. The glyph for "uppercase A" will differ between fonts, but that doesn’t change the underlying meaning of the abstract character.

Now, since computers only deal with numbers, we must have a way to represent each character with a numeric code. Each character in a character set has a code position, or code point. The code point is the numeric representation (index) of the character within the character set. Code points in Unicode are usually expressed in hexadecimal (e.g., 0x0041 for "uppercase A").

Finally, the encoding — sometimes, unfortunately, also called a "character set" or "charset", though we’ll stick with the correct term "character encoding" here — is a mechanism for expressing those code points, usually with octets, which are groups of 8 binary digits (and thus are capable of representing numbers between 0 and 255, inclusive).

In the early days of computer communication, people used small character sets containing only the bare necessities for a specific language. The most well-known set is probably ASCII (ISO 646), which only contains 128 characters, 33 of which are unprintable "control codes". The ASCII character set has 128 code points numbered sequentially from 0 to 127. The encoding is a simple one-to-one: the codepoint for "uppercase A" is 65 (0x41), which is encoded as 65 (1000001 in binary).

ASCII isn’t very useful outside the English-speaking world, because it contains only the letters A-Z, digits 0-9, and some basic punctuation. The International Organization for Standardization (ISO) issued a set of standards called ISO 8859, which augmented the ASCII character set with characters that needed for other languages. In the Western world, the most common set is ISO 8859-1, known as Latin-1. It contains characters needed to write most Western European languages. The ISO 8859 series are both character sets and character encodings. Each character set contains 256 characters, which can be encoded using 8 binary digits. They each used the ASCII character set as a subset, i.e., the first 128 code points are the same.

But even 256 characters was not enough to write some languages. Chinese, for instance, needs thousands of characters. Several mutually incompatible encodings for Chinese were devised, but there were still big problems for those who wanted to exchange information across linguistic and cultural barriers.

From this point, it would be easy to create a character encodings that used 16 or even 32 binary digits for each character. However, using a 32-bit encoding would result in most documents being four times larger than they needed to be.

The solution was a variable-length encoding called UTF-8. It uses between 8 and 48 bits to encode each code point, and it can address the entire Unicode (or ISO 10646) character set. The first 128 code points are encoded in 8 bits, and are identical to the corresponding code points in ASCII. Most Western European languages can be encoded with single octets, sprinkled with the occasional 16-bit character for letters with diacritical marks (e.g., Ä).

How does this affect us as authors of web documents? If we use characters whose code points are outside the ASCII range, the encoding becomes really crucial. Specify the wrong encoding, and the page will be difficult — or even impossible — to read.

So how do we go about specifying the encoding? The proper way to do it is to send this information in the Content-Type HTTP header:

Content-Type: text/html; charset=utf-8

The HTTP headers are sent by our web server, so we must tweak the server to change the encoding information. How we achieve that will depend on which web server we use. For Apache, it can be specified in the global configuration file (httpd.conf) or in local .htaccess files. But if we’re using a shared host, we may not have sufficient privileges to tweak the configuration. In that case, we need a server-side scripting language to send our own HTTP header; here’s an example for PHP:

header('Content-Type: text/html; charset=utf-8');

We can also specify the encoding using an HTTP equivalent in a META element:

<meta http-equiv="Content-Type" 
content="text/html; charset=utf-8">

This meta element will be ignored if the real HTTP header contains encoding information. It can be useful anyway, though, because it will be used if a visitor saves our page to the hard drive and looks at it locally. In that situation, there’s no web server to send HTTP headers, so the meta element will be used instead.

There is no default encoding for HTML, so we should always make sure to specify it.

A common encoding under Microsoft Windows is Windows-1252. It’s very similar to ISO 8859-1, but there are differences. In ISO 8859-1, the range of code points between 0x80 and 0x9F is reserved for control characters. In Windows-1252, that range is instead used for a number of useful characters that are missing from the ISO encoding (e.g., typographically correct quotation marks). This is not an encoding that I would recommend for use on the Web, since it’s Windows-specific. However, it is the default encoding in many text editors under Windows.

13. What is a BOM?

The BOM, or byte order mark, is used for some encodings that use more than 8 bits to encode code points (e.g. UTF-8 and UTF-16). Computer processors (CPUs) can employ two different schemes for storing large integer numbers: "big-endian" and "little-endian". The BOM comprises 16 bits, written at the very beginning of the file, which tell the browser which scheme is being used.

Unfortunately, many older browsers cannot handle this information, so they display these bits as character data. If you see a couple of strange characters at the top of a page, the reason is probably that the BOM isn’t handled by the browser (or an incorrectly specified encoding).

The only resolution to this problem is to avoid using the BOM. Editors that can save a document as UTF-8 will usually allow us to choose whether or not to include the BOM.

14. What encoding should I declare?

It’s very, very simple: we must specify the encoding that we used when saving our source file! If we save the file as ISO 8859-1, we must specify the encoding as iso-8859-1; if we save as UTF-8, we specify it as utf-8. The only problem here is that we may not always know what encoding our editor uses to save the file. Any editor worth its salt should give us the option to specify the encoding, though.

If we are writing in English, it doesn’t matter all that much which encoding we choose, because we are mostly going to use characters that are encoded the same in most encodings. US-ASCII, ISO 8859-1, UTF-8 … take your pick. For those of us who write code in other languages, the choice becomes more important. My native language — Swedish — uses three letters more than the English alphabet has to offer. Those are present in ISO 8859-1, so I can choose between that and UTF-8 encoding. Browser support for UTF-16 is poor, so it should be avoided on public web sites.

My recommendation is to use UTF-8 encoding wherever possible, without a BOM. It can natively represent any character in the Unicode character set.

Avoid Windows-1252 on public web pages, since it’s a Windows-specific encoding. Use ISO 8859-1 instead (or ISO 8859-15, if you need the Euro sign).

15. How do I insert characters outside the encoding range?

What if we’re using ISO 8859-1 encoding and wish to include a Euro sign in our content? There is no Euro sign in that character set, and hence no way to encode it, although it is present in ISO 10646 and can be used on a web page.

We have two choices: a named entity or a numeric reference.

The named entity for the Euro sign is &euro;. Entities start with an ampersand (&) and end with a semicolon (;). In some circumstances we can get away with omitting the semicolon, but it is definitely good practice to always put it in. Entity names are case-sensitive.

A numeric reference can be either decimal (&#8212;) or hexadecimal (&#x2014;), but it’s generally safer to stick with decimal notation, because some old browsers can’t handle the hexadecimal version. Note that the numeric value references the code point in ISO 10646; it has nothing to do with the encoding we’ve specified for our document.

References (in decimal) always work. Named entities may cause problems in older browsers, because some of them only support a subset of HTML entities.

16. Why do I need to write &amp; instead of just &?

Certain characters have special meanings in HTML: < (less than), > (greater than), & (ampersand), " (quotation mark) and ' (apostrophe). In some circumstances, when we want to use these characters in normal text, we need to replace them with HTML entities.

The entities for the first four characters are as follows:

  • &lt; (less than)
  • &gt; (greater than)
  • &amp; (ampersand)
  • &quot; (quotation mark)

XML defines an entity for the apostrophe (&apos;), but HTML does not include this entity. An apostrophe can only be escaped using a numeric reference (&#39;).

Since the ampersand is used for these entities, it must nearly always be escaped, including occasions when it’s used inside attribute values, such as the href attribute of links. Unfortunately, the ampersand is a very common argument separator in URIs, which means that it’s quite common to encounter ampersands in URIs.

Most of the time in HTML, unescaped ampersands don’t break anything (though XHTML is a different story). The error handling routines in browsers recover from the error and it all works. But if we should happen to have a query parameter whose name matches one of the predefined named entities in HTML …

17. How should heading elements be used?

HTML heading element types are h1, h2, h3, h4, h5 and h6. The number denotes the structural level of the heading, which means we should treat headings as we did in those outlines we had to learn in school (and promptly forgot about right after graduation).

The top-level heading on a page must be an h1. It should describe what the page is about. Most pages will have one h1 heading, but very complex documents that deal with several disparate topics may need more than one.

h2 headings will mark up the next structural level. Any sub-levels under that will be h3, and so on. We can never skip a heading level as we move downward through the hierarchy. An h4 should not follow an h2; there should be an h3 in between. (The validator will not complain about this, but it is good practice.)

It’s important to mark up headings with the Hn element types. Assistive technologies such as screen readers can make use of a proper heading hierarchy to present an outline of the document. If we use <font size="7">...</font>, they cannot.

18. What are block-level and inline elements?

HTML employs two main categories of element types: block-level elements and inline elements. The differences between them are mainly semantic and grammatical.

Block-level elements are usually "containers" for other elements. Examples of block-level elements are div, p, form and table. Some block-level elements (e.g., p) can only contain text and inline elements. Others (e.g., form) can contain only block-level elements (in the Strict DTD). And some, like div, can contain text, inline elements and block-level elements. By default, block-level elements are rendered with an implicit line break before and after; in other words, we cannot have two block-level elements side by side using only Strict HTML. (To do so would require CSS.)

Inline elements are elements that can exist "inline" within text. Examples include a, em, q and span. An inline element can contain only text and other inline elements. An inline element cannot contain a block-level element, with one exception: object (which is known as a replaced inline element, the same as img). Inline elements, when rendered, do not have any implied line breaks before or after.

In some cases, additional restrictions are placed on child element types. For instance, anchor links (a) can contain text and inline elements, but not other a elements; you cannot nest links.

The rules are somewhat different between the Strict and Transitional DTDs. In the Strict DTD, some block-level elements, including body, blockquote and form, can only have block-level children. In the Transitional DTD, they can also contain text and inline elements as immediate children.

19. Can I make an inline element block-level with CSS?

No. This is a common misconception. Beginners sometimes think that by applying the display: block declaration to an a element, they will be able to put a block-level h1 inside the link. That is not the case.

HTML has block-level and inline elements. CSS has block and inline boxes (plus a few others). These are very different things. The distinction in HTML has to do with semantics and syntax, while the distinction in CSS has to do with rendering and presentation. By default, block-level elements generate block boxes, and inline elements generate inline boxes (this is a grossly simplified explanation, but is generally true). The display property can change the type of the generated box, but CSS cannot change the grammatical or syntactical rules of HTML.

20. Why are external CSS and JavaScript files a good idea?

From a maintenance perspective, a full separation of content, presentation and behaviour is something to strive for. Then, if we want to change the colours of our site, we can simply edit a single style sheet instead of updating possibly thousands of HTML documents. If we use style attributes and write inline CSS, we will have to edit all of those HTML documents when redesigning our site, instead of simply editing a single style sheet file.

There is also another issue: both CSS and JavaScript often contain characters that have special meanings in HTML. If the CSS code or JavaScript code is embedded into the HTML document, these characters need to be escaped. If we have embedded JavaScript, and use the archaic practice of "hiding" the script code within SGML comments (<!--...-->), we cannot use the decrement operator (--), because the double hyphen will terminate the comment.

21. Should I use p or br?

The p element marks up a paragraph of text. A paragraph is one or more sentences that deal with a single thought.

A line break (br) is mostly a presentational tool, and should be handled by CSS rather than HTML. However, there are a few cases where line breaks can be said to have semantic meaning, for instance in poetry, song lyrics, postal addresses and computer code samples. These can constitute legitimate uses for br, but using br to separate paragraphs is definitely an abuse of the br element.

On the other hand, p has a very clear semantic meaning: it denotes a paragraph. Sometimes web authors tend to treat p as a generic block-level container element, but that’s not correct. It’s not uncommon to see a label and an input field wrapped inside a p within a form, but I would argue that it’s semantically wrong. A label and an input field do not constitute a "paragraph".

22. What does "semantic" mean?

se-man-tic [si-'man-tik]
adj. Of, pertaining to, or arising from the different meanings of words or other symbols.

(definition from dictionary.com)

When we talk about "semantic markup", we mean the proper use of element types — based on their meaning — to mark up content. The opposite is "presentational markup" or "tag soup", where authors choose element types because of their default rendering, rather than their semantic meanings.

An example: This is a semantically correct way to mark up the top-level heading of a web page:

<h1>Heading Text</h1>

This is an unsemantic (presentational) way to do it:

<br><font size="7"><b>Heading Text</b></font><br>

The semantic richness of HTML is quite limited. HTML was originally used by physicists to exchange scientific documents, and that shows quite clearly in the set of available element types. HTML would probably have had a very different set of element types if it had been invented by accountants or librarians.

HTML has two semantically neutral element types as well: the block-level div and the inline-level span. Neither of those two implies any particular semantics about its content; div is just a "division of the document", while span is a "span of characters". On the other side of the spectrum we have element types with clearly defined semantics: p (paragraph of text), table (tabular data), ul (unordered list), and so on.

The purpose of HTML is to mark up the semantics of a document, and — to some extent — to show the structure of its content. HTML has nothing at all to do with the way this document looks in a browser (although browsers have a default style for each element type).

23. Should I replace b and i with strong and em?

Only if you really mean to emphasise something. These notations are not interchangeable.

In the Bad Old Days, authors would use b and i to emphasise words.

In the Equally Bad Modern Days, authors use strong and em to make text boldfaced or italic.

em signifies semantic emphasis. The content to which it is applied should have some sort of emphasis when read out loud (louder, more slowly). strong indicates even stronger emphasis, but is now often considered redundant (you could nest em elements to indicate increasing emphasis). Some experts recommend that strong be used only for certain page elements that should be clearly indicated (like a "current page" indicator), and not to mark up words or phrases in the body copy.

b and i have no semantics; they only indicate bold or italics. They are useful for adhering to typographic conventions that do not have a semantically correct element type in HTML. For instance, ship names are traditionally written in italics, but there is no ship element type in HTML. Thus we can use <i>Titanic</i>.

24. Why are layout tables considered harmful?
  • It is semantically wrong to mark up non-tabular information as a table.
  • They can cause accessibility or usability problems (especially with some assistive technologies), particularly when nested several levels deep.
  • They mix presentational issues with the content, making it difficult or impossible to achieve alternate styling and output device independence.
  • They bloat the document markup with lots of unnecessary HTML tags, which can be detrimental for low-bandwidth users (those using dial-up connections or mobile devices) as well as for the web server’s load and bandwidth.
25. Should I use divs instead of layout tables?

No, we should use semantically correct element types as far as possible, and only revert to divs when there are no other options.

Abusing divs is no better than abusing tables. We can set id and class attributes on virtually any element type. We can assign CSS rules to virtually any element type, not only to divs.

26. Are tables deprecated?

Not at all. table is the proper, semantically correct element type to use for marking up tabular data: information that has relationships in two or more dimensions. Tables are not deprecated, but layout tables are an issue.

27. What is the correct use of the address element type?

address is used to mark up contact information for the page (or for a part of a page). This can be a postal address, an email address, a telephone number, or virtually any contact details. address is a block-level element that can only contain text and inline elements. The default rendering is italic in most browsers, but that can be changed easily with CSS.

A common misconception is that address is meant to be used to mark up only postal addresses, but that is not the case.

28. What is the correct use of the dfn element type?

dfn is used to mark up the "defining instance" of a term. It’s a typographic convention, especially common in scientific documents, to italicise a new term — one with which the reader cannot be expected to be familiar — the first time appears in the text. The default rendering of dfn is thus italic.

A common misconception is that dfn means "definition", and many authors use it in the same way they use abbr or acronym (by using the title attribute to provide an explanation of the term). A certain term should only be marked up with dfn once in a document (where it is first used and explained).

29. What is the correct use of the var element type?

var is used to mark up a variable, or replaceable, part of some text. It’s a typographic convention to italicise such variables, which will be replaced by actual data in real life. For instance, in a telephone system manual, the instruction for relaying incoming calls to another extension could look something like this:

<kbd>* 21 * <var>extension</var> #</kbd>

Here, a var element is used to mark up "extension" (which will be italic by default). Someone trying to program the telephone system to relay his incoming calls to extension 942 would type "*21*942#". Thus the var element indicates that you shouldn’t actually type "e-x-t-e-n-s-i-o-n", but enter the actual extension number instead. The word "extension" is a variable.

A common misconception is that var should be used for marking up variables in programming code samples.

30. Should I use quotation marks within or around a q element?

No, the specification clearly says that it is the responsibility of the user agent to add quotation marks to inline quotations. Unfortunately, some older browsers (such as Internet Explorer 6) do not comply with the specification and will not add quotation marks. An option is to insert the quotation marks with JavaScript, and use some special styling with CSS to insert quotations for IE users with JavaScript disabled. Some CSS-only solutions have been proposed, but they will fail in non-CSS browsers such as Lynx.

31. What is the difference between abbr and acronym?

No one really seems to know the answer to this one! Even the HTML specification contradicts itself on this point.

abbr was a Netscape extension to HTML during the "browser wars". acronym was Microsoft’s extension. Both meant the same thing, more or less. Both element types were incorporated into the HTML specification, with different semantics. The problem is that no one seems to be able to explain what those semantics are.

Let us look at a couple of dictionary definitions, then:

ab-bre-vi-a-tion [uh-bree-vee-'ey-shuhn]
n. A shortened or contracted form of a word or phrase, used to represent the whole.
ac-ro-nym ['ak-ruh-nim]
n. A word formed from the initial letters or groups of letters of words in a set phrase or series of words.

The definition for acronym says that it is a word, i.e., it can be pronounced. Thus, "NATO" would be an acronym, formed from the initial letters in the phrase "North Atlantic Treaty Organization". "FBI", however, would not be an acronym according to the dictionary definition, because it is not pronounced as a word, but rather spelled out (eff bee eye). And this is where the problems begin. "FBI" is technically known as an initialism, about which the dictionary has the following to say:

in-i-tial-ism [i-'nish-uh-liz-uhm]
n. 1. A name or term formed from the initial letters of a group of words and pronounced as a separate word.
2. A set of initials representing a name, organization, or the like, with each letter pronounced separately.

The first definition is almost the same as for acronym, but the second is more relaxed. However, there is no initialism element type in HTML, and the confusion is exacerbated by the fact that "acronym" in normal American parlance is used as a synonym for "initialism".

The HTML specification offers the following definitions:

abbr: Indicates an abbreviated form (e.g., WWW, HTTP, URI, Mass., etc.).
acronym: Indicates an acronym (e.g., WAC, radar, etc.).

So far it looks like the specification is adhering to the dictionary definitions, which means that "FBI" should be marked up with abbr since it can’t be pronounced as a word. However, a few paragraphs further down, the specification says,

Western languages make extensive use of acronyms such as "GmbH", "NATO", and "F.B.I.", as well as abbreviations like "M.", "Inc.", "et al.", "etc."

Are you confused yet? I am. The safe thing to do then should be to always use abbr, since all acronyms are abbreviations, but not vice versa. However, there’s a slight problem with that approach. Microsoft was so miffed when the W3C decided to use abbr for abbreviations and initialisms instead of their acronym, that they actually refused to support abbr! (They’ve started supporting abbr in Internet Explorer 7, though.)

So, what’s a poor web author to do? Why should we even bother? It might be nice to have an element to attach a title attribute to, but we could use SPAN for that. The idea, allegedly, is that marking up abbreviations and acronyms would be beneficial for assistive technologies; especially screen readers. But screen readers tend to ignore abbr and acronym, since no one knows how to use them properly and Microsoft doesn’t support abbr. It’s a catch-22.

The answer to this frequently asked question is: I don’t know! I, personally, use abbr for obvious abbreviations like "Inc." and for initialisms like "FBI", and I use acronym for things that can be pronounced as words, like "GIF". But due to the ambiguity of the specification, I cannot fault anyone for marking up "FBI" as an acronym (although "Inc." certainly is not an acronym). And what about "SQL", which some spell out and others pronounce as "sequel"? (I’d use abbr.)

32. Why is <feature X> deprecated?

The most common "feature" that beginners ask about is the target attribute for links. This feature is deprecated (disapproved of) in HTML 4.01 Strict, but it’s still valid in HTML 4.01 Transitional. Many other element types and attributes that are allowed in Transitional are removed from Strict.

The reason for deprecating those items is that the W3C wants to promote the separation between content (HTML), presentation (CSS) and behaviour (JavaScript). Making an element centred within the viewport is a presentational issue; thus it should be handled by CSS instead of a center element. Opening a new browser window is a behavioural issue; thus it should be handled by JavaScript rather than a target attribute.

Typically, the deprecated features are those that arose during the browser war era of the late 1990s, when browser vendors were competing by adding various extensions to HTML to make it into some sort of page layout language. These features were included in HTML 3.2 to bring some sort of order to the chaos, but this is not what HTML was intended for. When HTML 4 was released, the authors tried to "reclaim the Web" by deprecating what they saw as "harmful" parts of HTML 3.2, at least in the Strict DTD.

In other words, things are deprecated for a reason. Don’t use those features unless you absolutely have to.

33. Must I have an alt attribute for every image?

Yes, the alt attribute is required for the img element type. Why? Well, not all users can see images and not all user agents can understand or display images. For example:

  • A person who is blind or has very low vision cannot see an image. A screen reader cannot describe an image.
  • Users with slow connections (dial-up or mobile) sometimes disable images for faster surfing.
  • Text browsers like Lynx do not support images.
  • Search engine bots cannot understand images.

Thus we have to provide a text equivalent for each image, using the alt attribute. This text equivalent should not describe the image; it should convey the equivalent information. Writing good text equivalents is not easy, and it takes a lot of practice. Remember that the text equivalent is displayed instead of the image.

So what is a good text equivalent for a given image? That depends on the context in which the image is used! It’s not like there is a single "perfect" text equivalent for each image. Let us look at an example: say we have an image of a grazing cow. This particular cow happens to be an Aberdeen Angus. Let us then consider a few use cases for this image.

  • In the first case, this image is used as a generic illustration for an article about beef cattle farming in Scotland. The actual cow isn’t germane to the article; it’s just an illustration, a decorative design element that draws the reader’s eye and relieves the monotony of the text. In this case, the image doesn’t convey any relevant information. Therefore it should have an empty text equivalent: alt="".
  • In the second case, the image is used on a children’s web site about farm animals. The page shows pictures of various animals: a horse, a sheep, a pig, a cow, etc. Next to each image is a block of text that presents some facts about each species. In this case, alt="Cow:" could be appropriate. It’s not important that it’s an Aberdeen Angus; the picture represents bovine quadrupeds in general.
  • In the third case, the image is used on a site about different breeds of cattle. Here it is used to illustrate what an Aberdeen Angus looks like, and how it is different from other breeds. The page comprises a number of images, each with a caption that identifies the breed, but no other textual information. In this case, the text equivalent should describe the particular attributes and traits that are specific to an Aberdeen Angus: the robust build, the massive chest, the relatively short legs, the buffalo-like hump behind the head, etc.
  • In the fourth case, the image is used on a photographer’s portfolio page. It’s one image among several others, with very different motifs. This is one of the few cases where the alt attribute might actually include a description of the image itself, e.g., "A black Aberdeen Angus grazing in the sunshine with Ben Nevis in the background."

As we can see, the appropriate text equivalent depends on the context. Sometimes (often, actually) it should be empty, because the image doesn’t convey any information that isn’t available in the accompanying text. Some claim that such images should be background images specified via CSS, but there are many cases where that is impractical and where the image is really part of the content — even though it doesn’t convey any useful information to those who cannot see it.

For images that contain text, the text equivalent should of course replicate the text in the image. For things like pie charts, the text equivalent should convey information about the percentages — the same information as the image conveys.

The alternate text shouldn’t be too long. Some browsers don’t word-wrap text equivalents, and they cannot be formatted in any way. If we need a longer text equivalent, we should put it somewhere else and link to it via the longdesc attribute.

Internet Explorer and old Netscape browsers display the alt attribute in a tool-tip when the user hovers the mouse pointer over the image. This constitutes an incorrect use of text equivalent data. We should use the title attribute for "tool-tip" information. To suppress the alternate text appearing in tool tips, we can use an empty title: title="".

34. What is the difference between class and id?

An id uniquely identifies a particular element in an HTML document. It’s like a social security number, providing a unique handle for that element. Just as two people cannot have the same social security number, no two elements in a document can have the same id. ids must be unique within the page.

A class says that an element has some traits which it (possibly) shares with other elements. An element can belong to more than one class. An analogy could be professions: a person could be both a carpenter and a nurse, and there are many carpenters and many nurses. (They all have unique social security numbers, though.)

Both ids and classes are mainly used with CSS and/or JavaScript. In CSS, an id has higher specificity than a class, making it easy to specify special rules for a specific element. With JavaScript we can look up an element using its id (document.getElementById()).

We assign ids to page elements that can occur, at most, once per page, like a navigation menu, a footer, a sidebar, etc. We can also assign ids to specific elements that only occur once in the whole site, like a specific image, if we want to have certain CSS rules for it, or manipulate it with JavaScript.

We assign classes to elements that share some common traits, usually display properties via CSS rules.

ids and class names should be as "semantic" as possible. They should describe what something is, not what it looks like. Thus, id="menu" is much better than id="left"; especially if we redesign and move the menu to the right-hand side.

ids and class names are case sensitive, even in HTML. We shouldn’t rely on case-sensitivity, though (i.e., we should not use names that differ only in case).

35. Why doesn’t id="123" work?

Values for the id, name and class attributes must start with a letter (A-Z or a-z).

36. Why doesn’t <a href=My Cool Page.html> work?

There are two reasons in this case.

Attribute values that contain characters other than letters, digits and a few other characters must be enclosed in quotation marks (double or single). Any attribute value that needs to contain a space, for instance, must be quoted. The easiest and safest solution is to always quote attribute values. To include quotation marks in a quoted value, we have two options. We can either use the "other" quotation mark to enclose the value (alt='My "new" car', alt="Jane's car"), or use an entity or reference (alt="My &quot;new&quot; car", alt='Jane&#39;s car'). (Note that the &apos; entity cannot be used with HTML.)

The second reason is that there are spaces in the URI. These need to be encoded as shown here:

<a href="My%20Cool%20Page.html">

"%20" means "a character with code point 0x20". 0x20 is the code point for the space character. This applies to URIs only, not to attribute values in general.

37. How can I include an HTML page in another HTML page?

With a Strict DTD, there is only one valid option: the OBJECT element type:

<object type="text/html" href="http://example.com/foo.html">  
 Alternate content here for browsers that don't support OBJECT.  
</object>

Unfortunately, support for object is all but non-existent in Internet Explorer.

With a Transitional DTD, we can also use the iframe element type:

<iframe src="http://example.com/foo.html">  
 Alternate content here for browsers that don't support IFRAME.  
</iframe>

A much better approach is to handle inclusion on the server-side. Using server-side includes (SSI) is the simplest way to include a file into another, as long as they are from the same domain:

<!--#include virtual="/foo.shtml"-->

Note that this technique cannot be used to include a complete HTML document within another, though; it can be used only with fragments of HTML.

Other server-side technologies allow us to perform more advanced tasks. Your web server must support those technologies, of course. Often, shared servers with free hosting don’t provide any such technologies — not even SSI.

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

No Reader comments

Comments on this post are closed.