/ โ† HTML Checker Fixes / Doctype Errors
In this guide
  1. What the doctype actually does
  2. The messages you will see and what they mean
  3. What is allowed before the doctype
  4. Proving what the browser received
  5. Where the doctype lives on common platforms
  6. The fix, step by step
  7. Layout changes to expect after the switch
  8. Edge cases
  9. Keeping it fixed
  10. Questions and answers

What the doctype actually does

In the early days of CSS, browsers disagreed about basic sums such as how wide a box is once padding and borders are added. When browsers were later corrected to follow the standards, millions of existing pages relied on the old, wrong behaviour. The compromise was doctype sniffing: pages that declared a modern doctype got the standards behaviour, and pages without one kept the old behaviour so they would not suddenly break.

That compromise survives in every current browser. The HTML specification defines three modes:

ModeWhat triggers itWhat changes
No-quirks (standards)<!DOCTYPE html>, and some strict older doctypesLayout follows the current CSS specifications.
Limited-quirks (almost standards)HTML 4.01 Transitional or Frameset with a system identifier, and XHTML 1.0 Transitional or FramesetOne notable difference: images inside table cells are laid out the old way, which leaves small gaps under them.
QuirksNo doctype, a doctype after other content, a malformed doctype, or an old public identifier without a system identifierA long list of legacy behaviours, including the old box model on some elements, tables not inheriting font sizes, and percentage heights resolving differently.

Only the first is what you want. The doctype does not tell the browser which version of HTML you wrote, and it does not switch features on or off. It is purely a switch between rendering modes, which is why the modern version is so short.

๐Ÿ’ก The doctype is not case-sensitive. <!DOCTYPE html>, <!doctype html> and <!DocType HTML> are all valid and all give standards mode. Pick one form and use it in every template.

The messages you will see and what they mean

The HTML Checker follows the same wording as the W3C Nu validator, so the messages below are the ones to search your report for.

Start tag seen without seeing a doctype first

The parser reached an element, usually <html> or <head>, before any doctype. Either the doctype is missing from the template altogether, or the page is assembled from pieces and the piece that holds the doctype is not being included. The page is in quirks mode.

Non-space characters found without seeing a doctype first

Some visible text arrived before the doctype. This is the classic sign of a server-side script printing something too early: a PHP notice, a debugging echo, a stray character left in an include file, or a plugin writing output when it loads. The page is in quirks mode, and the stray text often appears as a line at the top of the screen.

Obsolete doctype. Expected <!DOCTYPE html>

The page uses an older declaration such as HTML 4.01 Strict or XHTML 1.0 Strict. These still give standards mode, so the layout is probably fine, but the validator flags them because they are no longer conforming. Replacing them is a one-line change.

Almost standards mode doctype. Expected <!DOCTYPE html>

A transitional or frameset doctype is putting the page into limited-quirks mode. The visible symptom is usually a few pixels of space under images in tables or in elements styled as table cells.

Quirky doctype. Expected <!DOCTYPE html>

The doctype exists but is one of the forms that browsers deliberately treat as quirks mode, for example HTML 4.01 Transitional written without its URL. Some very old site builders and email tools output these.

Stray doctype

A doctype appeared after the document had already started. This almost always means a complete HTML document has been pasted or included inside another one. The second doctype is ignored by the browser, but the <html>, <head> and <body> tags that come with it produce a cascade of further errors.

What is allowed before the doctype

There is a lot of folklore about the first line of an HTML file. The actual rules are narrower than many tutorials suggest. According to the HTML specification, a document may begin with the following before the doctype without any effect on the rendering mode:

What is not allowed is any other character: text, a tag, a PHP warning, an XML declaration in a page served as text/html that is then followed by other stray output, or a second copy of the page. So when you hunt for the cause, you are looking for visible characters, not whitespace.

โš ๏ธ Although blank lines before the doctype are harmless to HTML, they are not harmless to PHP. Output of any kind, including a single newline outside the <?php tags, can stop later code from sending headers or cookies. Keep the doctype as the first output for that reason, even though the validator would accept the whitespace.

