HTML Guides for expected digit
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 colspan attribute of a <th> takes a positive whole number written with digits only, and the validator names the first character in the value that isn't a digit.
colspan sets how many columns a header cell spans. The HTML standard requires a valid non-negative integer greater than zero and no larger than 1000, such as 2 or 3. Units, percentages, decimals, signs, spaces, quotes and keywords like auto all make the value invalid. The character after "saw" is where the number stopped: p in 2px, % in 100%, . in 1.5, - in -1.
A value that contains markup, like 2><span class=, usually means a quote is missing. In <th colspan="2><span class="label">, nothing closes the quote after 2, so the parser reads on to the next " and puts everything in between into colspan. The <span> start tag is lost, and what's left of it becomes stray attributes on the <th>. That's why errors like "No space between attributes" and "Quote in attribute name" usually appear next to this one. When the number is missing too, the value starts right at the >. A CMS or rich text editor can store the broken attribute with the < escaped as <, so check the saved content as well as the template.
Browsers read the leading digits and ignore the rest, so 2px still spans two columns. A value that doesn't start with a digit, or is zero, falls back to 1. The header then covers one column and every cell after it in the row moves over, so screen readers can announce data cells under the wrong header.
Write the number on its own, without a unit, and close the attribute's quote before the >.
Invalid example
<table>
<tr>
<th colspan="2px">Name</th>
<th colspan="2><span class="label">Contact</span></th>
</tr>
<tr>
<td>Ada</td>
<td>Lovelace</td>
<td>ada@example.com</td>
<td>555-0100</td>
</tr>
</table>
Valid example
<table>
<tr>
<th colspan="2">Name</th>
<th colspan="2"><span class="label">Contact</span></th>
</tr>
<tr>
<td>Ada</td>
<td>Lovelace</td>
<td>ada@example.com</td>
<td>555-0100</td>
</tr>
</table>
The height attribute of an <object> takes a number of CSS pixels written as digits only, so a unit such as px in height="800px" makes the value invalid.
The HTML standard defines width and height on <object> as dimension attributes, whose value must be a valid non-negative integer. The validator reads the value from the left and stops at the first character that isn't a digit. In 800px that is the p, and pt or pc stop at the same letter. Other units are reported by their first character (v in 80vh, e in 40em). A percentage such as 100% gets its own error, about the % sign.
Browsers read the leading digits and drop the rest, so height="800px" already renders 800 pixels tall. Deleting the unit leaves the layout as it is. The attribute can only express pixels, though. For a height in viewport units, ems or a percentage of the container, remove the attribute and set the CSS height property instead.
Invalid example
<object data="/docs/annual-report.pdf" type="application/pdf" width="600" height="800px"></object>
Valid example
<object data="/docs/annual-report.pdf" type="application/pdf" width="600" height="800"></object>
To size the object relative to the viewport, use CSS:
<object data="/docs/annual-report.pdf" type="application/pdf" style="width: 100%; height: 80vh;"></object>
The width and height attributes of an <img> take a number of pixels written with digits only, and the validator reports the first character in the value that isn't a digit.
Both attributes must hold a valid non-negative integer, such as 640. Units, percentages, signs, decimals, spaces and any other text make the value invalid. The character in the message tells you where the number broke: in 324&height=303 it's the &, in 10em it's the e, in -1 it's the -, and in " 300" it's the leading space.
Values like these usually come from code, not from hand-written markup. A template that copies the image's query string (?width=324&height=303) into the attribute, a CMS that pastes a CSS declaration into it, or a placeholder such as {{ width }} that was never filled in all end up here. Browsers keep the leading digits and drop the rest, so 10em becomes 10 pixels, not 10 em, and a value that doesn't start with a digit is ignored. Either way the browser may reserve the wrong space for the image, and the page shifts when it loads.
Write the pixel size on its own, with no unit. When the image should display at another size, or scale with the layout, set that in CSS and keep the attributes at the image's real pixel dimensions, so the browser still knows its aspect ratio.
Invalid example
<img src="photo.jpg" alt="A red car" width="324&height=303">
<img src="logo.png" alt="Company logo" width="10em" height="4em">
Valid example
<img src="photo.jpg" alt="A red car" width="324" height="303">
<img src="logo.png" alt="Company logo" width="160" height="64" style="width: 10em; height: auto;">
According to the HTML Living Standard, the width and height attributes on the <object> element accept only valid non-negative integers — plain numbers representing pixels, such as 600 or 400. The validator expects each character in the value to be a digit (0–9). When it encounters a % sign, it reports "Expected a digit but saw '%' instead."
This is different from some legacy HTML 4 behavior where certain elements accepted percentage values in dimension attributes. In modern HTML, the <object> element's dimension attributes are strictly pixel-only. The same restriction applies to elements like <img>, <video>, and <canvas>.
Why this matters
- Standards compliance: Browsers may still render percentage values in these attributes, but the behavior is not defined by the specification and cannot be relied upon across browsers or future versions.
- Predictable rendering: Pixel values in attributes give the browser a concrete intrinsic size for the object, which helps with layout calculations and prevents content reflow as the page loads.
- Accessibility and tooling: Assistive technologies and other tools that parse HTML rely on well-formed attribute values. Invalid values may cause unexpected behavior.
How to fix it
You have two options:
- Use pixel values in the attributes if you know the exact dimensions you need.
- Use CSS if you need percentage-based or responsive sizing. Remove the
widthandheightattributes (or set them to pixel fallback values) and apply CSSwidthandheightproperties instead.
When using CSS for 100% height, remember that percentage heights require the parent elements to also have a defined height. This typically means setting height: 100% on html and body as well.
Examples
❌ Invalid: percentage values in attributes
<object data="example.pdf" type="application/pdf" width="100%" height="100%"></object>
The validator flags both width="100%" and height="100%" because % is not a digit.
✅ Fixed: pixel values in attributes
<object data="example.pdf" type="application/pdf" width="600" height="400"></object>
Plain integer values are valid and give the object a fixed size in pixels.
✅ Fixed: percentage sizing with CSS
<object
data="example.pdf"
type="application/pdf"
style="width: 100%; height: 500px;">
</object>
Using inline CSS allows you to mix units freely, including percentages, vh, em, and more.
✅ Fixed: full-page object with CSS
When you need the <object> to fill the entire viewport, use a stylesheet to set heights on the ancestor elements:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Full-Page Object Example</title>
<style>
html, body {
height: 100%;
margin: 0;
}
object {
display: block;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<object data="example.pdf" type="application/pdf"></object>
</body>
</html>
This approach is fully valid, responsive, and gives you much more control over sizing than HTML attributes alone.
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries