Deprecated HTML elements

A list of HTML elements which have been deprecated, and the elements with which they should be replaced.

In many cases where the official W3C recommendations have deprecated HTML elements or attributes, they don't state clearly which replacements to use for those elements. They usually hint as to where you should look, but all too often, you're on your own. And that's where this document comes in, which tries to provide (nearly) all the answers that the W3C recommendations neglect to give.

Notes:

¹ Not exactly deprecated, but W3C says these elements are discouraged in favour of stylesheets.
² Never a part of the official definition of HTML, this element shouldn't be used.
³ Other problems. Not recommended.

Element examples

<ACRONYM> and <ABBREV>

Example: <ACRONYM title="First Online Righteous Church of Equality"> FORCE </ACRONYM>

Has exactly the same meaning as <abbr>.

Result: <abbr title="First Online Righteous Church of Equality"> FORCE </abbr>

<APPLET> and <APP>

Example: <APPLET CODE=clock.class NAME=clockprog ALIGN=MIDDLE width="200" height="200" ALT=Clock HSPACE=10 VSPACE=3> Java clock </APPLET>

Use an object with a codetype of "application/java" and a classid for the name of the file containing the code.
Additionally, replace the HSPACE and VSPACE attributes with a margin property.
And replace the ALIGN attribute with either a float or a vertical-align property, according to this list.