Proving what the browser received

The fastest check is the browser console. Open the page, open developer tools and run this in the console:

document.compatMode
// "CSS1Compat"  means standards or limited-quirks mode
// "BackCompat"  means quirks mode

document.doctype
// shows the doctype node the parser found, or null if there was none

document.compatMode cannot tell standards mode from limited-quirks mode, so if it says CSS1Compat but you suspect a transitional doctype, read document.doctype.publicId and document.doctype.systemId. Firefox also prints a console message when a page loads in quirks mode.

Next, look at what the server actually sends rather than what your template file contains. View Source is good, but it can hide invisible characters. From a terminal:

curl -s https://www.example.co.uk/ | head -c 200 | od -c | head -8

This prints the first 200 bytes one character at a time. You should see the doctype immediately, optionally preceded by the three BOM bytes (shown as 357 273 277) or whitespace. Anything else in front of it is the cause of your problem.

Test more than the home page

Doctype problems are often confined to one template. A shop may have a correct home page while product pages load a different header file, or an error page, search results page or print view may be built by separate code. Run the HTML Checker on one page of each type, and include pages behind query strings, such as filtered listings, which sometimes go through a different code path.

Where the doctype lives on common platforms

PlatformFile that outputs the doctypeUsual cause of errors
WordPress (classic themes)header.php in the active theme or child themeAn old theme with an XHTML doctype, or a plugin printing a notice before the header loads.
WordPress (block themes)Generated by WordPress coreRarely the doctype itself; look for plugins or functions.php code producing early output.
Shopifylayout/theme.liquid and any alternate layoutsA second layout file, for example for a landing page app, written without a doctype.
Laravel, Django, RailsThe base layout that other views extendA view that does not extend the base layout, or a partial that contains a full document.
React, Next.js, VueThe server document or root layout; Next.js adds it automaticallyA custom server template or a static index.html edited by hand.
Static site generatorsThe base layout in the layouts or includes folderA page using a different layout, or a layout that includes another full layout.
Hand-built HTMLEvery filePages copied from an old template years ago.

The line should read exactly this, with the html element and the character encoding following immediately:

<!DOCTYPE html>
<html lang="en-GB">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Garden rooms and summerhouses | Larchfield Timber</title>

The fix, step by step

Step 1

Confirm the rendering mode in the browser

Open a page the HTML Checker flagged, open the developer tools console and run document.compatMode. A result of BackCompat means quirks mode and should be fixed first, because it changes layout. A result of CSS1Compat with an obsolete or almost standards warning is less urgent. Check document.doctype too; a result of null means the parser found no doctype at all, not merely an old one.

Step 2

Read the raw bytes the server sends

Fetch the page with curl and look at the first few hundred bytes, or use View Source and check the very first line. You are looking for anything other than whitespace, a comment or a byte order mark in front of the doctype: a warning message, a stray letter, a closing PHP tag followed by text, or a second HTML document. Write down exactly what appears, because it tells you which file to open.

Step 3

Replace any old doctype with the HTML5 one

Open the base layout or header template and replace the whole HTML 4 or XHTML declaration, including its long public identifier and URL, with <!DOCTYPE html>. On XHTML templates, also remove the xmlns attribute only if you are sure the page is served as text/html, and replace any old http-equiv content type tag with <meta charset="utf-8">. Do this in a child theme or your own layout file, never in files an update will overwrite.

Step 4

Remove output printed before the doctype

If text appears before the doctype, find where it comes from. A PHP notice or deprecation warning means you should fix that code and set display_errors to off in production so errors are logged instead of printed. A stray character usually lives after a closing ?> tag in an include or functions.php; removing the closing tag from files that contain only PHP prevents it. Deactivate plugins one at a time if the source is unclear.

Step 5

Delete doctypes repeated inside the page

A stray doctype message means a whole document has been placed inside another. Search the template and the content for a second <!DOCTYPE, typically in an HTML block pasted from an email builder, an embedded widget saved as a full page, or a partial that was once a standalone file. Keep only the fragment that belongs in the body, and delete its doctype, html, head and body tags along with their closing tags.

