# Bad value X for attribute “sizes” on element “img”: Bad media condition: Parse Error at Y.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-x-for-attribute-sizes-on-element-img-bad-media-condition-parse-error-at-y
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `sizes` attribute tells the browser how wide an image will be displayed under different viewport conditions, allowing it to choose the best candidate from `srcset` before the page layout is calculated. Its value is a comma-separated list where each entry (except optionally the last) pairs a media condition with a CSS length. The final entry can be a bare length that serves as the default fallback. The full syntax looks like this:

```
(media-condition) length, (media-condition) length, fallback-length
```

Media conditions use the same grammar as CSS media queries. They must be enclosed in parentheses and can use logical operators like `and`, `or`, and `not` to combine sub-expressions. The slot size (length) that follows each condition must use a valid CSS length unit such as `px`, `em`, `rem`, `vw`, `vh`, `vmin`, `vmax`, or `ch`. Percentages are **not** valid in `sizes` slot lengths, and unitless numbers (other than `0`) are also invalid.

This error matters for several reasons. First, if the browser cannot parse the `sizes` value, it falls back to a default of `100vw`, which may cause it to download an unnecessarily large image — hurting performance and wasting bandwidth. Second, an invalid `sizes` attribute signals a misunderstanding of responsive image markup that could lead to layout or rendering issues. Third, standards-compliant HTML ensures consistent behavior across all browsers.

## Common Parse Errors

Here are the most frequent mistakes that trigger this validation error:

- **Missing parentheses around the media condition.** Writing `min-width: 600px` instead of `(min-width: 600px)`.
- **Missing slot size after a condition.** Each media condition must be followed by a length value, e.g., `(min-width: 600px) 50vw`. Writing `(min-width: 600px), 100vw` without a slot size after the condition is invalid — the browser interprets `(min-width: 600px)` alone as the entry.
- **Using percentages as slot sizes.** Values like `50%` are not allowed; use viewport-relative units like `50vw` instead.
- **Unitless numbers.** A slot size of `300` is invalid; it must be `300px` or another valid length.
- **Trailing or extra commas.** A trailing comma after the last entry or double commas between entries will cause a parse error.
- **Mixing up range syntax.** Modern media query range syntax like `(width >= 600px)` is valid, but hybrid forms like `(min-width <= 600px)` are not. Use either the traditional `(min-width: 600px)` or the range form `(width >= 600px)`.
- **Invalid tokens or typos.** Misspelled feature names (e.g., `min-widht`) or unsupported tokens will break parsing.

## How to Fix

1. **Wrap every media condition in parentheses.** Even simple conditions need them: `(min-width: 600px)`.
2. **Follow each condition with a valid length.** For example, `(min-width: 600px) 50vw`.
3. **End with a fallback length.** The last item should be a bare length with no media condition, like `100vw`.
4. **Use valid CSS length units** for slot sizes — `px`, `em`, `rem`, `vw`, `vh`, etc. Never use `%`.
5. **Ensure your `srcset` uses `w` descriptors** that match the intrinsic pixel widths of the image files, since `sizes` only works with width descriptors.

## Examples

### Incorrect: missing parentheses and missing slot size

The media condition lacks parentheses, and there is no slot size telling the browser how wide the image will be when the condition matches.

```html
<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w, photo-800.jpg 800w"
  sizes="min-width: 600px, 100vw"
  alt="A mountain landscape">
```

### Correct: parentheses and slot size added

```html
<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w, photo-800.jpg 800w"
  sizes="(min-width: 600px) 50vw, 100vw"
  alt="A mountain landscape">
```

### Incorrect: percentage used as slot size

```html
<img
  src="banner-1200.jpg"
  srcset="banner-600.jpg 600w, banner-1200.jpg 1200w"
  sizes="(min-width: 768px) 50%, 100%"
  alt="Promotional banner">
```

### Correct: viewport units instead of percentages

```html
<img
  src="banner-1200.jpg"
  srcset="banner-600.jpg 600w, banner-1200.jpg 1200w"
  sizes="(min-width: 768px) 50vw, 100vw"
  alt="Promotional banner">
```

### Incorrect: trailing comma

```html
<img
  src="icon-256.png"
  srcset="icon-128.png 128w, icon-256.png 256w"
  sizes="(min-width: 1024px) 128px, 64px,"
  alt="App icon">
```

### Correct: trailing comma removed

```html
<img
  src="icon-256.png"
  srcset="icon-128.png 128w, icon-256.png 256w"
  sizes="(min-width: 1024px) 128px, 64px"
  alt="App icon">
```

### Incorrect: invalid range syntax mixing traditional and modern forms

```html
<img
  src="hero-1600.jpg"
  srcset="hero-800.jpg 800w, hero-1600.jpg 1600w"
  sizes="(min-width <= 600px) 100vw, 50vw"
  alt="Hero image">
```

### Correct: using proper range syntax

```html
<img
  src="hero-1600.jpg"
  srcset="hero-800.jpg 800w, hero-1600.jpg 1600w"
  sizes="(width <= 600px) 100vw, 50vw"
  alt="Hero image">
```

### Multiple conditions with a fallback

This example shows a fully valid `sizes` attribute with several breakpoints, combining traditional and modern range syntax across entries.

```html
<img
  src="article-1200.jpg"
  srcset="article-400.jpg 400w, article-800.jpg 800w, article-1200.jpg 1200w"
  sizes="(min-width: 1200px) 33vw, (min-width: 768px) 50vw, 100vw"
  alt="Article thumbnail">
```

### Using `calc()` in slot sizes

You can use `calc()` for more precise slot sizes. This is fully valid in the `sizes` attribute.

```html
<img
  src="card-800.jpg"
  srcset="card-400.jpg 400w, card-800.jpg 800w"
  sizes="(min-width: 960px) calc(33.33vw - 2rem), calc(100vw - 2rem)"
  alt="Product card">
```
