HTML Guides for obsolete
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The doctype declaration tells the browser which version of HTML the document is written in and determines how the browser renders the page. Older HTML versions required long, complex doctype strings that referenced Document Type Definitions (DTDs). With the introduction of HTML5, the doctype was simplified to just <!DOCTYPE html>, which is now the only recommended doctype for modern web pages.
When a browser encounters an obsolete doctype—or no doctype at all—it may switch into “quirks mode,” a legacy rendering mode that emulates old browser behavior. In quirks mode, CSS box models, layout calculations, and other rendering behaviors can differ significantly from standards mode, leading to inconsistent appearance across browsers. Using the modern <!DOCTYPE html> ensures the browser operates in “standards mode,” giving you predictable and consistent rendering.
Beyond rendering concerns, using an obsolete doctype means your document is referencing outdated specifications. Modern HTML validators, including the W3C Nu HTML Checker, are designed to validate against the current HTML Living Standard. Legacy doctypes may cause the validator to misinterpret your markup or report errors that don’t apply, making it harder to maintain clean, valid code.
To fix this, simply replace whatever doctype declaration appears at the top of your HTML file with <!DOCTYPE html>. This single change is backward-compatible—it works in all modern browsers and even in Internet Explorer 6 and later. No DTD reference or version number is needed.
Examples
Obsolete doctypes that trigger this issue
These are common legacy doctypes that the validator will flag:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
Correct HTML5 doctype
Replace the obsolete doctype with the simple, modern declaration:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
Key points about the modern doctype
- It must appear on the very first line of the document, before the <html> tag. No comments or whitespace should precede it.
- The declaration is case-insensitive—<!DOCTYPE html>, <!doctype html>, and <!Doctype Html> are all valid, though lowercase or uppercase conventions are most common.
- Unlike older doctypes, it does not reference a DTD URL or version number.
- Adding a lang attribute to the <html> element and a <meta charset="utf-8"> tag in the <head> are best practices that pair well with the modern doctype for a fully standards-compliant document.
In earlier versions of HTML, there were two separate elements for shortened forms of words and phrases: <abbr> for abbreviations (like “Dr.” or “etc.”) and <acronym> for acronyms (like “NASA” or “HTML”). The HTML5 specification eliminated this distinction because acronyms are simply a type of abbreviation. The <abbr> element now covers all cases.
Using the obsolete <acronym> element causes W3C validation errors and has several practical drawbacks:
- Standards compliance: The element is not part of the current HTML specification. Validators will flag it as an error, and future browsers are not guaranteed to support it.
- Accessibility: Assistive technologies are designed and tested against current standards. While many screen readers still handle <acronym>, relying on an obsolete element risks inconsistent behavior. The <abbr> element has well-defined, standardized accessibility semantics.
- Consistency: Using <abbr> for all abbreviations and acronyms simplifies your markup and makes it easier for developers to maintain.
The fix is straightforward: replace every <acronym> tag with <abbr>. The title attribute works the same way on both elements — it provides the expanded form of the abbreviation or acronym that browsers typically display as a tooltip on hover.
Examples
❌ Obsolete: using <acronym>
<p>The <acronym title="World Wide Web">WWW</acronym> was invented by Tim Berners-Lee.</p>
<p>This page is written in <acronym title="HyperText Markup Language">HTML</acronym>.</p>
✅ Fixed: using <abbr>
<p>The <abbr title="World Wide Web">WWW</abbr> was invented by Tim Berners-Lee.</p>
<p>This page is written in <abbr title="HyperText Markup Language">HTML</abbr>.</p>
Using <abbr> for both abbreviations and acronyms
Since <abbr> now handles all shortened forms, you can use it consistently throughout your markup:
<p>
Contact <abbr title="Doctor">Dr.</abbr> Smith at
<abbr title="National Aeronautics and Space Administration">NASA</abbr>
for more information about the <abbr title="International Space Station">ISS</abbr>.
</p>
Styling <abbr> with CSS
Some browsers apply a default dotted underline to <abbr> elements with a title attribute. You can customize this with CSS:
<style>
abbr[title] {
text-decoration: underline dotted;
cursor: help;
}
</style>
<p>Files are transferred using <abbr title="File Transfer Protocol">FTP</abbr>.</p>
If you’re migrating a large codebase, a simple find-and-replace of <acronym with <abbr and </acronym> with </abbr> will handle the conversion. No other attributes or content changes are needed — the two elements accept the same attributes and content model.
The <big> element was a purely presentational HTML element that increased the text size by one level (similar to moving from small to medium, or medium to large). HTML5 removed it from the specification because it violates the principle of separating content structure from visual presentation. HTML should describe the meaning of content, while CSS should handle how it looks.
Using obsolete elements causes several problems. First, W3C validation will fail, which can impact code quality standards and SEO audits. Second, while current browsers still support <big> for backward compatibility, there’s no guarantee future browsers will continue to do so. Third, the <big> element carries no semantic meaning — it doesn’t tell assistive technologies why the text is larger, only that it should be displayed differently. CSS gives you more precise control over font sizing while keeping your HTML clean and standards-compliant.
To fix this issue, replace every <big> element with a <span> (or another semantically appropriate element) and apply CSS to control the font size. You can use inline styles, a <style> block, or an external stylesheet.
If the larger text has a specific meaning — such as emphasizing importance — consider using a semantic element like <strong> or <em> instead, and style it with CSS as needed.
Examples
❌ Obsolete: using the <big> element
<p>This is <big>important text</big> in a paragraph.</p>
✅ Fixed: using a <span> with inline CSS
This is a direct replacement that mimics the original behavior of <big>, which rendered text at font-size: larger:
<p>This is <span style="font-size: larger;">important text</span> in a paragraph.</p>
✅ Fixed: using a CSS class
For better maintainability, use a class instead of inline styles:
<style>
.text-big {
font-size: larger;
}
</style>
<p>This is <span class="text-big">important text</span> in a paragraph.</p>
✅ Fixed: using a semantic element with CSS
If the text is larger because it’s important or emphasized, use a semantic element and style it:
<style>
.highlight {
font-size: 1.25em;
}
</style>
<p>This is <strong class="highlight">important text</strong> in a paragraph.</p>
Choosing a font-size value
The <big> element historically corresponded to font-size: larger, but with CSS you have full flexibility:
- font-size: larger — relative increase, closest to original <big> behavior
- font-size: 1.2em — scales to 120% of the parent’s font size
- font-size: 1.25rem — scales relative to the root font size
- font-size: 20px — absolute pixel value (less flexible, generally avoid)
Using relative units like em, rem, or the larger keyword is preferred because they scale well across different screen sizes and respect user font-size preferences.
In earlier versions of HTML, the charset attribute on <link> was used to indicate the character encoding of the linked resource (such as a stylesheet or other external file). The HTML Living Standard has since made this attribute obsolete. Modern browsers determine the character encoding of linked resources through the Content-Type HTTP response header — for example, Content-Type: text/css; charset=UTF-8 — or by using default encoding rules defined in the relevant specification (CSS files, for instance, default to UTF-8).
Using the obsolete charset attribute creates several issues. It gives a false sense of control over encoding, since browsers don’t actually use it. It also clutters your markup with unnecessary attributes, and it may signal to other developers that this is the mechanism being relied upon for encoding, when in reality it has no effect. For standards compliance and clean, future-proof markup, it should be removed.
The fix involves two steps: first, remove the charset attribute from your HTML; second, ensure your web server sends the correct Content-Type header for the linked resources.
Examples
Incorrect: using charset on a <link> element
<link rel="stylesheet" href="styles.css" charset="UTF-8">
<link rel="stylesheet" href="print.css" charset="iso-8859-1">
Both of these will trigger the validation warning because the charset attribute is obsolete on <link>.
Correct: charset attribute removed
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="print.css">
Simply removing the attribute resolves the validation error. The server should handle encoding declaration instead.
Full document example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example Page</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
Configuring the server to declare character encoding
Once you’ve removed the charset attribute, make sure your web server sends the proper Content-Type header with the linked resources. Most modern servers already default to UTF-8 for CSS and JavaScript files, but you can configure this explicitly.
Apache
Add the following to your .htaccess file or server configuration:
<FilesMatch "\.css$">
AddCharset UTF-8 .css
</FilesMatch>
This causes Apache to serve CSS files with the header Content-Type: text/css; charset=UTF-8.
Nginx
Add a charset directive to the relevant location block in your server configuration:
location ~* \.css$ {
charset utf-8;
}
Node.js (Express)
Set the Content-Type header explicitly when serving the file:
app.get('/styles.css', function(req, res) {
res.setHeader('Content-Type', 'text/css; charset=UTF-8');
res.sendFile(__dirname + '/styles.css');
});
If you’re using Express’s built-in static file middleware (express.static), it typically sets correct content types automatically based on file extensions.
Verifying the fix
You can confirm that the server is sending the correct header by opening your browser’s developer tools, navigating to the Network tab, clicking on the linked resource, and inspecting the Content-Type response header. It should include charset=UTF-8 (or whichever encoding your file uses). Once the attribute is removed from your HTML and the server is configured correctly, the validation warning will be resolved.
The charset attribute was historically used to declare the character encoding of an external script file when it differed from the document’s encoding. In modern HTML, this attribute is obsolete because the HTML specification now requires that the character encoding of an external script must match the encoding of the document itself. Since the document’s encoding is already declared via <meta charset="UTF-8"> (or through HTTP headers), specifying it again on individual <script> elements is redundant and no longer valid.
If your external script files use a different encoding than your HTML document, the correct solution is to convert those script files to match the document’s encoding (typically UTF-8) rather than using the charset attribute. UTF-8 is the recommended encoding for all web content and is supported universally across browsers.
This matters for standards compliance — the HTML living standard explicitly marks this attribute as obsolete. It also affects maintainability, since having encoding declarations scattered across script tags can create confusion about which encoding is actually in effect. Browsers may also ignore the attribute entirely, leading to unexpected behavior if you’re relying on it.
How to fix it
- Remove the charset attribute from all <script> elements.
- Ensure your document declares its encoding using <meta charset="UTF-8"> inside the <head>.
- Convert any script files that aren’t already UTF-8 to use UTF-8 encoding. Most modern code editors can do this via “Save with Encoding” or a similar option.
- While you’re at it, you can also remove type="text/javascript" — this is the default type for scripts and is no longer needed.
Examples
Incorrect: using the obsolete charset attribute
<script src="app.js" type="text/javascript" charset="UTF-8"></script>
This triggers the validation warning because charset is obsolete. The type="text/javascript" is also unnecessary since it’s the default.
Incorrect: charset on an inline script
<script charset="UTF-8">
console.log("Hello");
</script>
The charset attribute was only ever meaningful for external scripts, and even in that context it is now obsolete.
Correct: clean script element
<script src="app.js"></script>
Correct: ensuring encoding is declared at the document level
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Page</title>
<script src="app.js"></script>
</head>
<body>
<p>Content here.</p>
</body>
</html>
The <meta charset="UTF-8"> declaration in the <head> covers the encoding for the entire document, including all linked scripts. No additional charset attributes are needed on individual elements.
The <font> element was originally introduced to give authors control over text rendering directly in markup. A typical usage looked like <font face="Arial" size="3" color="red">. While browsers still render this element for backward compatibility, it has been obsolete since HTML5 and will trigger a validation error. The W3C validator flags it because it violates the principle of separation of concerns: HTML should define the structure and meaning of content, while CSS should handle its visual presentation.
Using <font> causes several practical problems:
- Maintainability: Styling scattered across <font> tags throughout your HTML is extremely difficult to update. Changing a color scheme could mean editing hundreds of elements instead of a single CSS rule.
- Accessibility: The <font> element carries no semantic meaning. Screen readers and other assistive technologies gain nothing from it, and its presence can clutter the document structure.
- Consistency: CSS enables you to define styles in one place and apply them uniformly across your entire site using classes, selectors, or external stylesheets.
- Standards compliance: Using obsolete elements means your HTML does not conform to the current specification, which can lead to unexpected rendering in future browser versions.
To fix this issue, remove every <font> element and replace its visual effects with equivalent CSS properties. The three attributes of <font> map directly to CSS:
| <font> attribute | CSS equivalent |
|---|---|
| color | color |
| size | font-size |
| face | font-family |
You can apply CSS as inline styles for quick fixes, but using a <style> block or an external stylesheet with classes is the preferred approach for any real project.
Examples
Incorrect: using the obsolete <font> element
<p>
<font face="Arial" size="4" color="blue">Welcome to my website</font>
</p>
This triggers the validator error: The “font” element is obsolete. Use CSS instead.
Fix with inline styles
If you need a quick, direct replacement:
<p style="font-family: Arial, sans-serif; font-size: 18px; color: blue;">
Welcome to my website
</p>
Fix with a CSS class (recommended)
Using a class keeps your HTML clean and makes styles reusable:
<style>
.welcome-text {
font-family: Arial, sans-serif;
font-size: 18px;
color: blue;
}
</style>
<p class="welcome-text">Welcome to my website</p>
Nested <font> elements replaced with CSS
Old markup sometimes used multiple nested <font> tags:
<!-- Obsolete -->
<p>
<font color="red" size="5">
Important:
<font face="Courier">code goes here</font>
</font>
</p>
The correct approach uses <span> elements or semantic tags with CSS classes:
<style>
.alert-heading {
color: red;
font-size: 24px;
}
.code-snippet {
font-family: Courier, monospace;
}
</style>
<p>
<span class="alert-heading">
Important:
<span class="code-snippet">code goes here</span>
</span>
</p>
If the text carries a specific meaning — such as marking something as important or representing code — consider using semantic HTML elements like <strong>, <em>, or <code> alongside your CSS:
<style>
.alert-heading {
color: red;
font-size: 24px;
}
</style>
<p class="alert-heading">
<strong>Important:</strong>
<code>code goes here</code>
</p>
This approach gives you full control over appearance through CSS while keeping your HTML meaningful, accessible, and standards-compliant.
The language attribute was used in early HTML to specify the scripting language of a <script> block, typically set to values like "JavaScript" or "VBScript". It was deprecated in HTML 4.01 (in favor of the type attribute) and is now fully obsolete in the HTML Living Standard. While browsers still recognize it for backward compatibility, it serves no functional purpose and triggers a validation warning.
The <script> element accepts several standard attributes, but the two most common are type and src. The type attribute specifies the MIME type or module type of the script (e.g., "module" or "application/json"), and src points to an external script file. When writing standard JavaScript, you can omit type entirely because "text/javascript" is the default. The language attribute, however, should always be removed — it is not a valid substitute for type and has no effect in modern browsers.
Why this matters
- Standards compliance: Using obsolete attributes means your HTML does not conform to the current HTML specification. This can cause validation errors that obscure more important issues in your markup.
- Code clarity: The language attribute is misleading to developers who may not realize it’s non-functional. Removing it keeps your code clean and easier to maintain.
- Future-proofing: While browsers currently tolerate the attribute, there is no guarantee they will continue to do so indefinitely. Relying on obsolete features is a maintenance risk.
How to fix it
Simply remove the language attribute from your <script> elements. If you’re using JavaScript (the vast majority of cases), no replacement is needed. If you need to specify a non-default type, use the type attribute instead.
Examples
❌ Obsolete: using the language attribute
<script language="JavaScript">
console.log("Hello, world!");
</script>
<script language="JavaScript" src="app.js"></script>
✅ Fixed: attribute removed
For inline JavaScript, simply omit the attribute:
<script>
console.log("Hello, world!");
</script>
For external scripts, only src is needed:
<script src="app.js"></script>
✅ Using the type attribute when needed
If you need to specify a script type — for example, an ES module or a data block — use the standard type attribute:
<script type="module" src="app.js"></script>
<script type="application/json">
{ "key": "value" }
</script>
Note that type="text/javascript" is valid but redundant, since JavaScript is the default. You can safely omit it for standard scripts.
The longdesc attribute was originally designed to point to a URL containing a detailed description of an element’s content, primarily as an accessibility feature for screen reader users. On <iframe> elements, it was intended to describe the framed content for users who couldn’t perceive it directly. However, the attribute was poorly implemented across browsers, rarely used by assistive technologies, and was ultimately removed from the HTML specification for <iframe> elements.
Using obsolete attributes causes W3C validation errors and can create a false sense of accessibility. Since browsers and assistive technologies don’t reliably process longdesc on iframes, users who need the description may never actually reach it. A visible link, on the other hand, is universally accessible — it works for all users regardless of their browser, device, or assistive technology.
The fix is straightforward: remove the longdesc attribute from the <iframe> and place a regular <a> element near the iframe that links to the description page. This approach is more robust because the link is visible, discoverable, and works everywhere.
Examples
❌ Obsolete: Using longdesc on an <iframe>
<iframe src="report.html" title="Annual report" longdesc="report-description.html"></iframe>
This triggers the validation error because longdesc is no longer a valid attribute on <iframe>.
✅ Fixed: Using a visible link instead
<iframe src="report.html" title="Annual report"></iframe>
<p>
<a href="report-description.html">Read a detailed description of the annual report</a>
</p>
The longdesc attribute is removed, and a descriptive link is placed adjacent to the iframe so all users can access it.
✅ Alternative: Wrapping in a <figure> for better semantics
For a more structured approach, you can use a <figure> element with a <figcaption> to associate the description link with the iframe:
<figure>
<iframe src="report.html" title="Annual report"></iframe>
<figcaption>
Annual report overview.
<a href="report-description.html">Read the full description</a>.
</figcaption>
</figure>
This groups the iframe and its caption together semantically, making the relationship between them clear to both sighted users and assistive technologies.
✅ Alternative: Using aria-describedby for additional context
If you want to provide a short inline description that assistive technologies can announce automatically, you can use aria-describedby:
<p id="report-desc">
This iframe contains the interactive annual report for 2024.
<a href="report-description.html">Read the full description</a>.
</p>
<iframe src="report.html" title="Annual report" aria-describedby="report-desc"></iframe>
This links the iframe to the descriptive paragraph programmatically. Screen readers will announce the content of the referenced element when the iframe receives focus, while the visible link remains available to all users.
Key Takeaways
- Always include a title attribute on <iframe> elements to describe their purpose — this is an important baseline accessibility practice.
- Replace longdesc with a visible <a> element that links to the long description.
- Place the link near the iframe so users can easily find it.
- Consider using <figure> and <figcaption> or aria-describedby for stronger semantic association between the iframe and its description.
The name attribute was historically used on img elements to reference images through JavaScript’s document.images collection or via document.getElementsByName(). In early HTML, name served as an identifier for various elements before the id attribute was widely adopted. The HTML living standard (WHATWG) now marks name as obsolete on img elements, meaning it should no longer be used in new content.
This matters for several reasons:
- Standards compliance: Using obsolete attributes means your HTML does not conform to the current specification, which can cause validation errors and may lead to unexpected behavior in future browser versions.
- Consistency: The id attribute is the universal mechanism for uniquely identifying any HTML element. Using id instead of name keeps your markup consistent and predictable.
- JavaScript and CSS targeting: Modern APIs like document.getElementById() and document.querySelector() work with id, not name on image elements. CSS selectors also target elements by id (e.g., #myImage), making id the more versatile choice.
- Fragment linking: The id attribute allows you to link directly to an element using a URL fragment (e.g., page.html#myImage), whereas the obsolete name attribute on img does not serve this purpose.
To fix this issue, simply replace name with id on your img elements. Keep in mind that id values must be unique within the entire document — no two elements can share the same id. If you have JavaScript code that references the image by name (e.g., document.images["myImage"] or document.getElementsByName("myImage")), update those references to use document.getElementById("myImage") or document.querySelector("#myImage") instead.
Examples
Incorrect: using the obsolete name attribute
<img src="photo.jpg" name="heroImage" alt="A sunset over the ocean">
This triggers the validation error because name is no longer a valid attribute on img.
Correct: using the id attribute
<img src="photo.jpg" id="heroImage" alt="A sunset over the ocean">
The name attribute is replaced with id, and the element can now be targeted with document.getElementById("heroImage") or the CSS selector #heroImage.
Updating JavaScript references
If your existing code references the image by name, update it accordingly.
Before (relying on name):
<img src="logo.png" name="siteLogo" alt="Company logo">
<script>
var logo = document.images["siteLogo"];
logo.style.border = "2px solid blue";
</script>
After (using id):
<img src="logo.png" id="siteLogo" alt="Company logo">
<script>
var logo = document.getElementById("siteLogo");
logo.style.border = "2px solid blue";
</script>
Multiple images that previously shared a name
Since id values must be unique, you cannot give the same id to multiple elements. If you previously used the same name on several images and selected them as a group, switch to a shared class instead:
<img src="slide1.jpg" class="gallery-image" alt="Mountain landscape">
<img src="slide2.jpg" class="gallery-image" alt="Forest trail">
<img src="slide3.jpg" class="gallery-image" alt="River valley">
<script>
var images = document.querySelectorAll(".gallery-image");
images.forEach(function(img) {
img.style.borderRadius = "8px";
});
</script>
This approach is standards-compliant and gives you flexible, modern element selection using class for groups and id for unique elements.
The name attribute was historically used on <option> elements in older HTML specifications, but it has been obsolete since HTML5. The WHATWG HTML Living Standard does not list name as a valid attribute for <option>. The valid attributes for <option> are disabled, label, selected, and value, in addition to the global attributes (such as id, class, style, etc.).
It’s important to understand that the name attribute on <option> never served the same purpose as name on <input> or <select>. For form submission, the browser sends the name from the parent <select> element paired with the value of the selected <option>. Putting name on individual <option> elements has no effect on form data and can mislead developers into thinking it influences form behavior.
Removing the obsolete name attribute ensures your HTML is standards-compliant, avoids confusion for developers maintaining the code, and prevents potential issues with future browser behavior. If you need to reference a specific <option> in JavaScript or CSS, use the id global attribute instead.
Examples
Incorrect: using the obsolete name attribute
<select id="pet-select" name="pet">
<option value="">--Please choose an option--</option>
<option name="dog-option" value="dog">Dog</option>
<option name="cat-option" value="cat">Cat</option>
<option name="hamster-option" value="hamster">Hamster</option>
</select>
This triggers the validation error because name is not a valid attribute on <option>.
Correct: using id instead of name
If you need to uniquely identify each option (for example, to target them with JavaScript or CSS), use the id attribute:
<select id="pet-select" name="pet">
<option value="">--Please choose an option--</option>
<option id="dog-option" value="dog">Dog</option>
<option id="cat-option" value="cat">Cat</option>
<option id="hamster-option" value="hamster">Hamster</option>
</select>
Correct: simply removing name if no reference is needed
In most cases, you don’t need to identify individual options at all. The value attribute is sufficient for form submission, and you can remove name entirely:
<select id="pet-select" name="pet">
<option value="">--Please choose an option--</option>
<option value="dog">Dog</option>
<option value="cat">Cat</option>
<option value="hamster">Hamster</option>
</select>
Note that the name attribute on the <select> element itself is perfectly valid and necessary — it defines the key used when the form data is submitted. The obsolete attribute warning applies only to name on <option> elements.
In older HTML specifications (HTML 4.01), the scheme attribute was used to provide additional context for interpreting the content value of a <meta> element. It told browsers or metadata processors which encoding scheme, format, or vocabulary applied to the metadata. For example, you could specify that a date followed the W3CDTF format or that a subject classification used a particular taxonomy.
HTML5 dropped the scheme attribute because it was rarely used by browsers and its purpose was better served by making the scheme part of the metadata value itself. The WHATWG HTML living standard does not recognize scheme as a valid attribute on <meta>, so including it will produce a validation error. Keeping obsolete attributes in your markup can cause confusion for developers maintaining the code and signals outdated practices that may accompany other compatibility issues.
This issue most commonly appears in documents that use Dublin Core Metadata Initiative (DCMI) metadata, which historically relied on scheme to indicate the encoding format for dates, identifiers, and subject classifications.
How to fix it
There are several approaches depending on your use case:
- Simply remove the scheme attribute if the format is already clear from context (e.g., ISO 8601 dates are universally understood).
- Incorporate the scheme into the name attribute by using a more specific property name that implies the scheme.
- Include the scheme declaration in the content value so the format information is preserved within the value itself.
For Dublin Core metadata specifically, the modern recommended approach is to use the DCTERMS namespace with RDFa or to simply drop the scheme attribute, since most date formats like YYYY-MM-DD are unambiguous.
Examples
Obsolete: using the scheme attribute
This triggers the validation error because scheme is not a valid attribute in HTML5:
<meta name="DC.Date.Created" scheme="W3CDTF" content="2009-11-30">
Another common example with subject classification:
<meta name="DC.Subject" scheme="LCSH" content="Web development">
Fixed: removing the scheme attribute
If the value format is self-evident (as with ISO 8601 dates), simply remove scheme:
<meta name="DC.Date.Created" content="2009-11-30">
Fixed: incorporating the scheme into the value
When the scheme information is important for processors to understand the value, embed it in the content attribute:
<meta name="DC.Subject" content="LCSH: Web development">
Fixed: using a more specific property name
You can make the scheme implicit by using a more descriptive name value:
<meta name="DCTERMS.created" content="2009-11-30">
Fixed: using RDFa for richer metadata
For documents that require precise, machine-readable metadata with explicit schemes, consider using RDFa attributes instead of the obsolete scheme:
<meta property="dcterms:created" content="2009-11-30">
This approach is compatible with HTML5 and provides the same semantic richness that the scheme attribute was originally designed to offer.
The summary attribute was used in HTML 4 to provide a text description of a table’s structure and purpose, primarily for screen reader users. In HTML5, this attribute was deprecated because it was invisible to sighted users, creating an unequal experience. It was also frequently misused — authors often duplicated the table’s caption or provided unhelpful descriptions, diminishing its accessibility value.
The HTML Living Standard offers several better alternatives, each suited to different situations:
- Use a <caption> element — Best for a concise title or description that benefits all users, not just screen reader users. The <caption> must be the first child of the <table> element.
- Use a <figure> with <figcaption> — Ideal when you want to provide a longer description or contextual information alongside the table. This approach also semantically groups the table with its description.
- Simplify the table — If your table is straightforward with clear headers, it may not need any additional description at all. Well-structured <th> elements with appropriate scope attributes often provide enough context.
From an accessibility standpoint, the <caption> and <figcaption> approaches are superior because they are visible to all users and part of the document flow. Screen readers announce <caption> content when a user navigates to a table, providing the same benefit the summary attribute once offered — but now everyone can see it.
Examples
❌ Obsolete: Using the summary attribute
This triggers the validation warning because summary is no longer a valid attribute on <table>.
<table summary="This table shows monthly sales figures for 2024.">
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</table>
✅ Fix 1: Using a <caption> element
Replace the summary attribute with a <caption> as the first child of the <table>. This is the most common and straightforward fix.
<table>
<caption>Monthly sales figures for 2024</caption>
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</table>
✅ Fix 2: Using <figure> and <figcaption>
This approach is useful when you want to provide a longer description or when the table is referenced as a figure within surrounding content.
<figure>
<figcaption>
Monthly sales figures for 2024, showing a steady increase in revenue
during the first quarter.
</figcaption>
<table>
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</table>
</figure>
✅ Fix 3: Simplify and rely on clear headers
For simple tables where the data is self-explanatory, well-labeled headers with scope attributes may be sufficient. No extra description is needed.
<table>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Sales</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</tbody>
</table>
You can also combine approaches — use a <caption> for a brief title and wrap the table in a <figure> with a <figcaption> for additional context. The key takeaway is to remove the summary attribute and use visible, semantic HTML elements to describe your table instead.
The <tt> element was a purely presentational element — it described how text should look (monospaced) rather than what the text meant. HTML5 removed it as part of a broader effort to separate content from presentation. Browsers still render <tt> for backward compatibility, but validators will flag it as obsolete, and its use is discouraged in all new code.
The key issue is that <tt> was used for many different purposes — displaying code snippets, keyboard input, sample output, variables, filenames, and more — yet it conveyed none of that meaning to assistive technologies or search engines. HTML5 provides dedicated semantic elements for most of these use cases, making your content more meaningful and accessible.
Choosing the Right Replacement
Before reaching for a generic <span>, consider what the monospaced text actually represents:
- Code: Use <code> for inline code fragments (e.g., variable names, short statements).
- Keyboard input: Use <kbd> for text the user should type.
- Sample output: Use <samp> for output from a program or system.
- Variables: Use <var> for mathematical or programming variables.
- No semantic meaning: Use a <span> with CSS when the monospaced styling is purely visual and none of the above elements apply.
All of these elements render in a monospaced font by default in most browsers (except <var>, which is typically italic). You can further style them with CSS as needed.
Examples
❌ Obsolete usage with <tt>
<p>Run the command <tt>npm install</tt> to install dependencies.</p>
<p>The variable <tt>x</tt> holds the result.</p>
<p>The output was <tt>Hello, world!</tt></p>
These all trigger the validator error: The “tt” element is obsolete. Use CSS instead.
✅ Fixed with semantic elements
<p>Run the command <kbd>npm install</kbd> to install dependencies.</p>
<p>The variable <var>x</var> holds the result.</p>
<p>The output was <samp>Hello, world!</samp></p>
Each replacement conveys the meaning of the text. <kbd> tells assistive technologies this is something the user types, <var> marks a variable, and <samp> indicates program output.
✅ Fixed with <code> for inline code
<p>Use the <code>Array.prototype.map()</code> method to transform each element.</p>
✅ Fixed with a <span> and CSS when no semantic element fits
If the monospaced text doesn’t represent code, input, output, or a variable — for example, a stylistic choice for a filename or an arbitrary design decision — use a <span> with CSS:
<p>Edit the file <span class="mono">config.yaml</span> to change the settings.</p>
.mono {
font-family: monospace;
}
This keeps your HTML valid and your styling in the CSS layer where it belongs.
✅ Block-level code with <pre> and <code>
If you previously used <tt> inside a <pre> block for multi-line code, the standard approach is to combine <pre> with <code>:
<pre><code>function greet(name) {
return "Hello, " + name;
}</code></pre>
Summary
Replace every <tt> element with the semantic HTML element that best describes its content — <code>, <kbd>, <samp>, or <var>. If none of these fit, use a <span> styled with font-family: monospace in CSS. This keeps your markup valid, meaningful, and accessible.
In earlier versions of HTML, the version attribute on the <html> element served as a way to indicate the DTD (Document Type Definition) the document followed. For example, you might have seen something like <html version="-//W3C//DTD HTML 4.01//EN">. This was largely redundant even then, because the <!DOCTYPE> declaration at the top of the document already communicated the same information to browsers and validators.
With the introduction of HTML5, the version attribute was officially marked as obsolete. The HTML Living Standard maintained by WHATWG does not define or support it. Modern browsers completely ignore it, so it has no functional effect on rendering or behavior. However, keeping it in your markup produces a validation warning from the W3C HTML Validator and adds unnecessary clutter to your code.
Removing this attribute has no side effects. The <!DOCTYPE html> declaration is the only mechanism needed to signal that your document uses the current HTML standard. Keeping your markup clean and free of obsolete attributes improves maintainability and ensures your documents pass validation without unnecessary warnings.
How to fix it
- Locate the <html> tag in your document.
- Remove the version attribute and its value entirely.
- Ensure you have a valid <!DOCTYPE html> declaration at the top of the document.
- Keep the lang attribute on the <html> element, as it is important for accessibility and internationalization.
Examples
Incorrect: using the obsolete version attribute
<!DOCTYPE html>
<html version="-//W3C//DTD HTML 4.01//EN" lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
This triggers the W3C validator warning: The “version” attribute on the “html” element is obsolete.
Correct: version attribute removed
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
The version attribute has been removed, and the document remains fully valid. The <!DOCTYPE html> declaration and the lang attribute are the only things needed on the <html> element for a well-formed, standards-compliant document.
Ready to validate your sites?
Start your free trial today.