Step 6

Retest the layout after switching modes

Moving a page from quirks mode to standards mode can change its appearance, because the CSS was written against the old rules. Clear caches, rerun the HTML Checker, confirm document.compatMode now reads CSS1Compat, and then check the page at mobile and desktop widths. Look closely at boxes with padding, tables, full-height sections and images in table cells, and fix any shifts in the stylesheet rather than reverting the doctype.

Layout changes to expect after the switch

Fixing a doctype on a page that has been in quirks mode for years sometimes looks like it broke the page. It did not; it exposed CSS that only worked because of legacy behaviour. These are the differences you are most likely to notice:

๐Ÿ’ก Take screenshots of the key templates before you change the doctype. Comparing before and after side by side makes it much quicker to see which CSS rules relied on quirks mode.

Edge cases

Keeping it fixed

Questions and answers

1. Does a missing doctype hurt SEO?

Not directly. Search engines do not rank pages on whether they declare a doctype, and Google renders pages in a modern browser engine that copes with quirks mode. The indirect effects are what matter: quirks mode can break a responsive layout, push content out of view on phones or make text overlap, which harms how visitors use the page. Text printed before the doctype, such as a PHP error, can also end up in search snippets. Fix it for visitors first.

2. Is <!doctype html> in lower case valid?

Yes. The doctype keyword and the word html are both case-insensitive, so lower case, upper case and mixed case all produce standards mode and all pass validation. Many developers prefer the lower-case form because it compresses slightly better and matches the rest of their markup. What matters is that the text is complete, spelt correctly and is the first real content in the file. Choose one style and use it in every template so searches across the codebase find them all.

3. Can there be a blank line or a comment before the doctype?

Yes, according to the HTML specification. A byte order mark, whitespace and HTML comments may all appear before the doctype without triggering quirks mode in current browsers. Visible text, tags or error messages may not. The advice to keep the doctype on the first line is still sensible, partly because very old browsers were stricter and partly because in PHP any output before your code sends headers, including a blank line, can cause header and cookie errors.

4. Why did my layout change after I fixed the doctype?

Because the page had been rendering in quirks mode, and the CSS was relying on the old behaviour without anyone realising. In standards mode, padding adds to an element's width, percentage heights need a parent with a set height, images leave a small gap underneath, and tables inherit font sizes. Adjust the CSS to work under standards rules, for example by using border-box sizing and viewport height units, rather than putting the old doctype back.

5. Should I replace an XHTML 1.0 Strict doctype if the page looks fine?

It is worth doing, but it is low priority. XHTML 1.0 Strict and HTML 4.01 Strict already put browsers into standards mode, so the page will look the same after the change. The validator flags them as obsolete because they are no longer conforming, and the long declaration is easy to copy wrongly into new templates. Swap in the short HTML5 doctype next time you edit the base layout, and check that the page is served as text/html.

6. How do I tell if a page is in quirks mode?

Open the page, open your browser developer tools and type document.compatMode into the console. BackCompat means quirks mode; CSS1Compat means standards or almost standards mode. To tell those last two apart, look at document.doctype and check its public identifier. Firefox also logs a message to the console when a page loads in quirks mode. The HTML Checker reports the same problem from the other side by flagging the missing, quirky or transitional doctype that caused it.

7. Why does the checker report a stray doctype in the middle of my page?

A stray doctype means the parser met a second doctype after the document had already begun. It nearly always comes from a whole HTML document being placed inside another: an embed pasted with its full page wrapper, a partial template that still contains the full skeleton, or content copied from an email builder. Browsers ignore the extra doctype but the repeated html, head and body tags cause further errors. Keep only the fragment that belongs in the body.

Check every template's doctype

The HTML Checker validates your markup against W3C standards and reports errors and warnings from the doctype and character encoding through to nesting, ARIA, forms and the language attribute, so you can fix each template at its source.

Open HTML Checker Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All HTML Checker Fixes  ·  Fixing Character Encoding Errors  ·  Fixing the lang Attribute  ·  HTML Checker Guide  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.