Any parameters the program may need, will be submitted in the usual way: with param elements in the contents of the object.
The ALT attribute, however, is lost; object does not support it. Not that it matters greatly, since no browsers use the alt attribute anyway, but it would have been nice to have a one-to-one translation. (Some sources mention title as a replacement for ALT, but I'm not sure if that would amount to the same thing.)
And the NAME attribute also doesn't seem to correspond with any object attribute: although object does have name, it's not the same type of attribute: in applet it's defined as case sensitive, while in object, it's not. More research needed.

Result: <object codetype="application/java" classid="java:clock.class" style="vertical-align:middle; margin:3px 10px" width="200" height="200"> Java clock </object>

<B>

Example: <B> This is bold </B>

In HTML 4.01, this element is discouraged in favour of stylesheets.
Usually, this is replaced by:

<strong> This is bold </strong>

but only if you really mean "strong emphasis". If you just want to make something blacker than normal, use a span with a font-weight property.

Result: <span style="font-weight:bold"> This is bold </span>

Note: although the font property also seems to work as well as font-weight in some browsers, it's not supposed to! Don't use font just to change the weight.

HTML5 has changed the meaning of this element to something resembling <mark>, but I'm not sure about the usefulness of such a move.

<BASEFONT>

Example: <BASEFONT SIZE=4 FACE=Verdana>

This isn't properly implemented in all browsers. The browsers that do support this, sometimes treat it almost exactly like <FONT>, which is not the way the W3C page describes it. So handle this the same way you handle <FONT>: replace by anything containing a style. If no elements are available that you can add the style to, use a span. The most recent browsers all consistently map the old font sizes to the new styles as follows:

SIZE value font-size value
1 x-small
2 small
3 medium
4 large
5 x-large
6 xx-large
7 2rem

Notes:

Result: <span style="font-family:Verdana; font-size:large"> .. </span>

which can be made smaller by folding the font-size and the font-family together in a font property:

<span style="font:large Verdana"> .. </span>

<BGSOUND>

Example: <BGSOUND SRC=sound.wav BALANCE=0 DELAY=1 LOOP=3 VOLUME=-100>

This is not standard HTML. It should be replaced by an object with a type of "audio/wav" (or whatever the type is).
Not sure how to deal with the LOOP. More research needed.

Result: <object type="audio/wav" data="sound.wav"> </object>

<BIG>

Example: <BIG> This is big </BIG>

In HTML 4.01, this element is discouraged in favour of stylesheets. It's obsolete in HTML5.

Use any inline element (preferably span) with a font-size property.

(Note: not all browsers interpret BIG the same as font-size:larger. Sometimes, big is bigger than larger. There's not much we can do about that though. Take consolation from the fact that the differences between browsers when using larger are not as great as when using BIG.)

Result: <span style="font-size:larger"> This is big </span>

Example: <BLINK> This is blinking text </BLINK>

Get out of here.

<CENTER>

Example: <CENTER> This is centered </CENTER>

Officially, this is shorthand for:

<div ALIGN=CENTER> This is centered </div>

However, since ALIGN also is deprecated, this should further be replaced by

<div style="text-align:center"> This is centered </div>

There is a problem with that though. Not all browsers treat <div ALIGN=CENTER> and <div style="text-align:center"> the same. Especially tables in the div are problematic, so give all tables in a centered div a style of left-margin:auto; right-margin:auto, and cells in those tables text-align:left. By the way, tables in <center> elements don't behave the same on all browsers, but with this CSS solution, they will.

<COMMENT>

Example: <COMMENT> This is a comment </COMMENT>

This is not standard HTML. Replace by the official comment markers, making sure that the comment itself does not contain -- (which causes severe problems in some circumstances).

Result: <!-- This is a comment -->

<DIR>

Example: <DIR COMPACT> .. </DIR>

Although not originally meant to be identical to ul (DIRs are supposed to be multi-column), most browsers still display DIR and ul the same. That's probably the reason DIR got deprecated.
And the COMPACT attribute is not supported by any browser. Just leave it out.

Result: <ul> .. </ul>

<EMBED>

Example 1: <EMBED codebase="." CODE=clock.class width="200" height="200">

Example 2: <EMBED ALIGN=LEFT BGCOLOR=GREEN HSPACE=10 VSPACE=3 LOOP=TRUE PLAY=TRUE QUALITY=HIGH PLUGINSPAGE=../getflashplayer SRC=clock.swf type="application/x-shockwave-flash" width="90" height="90">

This is not standard HTML. It should be replaced by object.
What this command does, depends on its attributes. In the first example, it runs a Java applet and behaves exactly like the APPLET element. See APPLET for details.
In the second example, replace the ALIGN attribute with either a float or a vertical-align property, according to this list.
Additionally, replace the HSPACE and VSPACE attributes with a margin property.
PLUGINSPACE: unknown. Need research.
LOOP, PLAY and QUALITY become params for the object.

Result 1: <object codebase="." codetype="application/java" classid="java:clock.class" style="border:2px solid;" width="200" height="200"> Java clock </object>

Result 2: <object type="application/x-shockwave-flash" data="clock.swf" style="float:left; background-color:green; margin:3px 10px" width="90" height="90">
<param name="loop" value="true">
<param name="play" value="true">
<param name="quality" value="high">
SWF clock </object>

(Note: I can't get this example to play under IE. The other browsers are no problem. Need research.)
HTML5 note: some versions of the HTML5 draft have redefined <embed> in such a way that you can use it again, but <NOEMBED> remains deprecated, so you will need to convert to <object> if you need some fallback mechanism. Or you can look into HTML5 specific elements like <audio> and <video> where appropriate.

<FONT>

Example: <FONT COLOR=YELLOW FACE=Verdana SIZE=4> .. </FONT>

Replace by anything containing a style. If no elements are available that you can add the style to, use a span. The most recent browsers all consistently map the old font sizes to the new styles as follows:

SIZE value font-size value
1 or -2 x-small
2 or -1 small
3 medium
4 or +1 large
5 or +2 x-large
6 or +3 xx-large
7 or +4 2rem

Notes:

Result: <span style="color:yellow; font-family:Verdana; font-size:large"> .. </span>

which can be made smaller by folding the font-size and the font-family together in a font property:

<span style="color:yellow; font:large Verdana"> .. </span>

Some browsers (Netscape and its descendants) support other, non-standard attributes to <FONT>:

Example: <FONT POINT-SIZE=20 FONT-WEIGHT=800> .. </FONT>

These can be replaced by font-size in points and font-weight, respectively.

Result: <span style="font-size:20pt; font-weight:800"> .. </span>

Note: although some early drafts for HTML5 tried to un-deprecate <font>, don't take those attempts seriously.

<FRAMESET>, <FRAME>, <NOFRAMES>

Example: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<title>frameset demo</title>
<frameset cols="200, *">
<frame src="left.html" name="left">
<frame src="right.html" name="right">
<noframes>Sorry, no frames today</noframes>
</frameset>
</html>

There are no more special versions of HTML for special purposes like this. Use a server-side mechanism to fill parts of the page, or use iframes instead.
You will need CSS that is different from case to case; it should be made to measure for the exact layout of the frameset. In this example, where the left frame is 200 pixels wide and the right frame fills the rest:

Result: <!DOCTYPE html>
<html>
<title>frameset repl demo</title>
<style>
html {height:100%;}
body {height:100%; margin:0; padding-left:206px;}
iframe {width:100%; height:100%; float:left; border:none}
iframe[name='left'] {border-right:6px ridge; width:200px; margin-left:-206px;}
</style>
<body>
<iframe src="left.html" name="left">Sorry, no frames today</iframe>
<iframe src="right.html" name="right"></iframe>
</html>

The 206 px padding on the body is needed for the left frame and the border, so that the rest is 100% wide to fit the other frame in. You get the idea.

<HGROUP>

Example: <HGROUP>
<h1>This is a webpage</h1>
<h2>This is a subdivision of the page</h2>
</HGROUP>

Part of a early HTML5 draft, but no longer in use. If you just want to keep the h1 and the h2 together, there's no need. This requires no extra markup. But if you want to mark off this part of the page as the header, you can use <header>.

Result: <header>
<h1>This is a webpage</h1>
<h2>This is a subdivision of the page</h2>
</header>

<I>

Example: <I> This is italic </I>

In HTML 4.01, this element is discouraged in favour of stylesheets.
Usually, this is replaced by:

<em> This is italic </em>

but be aware that this use is only valid if you really meant emphasis - a phrase that requires more attention than the words around it. Otherwise another element might be more appropriate; if you meant to mark something with a meaning, for instance, mention a song title by name, replace with <cite>. Talk about a variable in computer code, then you'd use <var>. But if there's really no semantic meaning to your italics, use a <span> with a font-style property.

Result: <span style="font-style:italic"> This is italic </span>

Note: although the font property also seems to work as well as font-style in some browsers, it's not supposed to! Don't use it here.

HTML5 has changed the meaning of this element to something resembling <mark>, but I'm not sure about the usefulness of such a move.

<IFRAME>

Example: <IFRAME src="clock.html" ALIGN=LEFT> clock in frame </IFRAME>

This element does not occur in all DTDs. If you use it and you want your HTML to validate, either use a HTML version that does contain it, or replace it by an object with a type of "text/html".
Note that most browsers I've tested do not require the type attribute to be present. However, it is strongly recommended that it is.
Also, replace the ALIGN attribute with either a float or a vertical-align property, according to this list.

Result: <object type="text/html" data="clock.html" style="float:left"> clock in frame </object>

<ILAYER>

Example: <ILAYER LEFT=10 TOP=20> offset </ILAYER>

This is only supported by older versions of Netscape (pre-Gecko).
Replace it with a relatively positioned span (if the ilayer doesn't have a SRC) or an object (if it does) with the appropriate properties.

Result: <span style="position:relative; left:10px; top:20px"> offset </span>

<ISINDEX>

Example: <ISINDEX PROMPT="What is it? ">

Use a text input and put the prompt in the normal text flow:

Result: What is it? <input>

<KEYGEN>

Example: <KEYGEN NAME=name CHALLENGE=challenge>

This is not standard HTML. I have no idea how this is supposed to work and what to replace it with. The W3C recommendations never mention anything about encryption keys. Can anybody point me to somewhere where this is explained, with examples?

<LAYER>

Example 1: <LAYER WIDTH=90 HEIGHT=60 BGCOLOR=#DDDDBB Z-INDEX=2> A layer </LAYER>

Example 2: <LAYER LEFT=80 TOP=50 WIDTH=90 HEIGHT=60 SRC=contents.html Z-INDEX=1> </LAYER>

This is only supported by older versions of Netscape (pre-Gecko).
The behaviour of a LAYER depends on its attributes, so deciding what to replace it with isn't very straightforward.
Without any attributes, it can be replaced by a simple div. If it has a fixed position (with LEFT and/or TOP), the div should get an absolute position.
When there's a SRC attribute, if the SRC points to a HTML file, use an object which displays the file, and ignore the LAYER's content. If, on the other hand, the SRC points to a picture, display the picture first, followed by the content.
And finally, the Z-INDEX attribute is replaced with a z-index property.

Result 1: <div style="width:90px; height:60px; background-color:#ddb; z-index:2"> A layer </div>

Result 2: <object style="position:absolute; left:80px; top:50px; width:90px; height:60px; z-index:1" type="text/html" data="contents.html"> </object>

<LISTING>

Example: <LISTING> A long &amp; boring list. </LISTING>

Replace this with <pre> elements with <code> blocks in them.
Also, the formal definition says that all characters inside are visible as plain text, so you should replace every & with &amp;, every < with &lt;, and for symmetry purposes, every > with &gt;. However, the browsers don't behave like this, so you may be better off not doing this if you want the result to look the same.
Note: the default width of a listing is 132 characters, so you can also set the width to 132ch (in the newest browsers only).

Other sources say the width in pixels should remain the same, but the font size should scale according to the WIDTH attribute, so that WIDTH characters is as wide as a normal 80 char line. So the font-size should be 80/WIDTH, or 60.6% for a default width of 132.

Result: <pre style="width:132ch"><code> A long &amp; boring list. </code></pre>

as IE: <pre style="width:132ch; font-size:60.6%"><code> A long &amp; boring list. </code></pre>

<MARQUEE>

Example: <MARQUEE LOOP=20 DIRECTION=RIGHT SCROLLAMOUNT=5 SCROLLDELAY=60> rolling... </MARQUEE>

This is not standard HTML. There is a W3C draft for doing the same in CSS, but it doesn't have properties for SCROLLAMOUNT and SCROLLDELAY, and not many browsers support it yet.

Result: <div style="overflow-style:marquee-line; marquee-play-count:20; marquee-direction:forward"> rolling... </div>

At the time of this writing, Safari supports marqueeing with CSS, but it has some different properties and values.

Safari: <div style="overflow-x:-webkit-marquee; -webkit-marquee-repetition:20; -webkit-marquee-direction:forwards"> rolling... </div>

Example: <MENU COMPACT> .. </MENU>

If the MENU is used as a list, replace it by ul.
And the COMPACT attribute is not supported by any browser. Just leave it out.
Note: Although the official W3C recommendations mention that MENU has the same structure as UL, just different rendering, I haven't found out for certain what those rendering differences are supposed to be. Most browsers display this identically to ul; only Chrome uses the style list-style-position:inside by default.

Result: <ul> .. </ul>

as Chrome: <ul style="list-style-position:inside"> .. </ul>

Note: this is only for MENU elements used as lists. In case they're used in their newer HTML5 meaning (i.e. as menus), you don't have to replace them, naturally!

<MULTICOL>

Example: <MULTICOL COLS=3 GUTTER=12 WIDTH=600> .. </MULTICOL>

This is not standard HTML. It divides text into a number of columns of the same width, where COLS is the number of columns to display (default=1) and GUTTER is the width between the columns in pixels (default=10).
Replace by a block element with the following style: column-count = COLS and column-gap = GUTTER (in px). Also set the width if WIDTH is given.

Result: <div style="column-count:3; column-gap:12px; width:600px"> .. </div>

Notes: not all browsers support column-count and column-gap yet. Use with care.
And some sources state that the WIDTH attribute specifies the width of each column, making the total structure in the example 3×600+2×12 pixels wide. A test with Netscape 4, however, proves this incorrect: the entire structure becomes as wide as WIDTH.

<NEXTID>

Example: <NEXTID N=A78>

This element does nothing. Remove it.

Note: The W3C entry for this element says, Use GUIDs instead. They don't really elaborate though.

<NOBR>

Example: <NOBR> This is an unbroken line </NOBR>

This is not standard HTML. To ensure that the browser doesn't break your text in two where you don't want it, use an inline element with a white-space property.

Result: <span style="white-space:nowrap"> This is an unbroken line </span>

Alternatively, you can also replace the spaces by non-breaking spaces, but I can't recommend that, since it actually changes the content of the document.

<NOEMBED>

Example: <EMBED whatever><NOEMBED> "embed" doesn't work! </NOEMBED>

This is not standard HTML. It's used to indicate alternate text to be displayed instead of embedded objects in case the EMBED doesn't work. If you replace all EMBEDs with objects, you don't need the <NOEMBED> elements; just use their contents for the contents of the <object> elements.

Result: <object whatever> "object" doesn't work! </object>

<NOLAYER>

Example: <NOLAYER> "layer" doesn't work! </NOLAYER>

This is not standard HTML. It's used to indicate alternate text in place of LAYER elements in case the layer doesn't work. (Browsers which don't understand the LAYER and NOLAYER elements, just render the content, while browsers which do know LAYER can ignore the NOLAYER altogether.)
If you can replace LAYERs with objects, you can use the contents of the NOLAYER for the contents of the object elements.
For LAYERs replaced with divs, you don't need the content of the NOLAYER at all, since all browsers recognise div, and an alternative in case it doesn't work isn't necessary.

Result: <object whatever> "object" doesn't work! </object>

<NOSCRIPT>

Example: <NOSCRIPT> JavaScript is off! </NOSCRIPT>
<script type="application/javascript">
alert('JavaScript is on!');
</script>

The standards contradict each other for this element. Sometimes it's deprecated, sometimes it isn't. Sometimes its contents are CDATA, sometimes they're not. Sometimes it doesn't work as it's supposed to, showing the contents even if JavaScript is enabled. So it might be best to avoid this element altogether and use other means to show content when JavaScript is disabled.

For instance: <span id="NOSCRIPT"> JavaScript is off! </span>
<script type="application/javascript">
document.getElementById('NOSCRIPT').style.display = 'none';
alert('JavaScript is on!');
</script>

<PLAINTEXT>

Example: <PLAINTEXT> And the rest is plain!

As I understand it, the very earliest browsers could use only HTML files and didn't know about any other kinds of file. In those days, nobody had heard about MIMEtypes. So in order to display a plain text file in a browser, what you did was take a text editor and put some info on top of it, e.g.,

<title>A text file</title><plaintext>

and then the browser would display it without complaining.
However, for many years now, browsers have had no trouble whatsoever displaying text files, and this element hasn't been necessary since then. Just leave the text files intact.

<RB>

Example: <ruby><RB>Ruby base text</RB><rt>with annotation</rt></ruby>

This element was never necessary. You can put the text directly in the <ruby>.

Result: <ruby>Ruby base text<rt>with annotation</rt></ruby>

<S> and <STRIKE>

Example: <STRIKE> Struck out text </STRIKE>

If you mean to show removed or no longer relevant content, use <del>. Otherwise use any inline element (preferably span) with a text-decoration style property.

Result: <span style="text-decoration:line-through"> Struck out text </span>

Note: HTML5 declares only <STRIKE> as obsolete; <S> has been made more or less similar to <del>. I can't recommend it at all though.

<SERVER>

Example: <SERVER> .. </SERVER>

This runs JavaScript on the server, the Netscape Enterprise Server to be precise, so unless you can find a server like that these days, you may have do some work to make it perform as intended.
You can use classic ASP with JScript as the server-side language, replace each <SERVER> with <% and each </SERVER> with %>, and then fiddle until it works.
Unfortunately, I don't have an exhausive list of differences between the two dialects. One change would be to change write to response.write, but then you're on your own. Good luck!

<SMALL>

Example: <SMALL> This is small </SMALL>

In HTML 4.01, this element is discouraged in favour of stylesheets.

Use any inline element (preferably span) with a font-size property.

Result: <span style="font-size:smaller"> This is small </span>

Note: because Opera has troubles interpreting the <SMALL> command correctly - sometimes, "small" text is larger than the surrounding normal text - doing this replacement will make for a difference in result in Opera. In other browsers, you can't see the difference.

In HTML5, this element has been redefined as "small print". However, since the HTML5 specification is still changing, and also because there's no symmetry between this and its counterpart <BIG>, I hesitate to recommend this.

<SPACER>

Example 1: <SPACER TYPE=HORIZONTAL SIZE=80>

Example 2: <SPACER TYPE=VERTICAL SIZE=70>

Example 3: <SPACER TYPE=BLOCK WIDTH=80 HEIGHT=70 ALIGN=RIGHT>

This is not standard HTML. In fact, spacers have been discarded by even Netscape itself.
In modern browsers, you can emulate them with empty span elements, as follows:

Create a span element with no borders, no margins and the appropriate horizontal or vertical padding.
If the SPACER has an ALIGN attribute, add a float property.
If the SPACER is vertical, add display:block.

Result 1: <span style="padding:0 80px 0 0;"></span>

Result 2: <span style="padding:70px 0 0 0; display:block"></span>

Result 3: <span style="padding:70px 80px 0 0; float:right;"></span>

A special case is when the spacer occurs at the beginning of a block of text, like a paragraph. In that case, you can replace it with a text-indent style property on the paragraph.

<TT>

Example: <TT> This is monospaced </TT>

In HTML 4.01, this element is discouraged in favour of stylesheets. It's obsolete in HTML5.
What to replace it with, depends on what purpose you had for using it.

Used for purpose Replace with
Computer output (as on a Teletype) samp
Computer input (from keyboard) kbd
Computer code (script, listing) code
Anything else use a style property

Result: <span style="font-family:monospace"> This is monospaced </span>

Note: Some browsers use different font families and/or sizes for this property than they do for elements like <TT> and <pre>. If you want to be sure the same font is used, specify a font family with CSS.

<U>

Example: <U> Underlined text </U>

Use any inline element (preferably span) with a text-decoration property.

Result: <span style="text-decoration:underline"> Underlined text </span>

HTML5 has changed the meaning of this element to something resembling <mark>, but I'm not sure about the usefulness of such a move.

<WBR>

Example: <NOBR> This is almost an <WBR>unbroken line </NOBR>

This element, like <NOBR>, is not standard HTML. To control where the browser can break, use runs of text with style nowrap with normal spaces in between.

Result: <span style="white-space:nowrap">This is almost an</span> <span style="white-space:nowrap">unbroken line</span>

HTML5 has undeprecated this, but without undeprecating <nobr> for whatever reason.

<XMP>

Example: <XMP> This is an <element>. </XMP>

Replace this with a <pre> element and replace every & in the content with &amp;, every < with &lt;, and for symmetry purposes, every > with &gt;.
The content of the example was to be 80 characters wide, so you can give the resulting <pre> width:80ch if you want.

Result: <pre style="width:80ch"> This is an &lt;element&gt;. </pre>

Miscellaneous

Positional ALIGN attribute

The ALIGN attribute on APPLET, EMBED or IFRAME specifies the position with respect to its context.

Here's a complete list, mapping all values to the most similar style property value.
Please note that not all ALIGN values are official W3C values; the W3C column marks the formally defined ones.

ALIGN value W3C vertical-align value
ABSBOTTOM vertical-align:text-bottom
ABSMIDDLE vertical-align:middle
BASELINE vertical-align:baseline
BOTTOM vertical-align:baseline
LEFT float:left
MIDDLE vertical-align:middle
RIGHT float:right
TEXTTOP vertical-align:text-top
TOP vertical-align:top

Does using styles make your document larger?

Many style names are longer than the corresponding attribute names, and translating them inline (as in the examples in this document) can make your HTML document look bloated. However, first of all, it's possible to fold many properties into one.
For instance, let's suppose that you want to want to display the contents of a td cell in the Verdana font and underlined. In the old system, you'd write

<td><FONT FACE=Verdana><I> Content </I></FONT></td>

Following the guidelines in here to the letter would leave you with this result:

<td><span style="font-family:'Verdana'><span style="font-style:italic"> Content </span></span></td>

But this can be written a lot more compact.
First of all, you can put both properties in one style attribute in the td element and dispense with both spans.

<td style="font-family:'Verdana'; font-style:italic"> Content </td>

And you can use the shorthand font property for those two properties (if you don't mind the other font properties to be reset to their defaults):

<td style="font:italic medium 'Verdana'"> Content </td>

But CSS shows its real strength when you decide to give all your tds this style.
Then you can put the style in the document's stylesheet

<style type="text/css">
td {font:italic medium 'Verdana'}
</style>

and code your tds all as if they had no decoration at all:

<td> Content </td>

which, if you have a lot of tables in your document, comes out a lot smaller, and more readable, than what you started out with.