Guías HTML para video
Aprende a identificar y corregir errores comunes de validación HTML marcados por el W3C Validator, para que tus páginas cumplan con los estándares y se muestren correctamente en todos los navegadores. También consulta nuestras Guías de accesibilidad.
The controlslist attribute was proposed to give developers a way to hint to the browser which default media controls to show or hide. It accepts values like nodownload, nofullscreen, and noremoteplayback, allowing you to selectively disable specific buttons in the browser’s built-in media player UI. For example, controlslist="nodownload" hides the download button on the video player.
However, this attribute was never adopted into the WHATWG HTML Living Standard or any W3C specification. It remains a Chromium-specific feature, meaning it only works in browsers like Chrome and Edge. Firefox, Safari, and other non-Chromium browsers simply ignore it. Because it’s not part of any standard, the W3C HTML Validator rightfully reports it as an invalid attribute.
While using controlslist won’t break your page — browsers that don’t recognize it will silently ignore it — relying on non-standard attributes has downsides:
- Standards compliance: Your HTML won’t validate, which can mask other real issues in validation reports.
- Browser compatibility: The behavior only works in Chromium-based browsers, giving an inconsistent experience across browsers.
- Future uncertainty: Non-standard attributes can be removed or changed without notice.
To fix this, you have a few options. The simplest is to remove the attribute entirely if the customization isn’t critical. If you need fine-grained control over media player buttons, the most robust approach is to build custom media controls using JavaScript and the HTMLMediaElement API. For the specific case of disabling remote playback, there is a standardized attribute — disableremoteplayback — that you can use instead.
Examples
❌ Invalid: Using the non-standard controlslist attribute
<video src="video.mp4" controls controlslist="nodownload nofullscreen"></video>
The validator will report: Attribute “controlslist” not allowed on element “video” at this point.
✅ Valid: Removing the attribute
<video src="video.mp4" controls></video>
The simplest fix is to remove controlslist and accept the browser’s default controls.
✅ Valid: Using custom controls with JavaScript
<video id="my-video" src="video.mp4"></video>
<div class="custom-controls">
<button id="play-btn">Play</button>
<input id="seek-bar" type="range" min="0" max="100" value="0">
<button id="fullscreen-btn">Fullscreen</button>
</div>
<script>
const video = document.getElementById("my-video");
document.getElementById("play-btn").addEventListener("click", () => {
video.paused ? video.play() : video.pause();
});
</script>
By omitting the controls attribute and building your own UI, you have full control over which buttons appear — across all browsers.
✅ Valid: Using disableremoteplayback for that specific need
<video src="video.mp4" controls disableremoteplayback></video>
If your goal was specifically controlslist="noremoteplayback", the standardized disableremoteplayback attribute achieves the same result and is valid HTML.
Audio element
The same issue and solutions apply to the <audio> element:
<!-- ❌ Invalid -->
<audio src="song.mp3" controls controlslist="nodownload"></audio>
<!-- ✅ Valid -->
<audio src="song.mp3" controls></audio>
The HTML specification defines the height attribute on media elements like <video> as accepting only a valid non-negative integer. This means the attribute value must consist solely of digits (e.g., "360"), with no units, keywords, or other characters. When you write height="auto", the validator expects to find a digit as the first character but encounters the letter "a", which produces the error.
The value "auto" is a valid concept in CSS, where height: auto tells the browser to calculate the element’s height automatically based on its intrinsic aspect ratio or content. However, HTML attributes and CSS properties follow different rules. The height HTML attribute is a simple pixel dimension hint — it doesn’t understand CSS keywords. Mixing CSS values into HTML attributes is a common mistake, and while browsers may silently ignore the invalid value, it leads to unpredictable behavior: the video may render without any height hint, potentially causing layout shifts as the browser discovers the video’s actual dimensions during loading.
Providing a valid height attribute matters for layout stability. When the browser knows the video’s dimensions before the media loads, it can reserve the correct amount of space in the page layout, preventing content from jumping around. This improves the user experience and contributes to better Core Web Vitals scores (specifically Cumulative Layout Shift). It also ensures your HTML is standards-compliant and accessible to assistive technologies that may rely on well-formed markup.
How to Fix
You have two approaches:
- Use a numeric value — Replace "auto" with an integer that represents the video’s height in pixels.
- Use CSS instead — Remove the height attribute from the HTML and apply height: auto (or any other value) via CSS. This is ideal when you want the video to scale responsively.
If you want the video to maintain its aspect ratio while scaling, the CSS approach is generally preferred for responsive designs. You can combine a width attribute (or CSS width) with CSS height: auto to let the browser calculate the correct height from the video’s intrinsic aspect ratio.
Examples
❌ Invalid: Using “auto” in the HTML attribute
<video width="640" height="auto" controls>
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
This triggers the validation error because "auto" is not a non-negative integer.
✅ Fixed: Using a numeric height value
<video width="640" height="360" controls>
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
The height attribute is now a valid integer. The browser reserves a 640×360 pixel area for the video before it loads.
✅ Fixed: Using CSS for responsive sizing
<video width="640" controls style="height: auto; max-width: 100%;">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
Here the height HTML attribute is removed entirely. CSS height: auto ensures the video scales proportionally, and max-width: 100% prevents it from overflowing its container. This is a common pattern for responsive video.
✅ Fixed: Using both attributes with CSS override
<video width="640" height="360" controls style="width: 100%; height: auto;">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
This approach provides the best of both worlds: the width and height HTML attributes give the browser an aspect ratio hint (preventing layout shifts), while the CSS makes the video responsive. Modern browsers use the attribute values to calculate the correct aspect ratio even when CSS overrides the actual rendered size.
The HTML specification defines the width attribute on <video> (and <img>, <canvas>, etc.) as a “valid non-negative integer,” which means it must consist only of digits like "640" or "1280". Values like "auto", "100%", or "50vw" are not permitted in the HTML attribute itself — these are CSS concepts, not valid HTML attribute values.
This matters for several reasons. First, browsers use the width and height HTML attributes to reserve the correct amount of space in the layout before the video loads, which prevents content layout shift (CLS). When the value is invalid, the browser may ignore it entirely, leading to layout jumps as the page loads. Second, invalid attributes can cause unpredictable rendering behavior across different browsers. Third, standards compliance ensures your markup is future-proof and works reliably with assistive technologies.
A common reason developers set width="auto" is to make the video responsive. The correct way to achieve this is through CSS rather than through the HTML attribute. You can still set width and height attributes with valid integers to define the video’s intrinsic aspect ratio (which helps the browser reserve space), and then override the display size with CSS.
How to Fix
- Replace "auto" with a valid integer that represents the desired pixel width.
- If you need responsive sizing, remove the width attribute or keep it for aspect ratio hinting, and use CSS to control the rendered size.
Examples
❌ Invalid: Using "auto" as the width attribute
<video width="auto" height="360" controls>
<source src="video.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
This triggers the error because "auto" is not a non-negative integer.
✅ Fixed: Specifying a valid pixel value
<video width="640" height="360" controls>
<source src="video.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
The width and height attributes use plain integers — no units, no keywords. The browser interprets these as pixels.
✅ Fixed: Responsive video using CSS
If you want the video to scale fluidly with its container, use CSS instead of the HTML attribute:
<style>
.responsive-video {
width: 100%;
height: auto;
}
</style>
<video class="responsive-video" controls>
<source src="video.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
In CSS, width: 100% and height: auto are perfectly valid and will make the video scale to fill its container while maintaining its aspect ratio.
✅ Best practice: Combine HTML attributes with CSS
For the best of both worlds — layout stability and responsive sizing — provide width and height attributes for aspect ratio hinting, then override with CSS:
<style>
.responsive-video {
max-width: 100%;
height: auto;
}
</style>
<video class="responsive-video" width="640" height="360" controls>
<source src="video.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
Here, the width="640" and height="360" attributes tell the browser the video’s intrinsic 16:9 aspect ratio, so it can reserve the right amount of space before the video loads. The CSS max-width: 100% ensures the video never exceeds its container, and height: auto keeps the aspect ratio intact. This approach minimizes layout shift while remaining fully responsive.
The poster attribute tells the browser which image to display as a preview frame before the user plays the video. According to the WHATWG HTML Living Standard, the poster attribute’s value must be a valid non-empty URL potentially surrounded by spaces. When you include poster="", the attribute is present but its value is an empty string, which is not a valid URL — triggering the W3C validator error: Bad value “” for attribute “poster” on element “video”: Must be non-empty.
This issue commonly occurs in a few scenarios:
- Template or CMS output where the poster URL is dynamically generated but the variable resolves to an empty string (e.g., poster="<?= $posterUrl ?>" when $posterUrl is empty).
- JavaScript frameworks that bind a value to the poster attribute, but the bound variable is null, undefined, or an empty string.
- Manual editing where a developer adds the attribute as a placeholder intending to fill it in later.
Why This Matters
While most browsers will gracefully handle an empty poster attribute by simply not displaying a poster image, there are good reasons to fix this:
- Standards compliance: An empty poster value violates the HTML specification. Valid markup ensures predictable behavior across all browsers and devices.
- Unnecessary network requests: Some browsers may attempt to resolve the empty string as a relative URL, potentially triggering a failed HTTP request to the current page’s URL. This wastes bandwidth and clutters developer tools and server logs with spurious errors.
- Accessibility: Screen readers and assistive technologies may interpret the empty attribute inconsistently, leading to confusing announcements for users.
How to Fix It
You have two straightforward options:
- Provide a valid image URL — If you want a poster frame, set the value to a real image path.
- Remove the attribute entirely — If you don’t need a poster image, simply omit poster. The browser will either show nothing or display the first frame of the video once enough data has loaded, depending on the preload attribute setting.
If the empty value comes from dynamic code, add a conditional check so the poster attribute is only rendered when a URL is actually available.
Examples
❌ Invalid: Empty poster attribute
<video controls poster="">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
This triggers the validation error because poster is present but has no value.
✅ Fixed: Poster attribute with a valid URL
<video controls poster="thumbnail.jpg">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
The poster attribute now points to a valid image file that the browser will display before playback begins.
✅ Fixed: Poster attribute removed entirely
<video controls>
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
When no poster image is needed, omitting the attribute is the cleanest solution.
✅ Fixed: Conditional rendering in a template
If you’re using a templating language or framework, conditionally include the attribute only when a value exists. Here’s a conceptual example using a server-side template:
<!-- Pseudo-template syntax: only render poster when posterUrl is not empty -->
<video controls {{#if posterUrl}}poster="{{posterUrl}}"{{/if}}>
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
This pattern prevents the empty poster="" from ever reaching the rendered HTML, keeping your output valid regardless of whether a poster URL is available.
The height attribute on <video> is defined in the HTML specification as a “valid non-negative integer.” This means it must be a string of digits (e.g., "480") with no units, no decimal points, and no percentage signs. When you write something like height="50%", the W3C validator rejects it because % is not a digit character and percentage values are not part of the attribute’s allowed syntax.
This same rule applies to the width attribute on <video>, as well as the width and height attributes on <img>, <canvas>, and other elements that accept pixel dimensions. The integer you provide represents a size in CSS pixels, so height="480" means 480 CSS pixels — no unit suffix is needed or allowed.
Why this matters
- Standards compliance: The HTML living standard explicitly defines these attributes as non-negative integers. Using percentages violates the spec and produces a validation error.
- Browser behavior: While some browsers may attempt to interpret a percentage value, the behavior is undefined and inconsistent. You cannot rely on it working correctly across all browsers and versions.
- Layout stability: Providing valid width and height integer values helps browsers reserve the correct aspect ratio for the video before it loads, reducing cumulative layout shift (CLS). Invalid values undermine this benefit.
How to fix it
- Replace the percentage value with a plain integer representing the desired pixel height.
- If you need percentage-based or responsive sizing, remove the percentage from the HTML attribute and use CSS instead. CSS width and height properties fully support percentage values, viewport units, and other flexible sizing methods.
- Always keep integer width and height attributes on the element when possible, even if you also use CSS for responsive sizing. This provides an intrinsic aspect ratio hint to the browser.
Examples
❌ Invalid: percentage value in the height attribute
<video controls width="100%" height="50%">
<source src="/media/video.webm" type="video/webm">
</video>
The validator reports: Bad value “50%” for attribute “height” on element “video”: Expected a digit but saw “%” instead. The same error applies to the width="100%" attribute.
✅ Fixed: integer values for intrinsic dimensions
<video controls width="640" height="480">
<source src="/media/video.webm" type="video/webm">
</video>
Both width and height use plain integers representing CSS pixels. This is valid and gives the browser an aspect ratio hint (4:3 in this case).
✅ Fixed: responsive sizing with CSS
If you need the video to scale as a percentage of its container, use CSS for the sizing while keeping valid integer attributes for the aspect ratio:
<video controls width="640" height="360" style="width: 100%; height: auto;">
<source src="/media/video.webm" type="video/webm">
</video>
Here, width="640" and height="360" tell the browser the video’s intrinsic aspect ratio (16:9), while the inline style (or an external stylesheet) makes the video fill 100% of its container width and scale its height proportionally. This approach is both valid HTML and fully responsive.
✅ Fixed: using a CSS class for responsive video
<style>
.responsive-video {
width: 100%;
max-width: 800px;
height: auto;
}
</style>
<video controls width="800" height="450" class="responsive-video">
<source src="/media/video.webm" type="video/webm">
</video>
This keeps the HTML valid, provides an aspect ratio hint, and achieves flexible, percentage-based sizing entirely through CSS.
The poster attribute specifies an image to display as a placeholder while the video is loading or before the user starts playback. Like all HTML attributes that accept URLs — such as src, href, and action — the value must conform to valid URI syntax as defined by RFC 3986. In this standard, a literal space character is not a legal character in any part of a URL. When the validator encounters a space in the poster attribute’s value, it flags it as an illegal character in the path segment.
While most modern browsers are forgiving and will attempt to resolve URLs containing raw spaces by internally encoding them, relying on this behavior is problematic for several reasons:
- Standards compliance: The HTML specification requires valid URLs. Raw spaces violate this requirement.
- Interoperability: Not all user agents, HTTP clients, or content delivery systems handle unencoded spaces the same way. Some may truncate the URL at the first space or fail to resolve the resource entirely.
- Portability: If your HTML is consumed by tools, scrapers, or APIs that strictly parse URLs, unencoded spaces can cause silent failures.
- Consistency: Keeping URLs properly encoded prevents subtle bugs when paths are constructed dynamically in server-side or client-side code.
The fix is straightforward. You have two options:
- Percent-encode the spaces: Replace every space in the URL with %20. This preserves the original file and folder names on the server while producing a valid URL in your HTML.
- Eliminate spaces from file and folder names: Use hyphens (-), underscores (_), or camelCase instead of spaces. This is generally considered best practice for web assets, as it avoids encoding issues across the board.
Note that this rule applies to the entire URL path, not just the filename. If any directory in the path contains a space, it must also be encoded or renamed. The same principle applies to other special characters that are reserved or disallowed in URLs, such as {, }, |, ^, and [.
Examples
Incorrect — space in the path
The folder name video images contains a space, which is illegal in a URL path segment.
<video controls poster="/img/video images/snapshot.png">
<source src="/videos/sample.mp4" type="video/mp4">
</video>
Incorrect — space in the filename
The filename my poster.jpg also triggers the same error.
<video controls poster="/img/my poster.jpg">
<source src="/videos/sample.mp4" type="video/mp4">
</video>
Fixed — percent-encoding the spaces
Each space is replaced with %20, producing a valid URL.
<video controls poster="/img/video%20images/snapshot.png">
<source src="/videos/sample.mp4" type="video/mp4">
</video>
Fixed — removing spaces from the path
Renaming the folder to use a hyphen eliminates the need for encoding entirely.
<video controls poster="/img/video-images/snapshot.png">
<source src="/videos/sample.mp4" type="video/mp4">
</video>
Fixed — removing spaces from the filename
<video controls poster="/img/my-poster.jpg">
<source src="/videos/sample.mp4" type="video/mp4">
</video>
As a general best practice, avoid spaces in all file and folder names used on the web. Use hyphens or underscores instead. If you’re working with files you can’t rename — such as assets from a CMS or third-party system — always percent-encode spaces as %20 in your HTML. This applies not only to poster but to every attribute that takes a URL value, including src, href, action, data, and formaction.
The HTML specification defines the width attribute on <video> as a “valid non-negative integer,” which means it must consist only of digits (e.g., 640). It cannot include units like px, em, or %. When you write something like width="100%", the validator expects a digit character but encounters the % sign, producing this error.
This is a common mistake because CSS allows percentage values for width, and some older HTML elements (like <table>) historically accepted percentage values in their width attributes. However, the <video> element follows the modern HTML specification, which restricts width to pixel integers only.
Why this matters
- Standards compliance: Browsers may interpret invalid attribute values unpredictably. While most modern browsers might ignore the % and attempt to parse the number, this behavior is not guaranteed.
- Responsive design intent is lost: Even if a browser tries to handle width="100%", it may treat it as width="100" (100 CSS pixels), which is almost certainly not what you intended.
- Accessibility and consistency: Valid markup ensures assistive technologies and all browsers render your content as expected.
How to fix it
If you need a fixed pixel width, set the width attribute to a plain integer. If you need a responsive or percentage-based width, remove the width attribute entirely and use CSS.
Examples
❌ Invalid: percentage value in the width attribute
<video controls width="100%">
<source src="/media/video.mp4" type="video/mp4">
</video>
✅ Fixed: using a pixel integer for a fixed width
<video controls width="640" height="360">
<source src="/media/video.mp4" type="video/mp4">
</video>
✅ Fixed: using CSS for a percentage-based width
<video controls style="width: 100%;">
<source src="/media/video.mp4" type="video/mp4">
</video>
✅ Fixed: using an external stylesheet for responsive video
<style>
.responsive-video {
width: 100%;
max-width: 800px;
height: auto;
}
</style>
<video controls class="responsive-video">
<source src="/media/video.mp4" type="video/mp4">
</video>
The CSS approach is generally preferred for responsive layouts because it gives you much more control — you can combine width, max-width, and height: auto to create a video that scales proportionally within its container. The width and height HTML attributes are best used when you want to specify the video’s intrinsic dimensions in pixels, which also helps the browser reserve the correct amount of space before the video loads, reducing layout shifts.
¿Listo para validar tus sitios?
Comienza tu prueba gratuita hoy.