Fixing Deprecated and Obsolete HTML Elements
An "obsolete element" or "obsolete attribute" error means your page still uses presentational HTML from the 1990s and early 2000s, such as the centre and font tags, align and bgcolor attributes, or named anchors.
Browsers still draw most of it, so nothing looks broken, but the markup mixes styling into content, fights your stylesheet and fails validation on every page it touches. This guide shows where these tags hide, what replaces each one, how to clear them from templates and stored content in bulk, and which similar-looking tags are perfectly valid.
- What "obsolete" means in the validator
- Obsolete elements and what replaces each one
- Obsolete attributes, which are far more common
- Tags that look old but are valid
- Finding every instance, not just the ones on one page
- The fix, step by step
- Edge cases and awkward examples
- Keeping obsolete markup from coming back
- Questions and answers
What "obsolete" means in the validator
The HTML standard, maintained by WHATWG as a living document, keeps a list of features that authors must not use. The validator reports them with messages such as The center element is obsolete. Use CSS instead. or The align attribute on the div element is obsolete. Use CSS instead. People often call these "deprecated", which was the HTML 4 term for features on their way out; in current HTML they are simply non-conforming.
Obsolete does not mean unsupported. Browsers are required to keep rendering most of these features
so that old pages still work, which is exactly why they survive for years unnoticed. A handful have genuinely
stopped working: <applet> needed a Java plugin that no browser loads any more, and
<keygen> was removed from the standard and from browsers. For the rest, the cost is
not a broken page today but a set of quieter problems:
- Styling that ignores your stylesheet. A
<font color>tag inside a paragraph overrides the colour your theme sets, so a rebrand or a dark mode leaves random red or grey text behind. - Layout that cannot respond. A table with a fixed
width="780"attribute will not shrink on a phone without extra CSS to undo it. - Noise in every audit. A single
<center>in a footer template produces the same error on every URL on the site, burying the errors that matter. - Meaning lost for assistive technology. A
<font size="6">used as a heading looks like a heading but is announced as ordinary text.
bgcolor
and align. Do not "fix" an email template against web validation rules; this guide is about
pages served on your website.Obsolete elements and what replaces each one
The right replacement depends on what the old tag was doing. Some were purely visual and become a CSS rule; others were standing in for an element with real meaning.
| Obsolete element | What it did | Replace with |
|---|---|---|
<center> | Centred its contents | A class with text-align: center
for text, or margin-inline: auto for a block with a width |
<font> | Set face, size and colour | Remove it and let the theme
style the text; if the emphasis matters, use <strong>, <em> or
a heading |
<big>, <tt> | Larger text, monospace text | A
class with font-size; <code>, <kbd> or <samp>
when it really is code or input |
<strike> | Line through text | <s> for no-longer-accurate
text (an old price), <del> for a recorded removal |
<acronym> | Marked an abbreviation | <abbr>,
with the expansion in the text the first time it appears |
<marquee>, <blink> | Scrolling or flashing text | Static
text. If movement is essential, a CSS animation that respects prefers-reduced-motion and
can be paused |
<frameset>, <frame>, <noframes> | Split the window into separate documents | Real pages sharing a header and navigation through your templates;
<iframe> only for genuinely embedded third-party content |
<dir> | A directory list | <ul> |
<nobr> | Prevented line breaks | A class with white-space: nowrap |
<applet> | Embedded a Java applet | Nothing will run it now; replace the feature or remove it |
<basefont>, <spacer>, <listing>, <xmp>,
<plaintext> | Legacy typography and preformatted text | CSS on the body
or container; <pre> with escaped content for preformatted text |
Flashing content also carries an accessibility risk of its own: WCAG 2.2 limits content that flashes
more than three times a second, and moving content that runs for more than five seconds needs a way to
pause it. Deleting a <marquee> fixes the validation error and that concern together.
Obsolete attributes, which are far more common
On most sites the elements are rare but the attributes are everywhere, usually in tables, images and iframes copied from old embed codes. The validator names the attribute and the element it sits on, which tells you exactly what to search for.
| Attribute | Typically found on | Modern equivalent |
|---|---|---|
align | div, p, img, table,
td, headings | text-align for text; float, flexbox or margin-inline: auto
for boxes and images |
valign | td, tr | vertical-align on the cells |
bgcolor, background | body, table,
td | background-color, background-image |
width, height | table, td, th | width
in CSS (note: on img, video and iframe these attributes are valid
and should stay) |
border, cellpadding, cellspacing | table | border
and padding on cells; border-collapse or border-spacing on the
table |
border, hspace, vspace | img | border
and margin in CSS |
frameborder, scrolling, marginwidth | iframe
from old embed codes | border: 0 in CSS; overflow is controlled by the embedded page |
name | a used as a jump target | An id on
the heading or section being linked to |
summary | table | A <caption>, or a
sentence before the table explaining it |
language, charset | script | Remove; serve the script file as UTF-8 |
clear | br | clear in CSS on the next block |
size, noshade, width | hr | border,
height and width on hr in CSS |
Warnings that are not errors
Two messages look similar but are warnings only: The type attribute is unnecessary for JavaScript
resources on <script type="text/javascript">, and The type attribute
for the style element is not needed and should be omitted on <style type="text/css">.
Removing the attribute is harmless and tidies the report, but it changes nothing for visitors. Do not
remove type="module" or type="application/ld+json": those change how the script
is treated.
Tags that look old but are valid
Several short presentational-sounding elements were kept in HTML5 and given a defined meaning. Replacing them wholesale is unnecessary and can remove meaning you wanted.
<b>: text drawn to attention without extra importance, such as a product name in a review or a keyword in a summary. Use<strong>when the words are genuinely important.<i>: a different voice or mood, a technical term, a foreign phrase or a ship name. Use<em>for stress that changes the sentence's meaning.<u>: an unarticulated annotation, such as a spelling mistake mark. Avoid it for plain emphasis, because readers expect underlined text to be a link.<s>: content that is no longer accurate, such as a crossed-out original price next to a sale price.<small>: side comments and small print, such as copyright lines or terms under a price.<hr>: a thematic break between sections of content.widthandheighton<img>: valid and recommended, because they let the browser reserve space before the image loads and reduce layout shift.
<table width= and <td width=, never the attribute alone.Finding every instance, not just the ones on one page
Validating one URL shows the problem; it does not show its reach. Obsolete markup lives in three places, and each needs its own search.
1. Templates and theme files
Search the code base for the tag and attribute names. From the theme or project folder, a recursive search catches most of them in one pass:
grep -rniE "<(center|font|big|tt|strike|acronym|marquee|blink|nobr|dir)[ >]" .
grep -rniE "(bgcolor|cellpadding|cellspacing|valign|frameborder)=" .
grep -rniE "<a [^>]*name=" .
Anything found here affects every page built from that template, so fix these first.
2. Content stored in a database
Posts, product descriptions and pages written years ago, or pasted from Word, Dreamweaver or an old site, keep their original markup. In WordPress you can find them with a read-only query before changing anything:
wp db query "SELECT ID, post_title FROM wp_posts
WHERE post_status = 'publish'
AND post_content REGEXP '<(center|font)[ >]'"
Adjust the table prefix if yours is not wp_. On hosted platforms without database access,
export the content (Shopify's product CSV export includes the body HTML) and search the file.
3. Third-party output
Embed codes, old widgets and some plugins or apps print obsolete attributes themselves, most often
frameborder on an iframe. If you cannot edit the output, note it as a known issue and ask
the supplier for a current embed code; many now provide one without the old attributes.
Run the HTML Checker on one page of each template type as well. The same obsolete element reported on every sample is a template problem; one that appears on a single URL is content.
The fix, step by step
Step 1
List every obsolete element and attribute
Run the HTML Checker on a sample of URLs covering each template: the home page, a category or listing page, a product or service page, an article and the contact page. Copy every message containing the word obsolete into a simple list with the element, the attribute and the URL. Group identical messages together, because one footer tag repeated on fifty pages is a single fix, not fifty separate problems to chase.
Step 2
Trace each one to a template or to stored content
For each group, decide where the markup comes from. If it appears on every sample page, search the theme or template files for the tag name. If it appears on one page only, it is almost certainly inside that page's stored content. If it sits inside an iframe or widget code, it is third-party output. Write the source next to each item, because templates, content and embeds are fixed in completely different ways.
Step 3
Create CSS classes for the effects you need to keep
Before deleting anything, decide which visual effects still matter. Add a small
set of named classes to your stylesheet, such as .text-centre, .no-wrap or
.table-bordered, rather than recreating each old attribute with a one-off style. A handful
of reusable classes keeps the replacement consistent, lets editors apply them from the editor, and makes
the next redesign a stylesheet change instead of another round of content editing.
Step 4
Replace the markup in templates
In
the theme or template files, swap each obsolete tag or attribute for its modern equivalent from the tables
above, using the classes you created. Work in a child theme, a duplicated theme or a branch, never directly
on the live files. Replace <center> wrappers with a div carrying your
centring class, remove <font> tags entirely, and move table widths, borders and padding
into CSS.
Step 5
Clean stored content in bulk, with a backup
Take a full database or content export first. For simple cases, such as unwrapping <font>
tags or replacing <center> with a classed div, a careful search and replace
across stored content is safe. Run it as a dry run first and read a sample of the proposed changes. Edit
unusual pages by hand, especially old tables used for layout, which usually need rebuilding rather than
patching.
Step 6
Swap named anchors for id attributes
Old
in-page links often point at an empty <a name="delivery"></a> placed before
a heading. Delete the empty anchor and give the heading itself id="delivery". Links written
as #delivery keep working without any change, because browsers match fragment links to an
id first. Check that the id is not already used elsewhere on the page, otherwise the jump lands on the
wrong element and you create a duplicate id error instead.
Step 7
Re-validate and compare the pages visually
Run the HTML Checker again on the same sample URLs and confirm that the obsolete messages have gone. Then open each page beside a screenshot taken before the change, at desktop and phone widths, and look for text that has lost its alignment, tables that have lost their borders, and images that have moved. Fix any difference with a class, never by putting the old attribute back.
Edge cases and awkward examples
Tables used for page layout
Pages built before CSS layout was reliable often nest tables inside tables, with width,
bgcolor and cellpadding on every cell. Stripping the attributes collapses the
design. Rebuild these pages with ordinary blocks and flexbox or grid instead; a layout table is also
read out as a data table by screen readers, so patching it keeps a second problem alive.
Centring an image
text-align: center on the parent works for an inline image. If the image is set to display: block
by your theme, which many are, use margin-inline: auto on the image instead. This is the
most common reason a replacement "does nothing".
.text-centre { text-align: center; }
.img-centre { display: block; margin-inline: auto; }
.table-bordered { border-collapse: collapse; }
.table-bordered th,
.table-bordered td { border: 1px solid #ccc; padding: 0.5rem; }
Old iframe embed codes
Map, video and booking embeds copied years ago often carry frameborder="0", scrolling="no"
and marginheight. Remove them and add iframe { border: 0; } to your stylesheet
once. While you are there, check the iframe has a title describing its content, which the
checker may also flag.
Pages you cannot edit
Output from a plugin, app or hosted form that you cannot change should be logged rather than fought. Filtering someone else's HTML with your own code on every request is fragile and breaks when they update. Ask for a fix, and weigh whether the feature is worth keeping if it also causes other problems.
Custom elements and unknown tags
An error such as Element foo not allowed as child of element div is different: the
validator does not recognise the tag at all. Custom elements must contain a hyphen, such as <booking-widget>;
a made-up tag without one is invalid rather than obsolete.
Keeping obsolete markup from coming back
- Paste as plain text. Most reintroduced
<font>tags arrive from Word, Google Docs or an old website through copy and paste. Teach editors the paste-as-text shortcut (Ctrl+Shift+V or Cmd+Shift+V in most browsers) and to apply formatting with the editor's own buttons. - Restrict raw HTML. Where your CMS lets you, limit who can use a raw HTML block, and give editors the classes they need through the editor's style options instead.
- Update embed codes when you touch a page. When editing a page that contains a map or video, take a fresh embed code from the provider.
- Add a check to your build. For static and framework sites, a validator step or a simple search for the tag names in your build output catches new instances before they reach production.
- Re-run the checker after imports. Content migrations and bulk product imports are the other big source. Validate a sample of imported pages before announcing the migration as done.
If the same pages also report unclosed or mis-nested tags, fix those first: old hand-written HTML with obsolete tags very often has broken nesting too, and a stray closing tag can change which element the validator thinks an attribute belongs to. The unclosed tags guide covers that, and the semantic HTML guide covers choosing meaningful elements once the old ones are gone.
1. Does obsolete HTML hurt my search rankings?
Not in any direct way that Google has described. Google has said for a long time that it does not use validation as a ranking factor, and browsers still render most obsolete tags. The indirect effects are what matter: font tags used instead of headings hide your page structure, fixed-width tables can make a page awkward to use on phones, and obsolete markup often travels with nesting errors that do affect how content is read. Treat it as maintenance that also improves accessibility, not as a ranking fix.
2. Is the b tag deprecated? Should I replace it with strong?
No. The b element is valid in current HTML and means text drawn to attention without extra importance, such as a product name in a review. The strong element means the words are important, serious or urgent. Screen readers generally treat both the same, so the choice is about meaning rather than behaviour. Replace b with strong only where the text genuinely carries importance, and leave the rest alone. The same applies to i and em, which are both valid too.
3. Why does my site still have font tags when I never typed any?
Almost always because content was pasted from a word processor, an email or an older website. Rich text editors try to preserve the formatting they receive, and older editors turned that formatting into font tags with face, size and colour attributes. Page builders and imports from old CMS platforms do the same. Pasting as plain text and then formatting with the editor's own buttons stops new ones appearing. Existing tags need removing from the stored content itself, as described in the bulk clean-up step.
4. Will browsers stop supporting center and font?
There is no announced plan to remove them, and the HTML standard asks browsers to keep rendering many obsolete features so that old pages keep working. A few features have already gone completely, such as applets, which needed Java, and the keygen element. The reason to replace center and font is not an imminent deadline but the fact that they override your stylesheet, clutter every audit and make redesigns harder. Relying on continued support is safe in the short term but gains you nothing.
5. Can I just hide these errors in the validator?
You can filter them out of a report, and some teams temporarily do so while they deal with more serious errors first. But hiding the message does not change the markup, so the styling problems and the maintenance cost remain, and the next person to audit the site will see the same errors. A better approach is to accept them only for output you truly cannot edit, such as a third-party embed, and to record why, while fixing everything in your own templates and content.
6. Are width and height attributes on images obsolete?
No, and they should not be removed. The width and height attributes are valid on img, video, canvas and iframe elements, and giving images their dimensions lets the browser reserve the right amount of space before the file downloads. That reduces layout shift, which is measured by the Cumulative Layout Shift metric. The width and height attributes that are obsolete are the ones on table, td, th, hr and similar elements, where CSS should now control the size instead.
7. What should replace a marquee announcement bar?
A static announcement bar with the text visible all the time is the simplest and most accessible replacement. Scrolling text is hard to read, easy to miss and a problem for people with vestibular or attention difficulties. If you need to show several messages, list them, or rotate them slowly with a visible pause button and no movement when the visitor's system asks for reduced motion. Under WCAG 2.2, moving content that lasts more than five seconds must be possible to pause, stop or hide.
The HTML Checker validates your page against W3C standards and reports errors and warnings, including deprecated elements and obsolete attributes, alongside doctype, encoding, nesting, duplicate ID, ARIA, form and language issues.
Open HTML Checker Fixes โ