HTML Guides for media
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.
A <source> element inside a <picture> that is followed by another <source> or an <img> with srcset must include a media and/or type attribute.
The <source> element is used inside <picture> for responsive images, allowing different resources to be loaded based on conditions such as viewport width (media) or image format (type). According to the HTML standard, when multiple <source> elements are present (or a following <img> with srcset), each <source> must provide a media and/or type attribute so the browser can choose the appropriate resource based on those hints.
Without media or type, the browser cannot distinguish when to use each source, which can lead to validation errors and unexpected rendering behavior.
Incorrect example (causes the validator error):
<picture>
<source srcset="image1.webp">
<source srcset="image2.jpg">
<img alt="" src="fallback.jpg" srcset="fallback2x.jpg 2x">
</picture>
Correct examples (fixing the error):
<picture>
<source srcset="image1.webp" type="image/webp">
<source srcset="image2.jpg" type="image/jpeg">
<img alt="" src="fallback.jpg" srcset="fallback2x.jpg 2x">
</picture>
or
<picture>
<source srcset="image-small.jpg" media="(max-width: 600px)">
<source srcset="image-large.jpg" media="(min-width: 601px)">
<img alt="" src="fallback.jpg" srcset="fallback2x.jpg 2x">
</picture>
By specifying the media and/or type attributes for each <source>, you satisfy the HTML standard and resolve the W3C validator issue.
The media attribute tells the browser under which conditions a linked stylesheet (or other resource) should be applied. Its value must be a valid media query list as defined by the CSS Media Queries specification. When the W3C HTML Validator reports a parse error for this attribute, it means the value couldn’t be parsed as a valid media query. The browser may ignore the attribute entirely or behave unpredictably, potentially loading the stylesheet in all conditions or not at all.
Common causes of this error include:
- Typos in media types or features — e.g., scrren instead of screen, or max-widht instead of max-width.
- Missing parentheses around media features — e.g., max-width: 600px instead of (max-width: 600px).
- Invalid or stray characters — e.g., extra commas, semicolons, or unmatched parentheses.
- Using CSS syntax instead of media query syntax — e.g., writing @media screen or including curly braces.
- Incorrect logical operators — e.g., using or at the top level instead of a comma, or misspelling not or only.
- Server-side template placeholders left unresolved — e.g., media="{{mediaQuery}}" rendered literally.
Getting this right matters for standards compliance and predictable cross-browser behavior. Browsers are generally lenient and may try to recover from malformed media queries, but the recovery behavior isn’t guaranteed to be consistent. A broken media attribute can cause stylesheets to load when they shouldn’t (wasting bandwidth) or not load when they should (breaking layout). It also affects performance, since browsers use the media attribute to prioritize resource loading.
To fix the issue, verify that your media value is a syntactically correct media query. Use valid media types (screen, print, all), wrap media features in parentheses, and separate multiple queries with commas.
Examples
Incorrect: missing parentheses around media feature
<!-- ❌ Parse error: media features must be wrapped in parentheses -->
<link rel="stylesheet" href="responsive.css" media="max-width: 600px">
Correct: parentheses around media feature
<link rel="stylesheet" href="responsive.css" media="(max-width: 600px)">
Incorrect: typo in media type
<!-- ❌ Parse error: "scrren" is not a valid media type -->
<link rel="stylesheet" href="styles.css" media="scrren">
Correct: valid media type
<link rel="stylesheet" href="styles.css" media="screen">
Incorrect: using or instead of a comma to separate queries
<!-- ❌ Parse error: top-level "or" is not valid between media queries -->
<link rel="stylesheet" href="styles.css" media="screen or print">
Correct: comma-separated media query list
<link rel="stylesheet" href="styles.css" media="screen, print">
Incorrect: stray semicolon in the value
<!-- ❌ Parse error: semicolons are not valid in media queries -->
<link rel="stylesheet" href="styles.css" media="screen; (max-width: 768px)">
Correct: combining media type and feature with and
<link rel="stylesheet" href="styles.css" media="screen and (max-width: 768px)">
More valid media query examples
<!-- Simple media type -->
<link rel="stylesheet" href="print.css" media="print">
<!-- Apply to all media (default behavior, but explicit) -->
<link rel="stylesheet" href="base.css" media="all">
<!-- Multiple conditions with "and" -->
<link rel="stylesheet" href="tablet.css" media="screen and (min-width: 768px) and (max-width: 1024px)">
<!-- Using "not" to exclude a media type -->
<link rel="stylesheet" href="no-print.css" media="not print">
<!-- Multiple queries separated by commas (logical OR) -->
<link rel="stylesheet" href="special.css" media="(max-width: 600px), (orientation: portrait)">
<!-- Prefers-color-scheme for dark mode -->
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
If you’re unsure whether your media query is valid, try testing it in a browser’s developer tools by adding a <style> block with @media and the same query — if the browser highlights it as invalid, the same value will fail in the media attribute.
The media attribute on the link element cannot use the deprecated value projection; only valid CSS media types should be specified.
The media attribute specifies what media/device the linked resource is designed for, using a media query or a list of valid media types. In modern HTML and CSS, commonly accepted values include all, print, and screen.
The value projection was intended for projectors but has been deprecated and is no longer recognized by browsers or the HTML standard. To ensure validity and compatibility, remove projection and use only accepted types such as screen and/or print.
Incorrect example (with deprecated value):
<link rel="stylesheet" href="style.css" media="screen, projection">
Correct examples:
<link rel="stylesheet" href="style.css" media="screen">
<link rel="stylesheet" href="style.css" media="screen, print">
If you intend your stylesheet for screens and print, you can use both screen, print; for only screens, use just screen. If the stylesheet should apply to all devices, you can omit the media attribute or use all:
<link rel="stylesheet" href="style.css">
or
<link rel="stylesheet" href="style.css" media="all">
The media attribute on a <link> element specifies the conditions under which the linked resource should apply. It accepts either a simple media type or a full media query. When the validator reports “unrecognized media,” it means the value you provided doesn’t match any known media type or valid media query syntax.
Several older media types that were defined in earlier CSS specifications have been deprecated. Types like handheld, projection, tv, tty, aural, braille, and embossed are no longer recognized as valid. Modern CSS and HTML only support three media types: all, screen, and print. If you’re using a deprecated type, you should replace it with an appropriate modern media query that targets the device characteristics you need.
Beyond deprecated types, this error also occurs when a media query expression is malformed — for example, missing parentheses around a feature expression, using an unknown feature name, or having a typo in the value.
Why this matters
- Standards compliance: Using unrecognized media types means your HTML doesn’t conform to the current HTML and CSS specifications.
- Browser behavior: Browsers may ignore the entire <link> element or apply the resource unconditionally when they encounter an unrecognized media type, leading to unexpected results.
- Performance: The media attribute helps browsers prioritize resource loading. A valid media query allows the browser to defer loading stylesheets that don’t match the current context (e.g., print stylesheets), improving page load performance.
How to fix it
- Replace deprecated media types with screen, print, or all, or use modern media queries that target specific device features.
- Check for typos in your media type or query expression.
- Validate your media query syntax — feature expressions must be wrapped in parentheses and use recognized feature names like max-width, orientation, or prefers-color-scheme.
Examples
Incorrect: using a deprecated media type
<link rel="stylesheet" href="mobile.css" media="handheld">
The handheld media type is deprecated and will trigger the validation error.
Incorrect: misspelled media type
<link rel="stylesheet" href="styles.css" media="screen">
Incorrect: malformed media query
<link rel="stylesheet" href="responsive.css" media="max-width: 768px">
The feature expression is missing its surrounding parentheses.
Correct: using valid media types
<link rel="stylesheet" href="general.css">
<link rel="stylesheet" href="print.css" media="print">
<link rel="stylesheet" href="screen.css" media="screen">
When no media attribute is specified, it defaults to all.
Correct: replacing deprecated types with modern media queries
Instead of media="handheld", use a media query that targets small screens or specific device capabilities:
<link rel="stylesheet" href="mobile.css" media="screen and (max-width: 768px)">
Correct: using complex media queries
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="portrait.css" media="screen and (orientation: portrait)">
<link rel="stylesheet" href="large.css" media="screen and (min-width: 1200px)">
Valid media types reference
| Media type | Description |
|---|---|
| all | Matches all devices (default when omitted) |
| Matches printers and print preview mode | |
| screen | Matches screens (computers, tablets, phones) |
For anything more specific than these three types, use media feature expressions like (max-width: 600px), (hover: hover), or (prefers-reduced-motion: reduce) to target the exact device characteristics you need.
sizes contains an invalid media condition; the value must be a comma-separated list of media conditions with corresponding slot sizes, ending with an optional fallback length.
Detailed explanation:
- The sizes attribute on img pairs a media condition with a slot size that represents the layout width of the image for that condition. Syntax: (<media-condition>) <length>[, ...], <length> where the last item can be a bare length fallback.
- A media condition uses the same grammar as CSS media queries. It must be valid CSS, e.g., (min-width: 600px) or (width <= 50rem) and (orientation: landscape). Each condition must be enclosed in parentheses unless using logical operators combining proper conditions.
Common parse errors:
- Missing parentheses: use (min-width: 600px), not min-width: 600px.
- Invalid units or tokens: use px, em, rem, vw, etc.; avoid % in media conditions.
- Missing slot size after a condition: (min-width: 600px) must be followed by a length like 600px.
- Using px only for slot size without units or using percentages: slot size must be a length like 300px, 50vw, not 300.
- Trailing comma or extra commas.
- Misusing comparison syntax: use modern range syntax like (600px <= width <= 1000px) or the traditional form (min-width: 600px) and (max-width: 1000px). Do not write (min-width <= 600px).
- Slot sizes must be lengths: px, em, rem, vw, vh, vmin, vmax, ch. Percentages are not allowed in sizes slot sizes.
- The srcset widths (w descriptors) must correspond to the intrinsic widths of the image candidates, e.g., 400w, 800w. The browser picks one based on sizes.
HTML examples:
-
Correct usage with media conditions and fallback:
<img src="image-800.jpg" srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w" sizes="(min-width: 900px) 50vw, (min-width: 600px) 66vw, 100vw" alt="Decorative pattern"> -
Using range syntax and avoiding common mistakes:
<img src="hero-1600.jpg" srcset="hero-800.jpg 800w, hero-1200.jpg 1200w, hero-1600.jpg 1600w" sizes="(800px <= width < 1200px) 80vw, (width >= 1200px) 50vw, 100vw" alt="Hero banner"> -
Minimal fixed example for a typical error (missing parentheses and slot size): Incorrect:
<img src="pic-800.jpg" srcset="pic-400.jpg 400w, pic-800.jpg 800w" sizes="min-width: 600px, 100vw" alt="Sample">Correct:
<img src="pic-800.jpg" srcset="pic-400.jpg 400w, pic-800.jpg 800w" sizes="(min-width: 600px) 50vw, 100vw" alt="Sample"> -
Example avoiding invalid tokens and commas:
<img src="avatar-256.png" srcset="avatar-128.png 128w, avatar-256.png 256w" sizes="(orientation: landscape) 30vw, 50vw" alt="User avatar">
sizes only accepts a valid media condition list (e.g., (min-width: 600px) 50vw, 100vw); malformed media conditions or missing length values trigger this parse error.
Detailed explanation
- Element: source in a picture or audio/video context. For responsive images, use attributes srcset, optional media, and optional sizes.
-
Attribute: sizes applies only when srcset contains width descriptors (e.g., 320w, 640w). It is a comma-separated list of:
- One or more media conditions followed by a length (e.g., (min-width: 800px) 50vw)
- A final fallback length with no media condition (e.g., 100vw)
Common parse errors:
- Missing parentheses around conditions: min-width: 600px → (min-width: 600px)
- Using invalid units or tokens: 50 (needs a length like 50vw or 50rem)
- Missing length after a condition: (min-width: 800px)
- Trailing commas or malformed separators
- Using sizes while srcset uses pixel density descriptors (1x, 2x); sizes is ignored for x-descriptors and may confuse validators
- Valid media condition syntax mirrors CSS media queries without the @media keyword. Use logical operators and, or, not per CSS Media Queries spec, and ensure spaces and colons are correct.
HTML examples
-
Correct responsive image with width descriptors and sizes
<picture> <source type="image/webp" srcset="hero-480.webp 480w, hero-800.webp 800w, hero-1200.webp 1200w" sizes="(min-width: 1200px) 1200px, (min-width: 800px) 800px, 100vw"> <img src="hero-800.jpg" srcset="hero-480.jpg 480w, hero-800.jpg 800w, hero-1200.jpg 1200w" sizes="(min-width: 1200px) 1200px, (min-width: 800px) 800px, 100vw" alt="Hero image"> </picture> -
Using viewport width units for simpler sizing
<img src="photo-640.jpg" srcset="photo-320.jpg 320w, photo-640.jpg 640w, photo-1024.jpg 1024w" sizes="(min-width: 900px) 50vw, 100vw" alt="Sample photo"> -
Correct when using pixel density descriptors (omit sizes)
<img src="avatar@1x.jpg" srcset="avatar@1x.jpg 1x, avatar@2x.jpg 2x" alt="User avatar">
Fixing common mistakes
-
Add parentheses and a length:
<img src="img-800.jpg" srcset="img-480.jpg 480w, img-800.jpg 800w" sizes="(min-width: 600px) 50vw, 100vw" alt="Example"> -
Remove stray comma and ensure final fallback:
<img src="banner-800.jpg" srcset="banner-400.jpg 400w, banner-800.jpg 800w" sizes="(min-width: 700px) 60vw, 100vw" alt="Banner"> -
Minimal valid document example
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Valid sizes Attribute</title> </head> <body> <img src="pic-800.jpg" srcset="pic-400.jpg 400w, pic-800.jpg 800w" sizes="(min-width: 600px) 50vw, 100vw" alt="Picture"> </body> </html>
Ready to validate your sites?
Start your free trial today.