Skip to main content
HTML Validation

Bad value X for attribute “sizes” on element “source”: Expected units (one of “em”, “ex”, “ch”, “rem”, “cap”, “ic”, “vw”, “svw”, “lvw”, “dvw”, “vh”, “svh”, “lvh”, “dvh”, “vi”, “svi”, “lvi”, “dvi”, “vb”, “svb”, “lvb”, “dvb”, “vmin”, “svmin”, “lvmin”, “dvmin”, “vmax”, “svmax”, “lvmax”, “dvmax”, “cm”, “mm”, “q”, “in”, “pc”, “pt”, “px”) but found Y at Z.

About This HTML Issue

The sizes attribute tells the browser how wide an image will be displayed at various viewport sizes, so it can choose the best candidate from srcset before the CSS has loaded. Each entry in the sizes list is either a media condition paired with a CSS length, or a bare fallback length at the end. The HTML specification requires these lengths to be valid CSS <length> values, which means a number followed by a recognized unit. The full list of accepted units includes px, em, ex, ch, rem, vw, vh, vmin, vmax, cm, mm, in, pt, pc, and newer viewport units like svw, lvw, dvw, svh, lvh, dvh, and others.

The calc() function is also permitted, which lets you combine units — for example, calc(100vw - 2rem).

Why this matters

The sizes attribute is parsed before layout occurs, meaning the browser relies on it being syntactically correct to make smart download decisions. An invalid value forces the browser to fall back to a default size (typically 100vw), which can lead to downloading images that are far too large or too small. Beyond performance, an invalid sizes value violates the HTML specification, and some browsers may handle the malformed input inconsistently, leading to unpredictable behavior across devices.

Common mistakes

  • Missing unit entirely: Writing 800 instead of 800px. Bare numbers without units are not valid CSS lengths (the only exception in CSS is 0, but even 0 should have a unit in sizes for clarity).
  • Using percentages: Writing 50% instead of 50vw. Percentages are not allowed in sizes because the browser hasn’t performed layout yet and doesn’t know what the percentage would be relative to. Use viewport units like vw instead.
  • Typos or extra characters: A stray character, misplaced comma, or missing whitespace can shift the parser’s position and cause it to find unexpected tokens where it expects a unit.
  • Using auto on <source>: The auto keyword for sizes is only valid on <img> elements (and requires the loading="lazy" attribute). Using it on <source> will trigger a validation error.

How to fix it

  1. Find the position indicated in the error message (“at Z”) to locate the problematic value.
  2. If the value is a bare number, append the correct unit (e.g., change 600 to 600px).
  3. If the value uses %, replace it with a viewport-relative unit like vw.
  4. Ensure commas separate each media-condition/length pair, and that the list ends with a fallback length.

Examples

Adding a missing unit

The value 800 in the sizes attribute is not a valid CSS length because it has no unit.

<!-- ❌ Invalid: "800" is missing a unit -->

<img
  src="hero-800.jpg"
  srcset="hero-800.jpg 800w, hero-1200.jpg 1200w"
  sizes="(min-width: 900px) 800, 100vw"
  alt="Hero image">
<!-- ✅ Valid: "800px" has a proper unit -->

<img
  src="hero-800.jpg"
  srcset="hero-800.jpg 800w, hero-1200.jpg 1200w"
  sizes="(min-width: 900px) 800px, 100vw"
  alt="Hero image">

Replacing a percentage with a viewport unit

Percentages are not permitted in sizes. Use vw to express a width relative to the viewport.

<!-- ❌ Invalid: "50%" is not an allowed unit in sizes -->

<img
  src="card-600.jpg"
  srcset="card-600.jpg 600w, card-900.jpg 900w"
  sizes="50%"
  alt="Product card">
<!-- ✅ Valid: "50vw" means 50% of the viewport width -->

<img
  src="card-600.jpg"
  srcset="card-600.jpg 600w, card-900.jpg 900w"
  sizes="50vw"
  alt="Product card">

Fixing the issue on a <source> element

The same rules apply to <source> elements inside <picture>. Every length value needs a valid unit.

<!-- ❌ Invalid: "600" on <source> is missing a unit -->

<picture>
  <source
    type="image/webp"
    srcset="hero-600.webp 600w, hero-1200.webp 1200w"
    sizes="(min-width: 768px) 600, 100vw">
  <img
    src="hero-600.jpg"
    srcset="hero-600.jpg 600w, hero-1200.jpg 1200w"
    sizes="(min-width: 768px) 600px, 100vw"
    alt="Hero image">
</picture>
<!-- ✅ Valid: both <source> and <img> use proper units -->

<picture>
  <source
    type="image/webp"
    srcset="hero-600.webp 600w, hero-1200.webp 1200w"
    sizes="(min-width: 768px) 600px, 100vw">
  <img
    src="hero-600.jpg"
    srcset="hero-600.jpg 600w, hero-1200.jpg 1200w"
    sizes="(min-width: 768px) 600px, 100vw"
    alt="Hero image">
</picture>

Using calc() for mixed-unit sizes

You can use calc() to combine different units, which is especially useful when accounting for padding or margins.

<img
  src="article-800.jpg"
  srcset="article-800.jpg 800w, article-1200.jpg 1200w"
  sizes="(min-width: 1024px) calc(100vw - 4rem), 100vw"
  alt="Article image">

Multiple slots with different conditions

A well-formed sizes attribute with several media conditions, ending with a unitless-condition fallback length:

<picture>
  <source
    type="image/avif"
    srcset="banner-480.avif 480w, banner-960.avif 960w, banner-1440.avif 1440w"
    sizes="(min-width: 1200px) 960px, (min-width: 600px) 80vw, 100vw">
  <img
    src="banner-480.jpg"
    srcset="banner-480.jpg 480w, banner-960.jpg 960w, banner-1440.jpg 1440w"
    sizes="(min-width: 1200px) 960px, (min-width: 600px) 80vw, 100vw"
    alt="Responsive banner">
</picture>

The general pattern is: sizes="(condition) length, (condition) length, fallback-length". Every length in that list — including the fallback — must be a valid CSS length with a unit or a calc() expression. If the validator error points to a specific character position, inspect that exact spot for a missing unit, a stray %, or malformed whitespace and replace it with one of the recognized units.

Find issues like this automatically

Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.

Help us improve our guides

Was this guide helpful?

Ready to validate your sites?
Start your free trial today.