Debugging Common HTML Problems
A symptom to cause lookup for the problems that come up repeatedly, and the two minute checks that resolve most of them.
- Concept
- The page renders strangely from a certain point
- My CSS is not applying
- My form field is not reaching the server
- My link goes to the wrong place
- My image is not showing
- My script cannot find an element
- My page scrolls sideways on a phone
- My page jumps while loading
- My label does not focus its field
- My accented characters are broken
- It works locally and breaks on the server
- It works in one browser and not another
- A two minute pre release check
- Important rules
- Common mistakes
- Best practices
- Practice
-
HTML Basics
- What is HTML: The Structure Layer of Every Web Page
- HTML Document Structure: DOCTYPE, html, head and body
- Elements, Tags and Attributes: The Vocabulary of HTML
- HTML Comments: Notes That Ship With Your Code
- Block Level and Inline Elements
- Writing and Running Your First HTML Page
- How a Browser Turns Markup Into a Page
- Text and Formatting
- Links and Navigation
- Images and Media
- Lists
- Tables
-
Forms
- Form Structure: form, action and method
- Input Types: Text, Email, Number, Date and the Rest
- Labels: The Most Important Element in a Form
- Checkboxes, Radio Buttons and Grouping
- select, option, optgroup and datalist
- textarea, File Uploads and Hidden Fields
- Buttons: submit, reset and button
- Built In Form Validation
- GET or POST: What Happens When a Form Is Submitted
- Semantic HTML
- HTML5 Features
- Head and Metadata
- HTML with CSS
- HTML with JavaScript
- Accessibility
-
HTML SEO
- How Google Works: Crawling, Indexing and Ranking
- SEO Friendly HTML Structure
- Titles and Descriptions That Earn Clicks
- Headings and Content Structure for Search
- Internal Linking and Anchor Text
- robots.txt and XML Sitemaps
- Canonical URLs and Duplicate Content
- Structured Data and JSON-LD
- Image SEO
- Core Web Vitals and Mobile Friendliness
- DevTools and Debugging
- Editor Productivity
- HTML Best Practices
- HTML Projects
- Advanced Projects
- Practice and Exams
Concept
Most HTML bugs are one of about fifteen things. This note is a lookup table: find the symptom, check the listed causes in order.
The page renders strangely from a certain point
Most likely: an unclosed tag, or a stray character.
- Open the Elements panel and find where the tree stops matching your source.
- Run the validator; it names the mismatched tag.
- Check for an unescaped
<in text content. - Check for a comment that was never closed, which swallows everything after it.
<!-- everything after this is inside the comment -->
<!-- a note that never closes
<p>This paragraph does not render.</p>My CSS is not applying
- Is the stylesheet loading? Network panel: a 404 or a redirect on the file.
- Is
rel="stylesheet"present? Without it the browser does not treat the file as CSS. - Is the selector matching? Select the element; the Styles pane lists every matching rule.
- Is the rule overridden? Struck through means something more specific won.
- Is it a case mismatch? Class names are case sensitive.
- Is the element actually there? The parser may have moved it.
- Is an inline style winning? Inline beats every selector.
My form field is not reaching the server
- Does it have a
name? This is the answer most of the time. No name, no submission. - Is it
disabled? Disabled controls are not submitted. Usereadonlyif the value is still needed. - Is it inside the
form? Check the Elements panel, not the source - a parser repair may have moved it out. - Is the checkbox checked? An unchecked box submits nothing at all.
- Is the method right? Check the Network panel Payload tab for what was actually sent.
- Is
enctypeset for a file upload? Withoutmultipart/form-dataonly the file name is sent.
My link goes to the wrong place
- Leading slash?
/aboutis from the site root;aboutis from the current folder. - Case? Servers are usually case sensitive; your local machine may not be.
- Trailing slash? Relative links resolve differently from
/blogand/blog/. - Two leading slashes?
//images/x.pngmeans another host. - Is there a
baseelement? It changes every relative URL on the page, including fragments.
My image is not showing
- Network panel: 404 means the path is wrong. Check case and the leading slash.
- Check the file extension matches the actual file.
- Check it is not blocked by a Content Security Policy - the console will say so.
- Over
file://, a root relative path points at the disk root, not the site root. - Check the file exists in the deployed build, not only locally.
My script cannot find an element
// Uncaught TypeError: Cannot read properties of null
document.getElementById("chart").textContent = "...";- Does the script run before the element is parsed? Add
defer. - Does the selector match? Test it in the console.
- Is the id spelt and cased identically?
- Is the element created later? Use event delegation on a stable parent.
- Is it inside a
template? Template contents are not in the document until cloned.
My page scrolls sideways on a phone
- An element with a fixed width larger than the viewport.
- An image with no
max-width: 100%. - A table or a
preblock with no scroll container. - A long unbroken string - a URL or a token - with no wrapping.
- Negative margins pushing content past the edge.
// find what is wider than the viewport
$$("*").filter(el => el.scrollWidth > document.documentElement.clientWidth)My page jumps while loading
- Images or iframes without
widthandheight. - Web fonts loading and reflowing the text.
- Content inserted above existing content after load.
- Ad or embed slots with no reserved space.
The Rendering panel has a layout shift regions switch that highlights exactly what moved.
My label does not focus its field
forandidmust match exactly, including case.- The id must be unique; a duplicate binds to the first.
- Labels only work with form controls, not with a
div. - Check the computed accessible name in the Accessibility pane.
My accented characters are broken
- Is
<meta charset="utf-8">present and first in the head? - Is the file actually saved as UTF-8? Declaring it does not convert it.
- Does the HTTP header declare a different encoding? The header wins.
- For database content, is the connection charset also utf8mb4?
It works locally and breaks on the server
- Case sensitivity. The most common cause by a wide margin.
- Root relative paths. They work over HTTP and not over
file://. - Missing files not committed to version control.
- Different base path if the site is deployed in a subfolder.
- Caching serving an old file. Hard reload.
- A stray
noindexorDisallow: /carried over from staging.
It works in one browser and not another
- Validate. Different browsers repair broken markup differently.
- Check support for any recent feature you used.
- Check the console in the failing browser specifically.
- Check for a vendor prefixed CSS property used without the standard one.
A two minute pre release check
// duplicate ids
const ids = $$("[id]").map(el => el.id);
console.log("duplicate ids:", ids.filter((id, i) => ids.indexOf(id) !== i));
// images with no alt
console.log("no alt:", $$("img:not([alt])"));
// unhelpful link text
console.log("weak links:", $$("a").filter(a =>
/^(click here|read more|link|here)$/i.test(a.textContent.trim())));
// form fields with no name
console.log("no name:", $$("input, select, textarea").filter(el => !el.name));
// the heading outline
console.table($$("h1,h2,h3,h4,h5,h6").map(h => ({ level: h.tagName, text: h.textContent.trim() })));
// anything wider than the viewport
console.log("overflowing:", $$("*").filter(el =>
el.scrollWidth > document.documentElement.clientWidth));Important rules
- Debug against the Elements panel, not the source file.
- Check the console before anything else.
- A 404 in the Network panel is a path problem, not a code problem.
- A missing
nameis the usual cause of a missing form value. - Case sensitivity explains most works locally, breaks deployed problems.
Common mistakes
- Changing code before reading the error message.
- Assuming the reported line number is where the mistake is.
- Testing only in one browser.
- Not validating.
- Debugging a cached copy of the file.
Best practices
- Read the console first, every time.
- Validate before assuming a browser bug.
- Keep the six check snippets above to hand.
- Hard reload when a change refuses to appear.
- Reproduce in a second browser before concluding anything.
- Change one thing at a time.
Practice
- Break a page five different ways from this note and fix each using only DevTools.
- Run the six check snippets on a page you built.
- Remove a
nameattribute, submit, and find the problem from the Payload tab alone. - Deploy a page with a case mismatch in a file name and observe the difference between local and server.