Guias HTML para async
Aprenda como identificar e corrigir erros comuns de validação HTML sinalizados pelo W3C Validator — para que as suas páginas cumpram os padrões e sejam renderizadas corretamente em todos os navegadores. Consulte também o nosso Guias de acessibilidade.
The HTML specification defines boolean attributes as attributes whose presence indicates a true state and whose absence indicates false. According to the WHATWG HTML standard, a boolean attribute may only have three valid representations:
- The attribute name alone (e.g., async)
- The attribute with an empty string value (e.g., async="")
- The attribute with a value matching its own name, case-insensitively (e.g., async="async")
Any other value — such as async="true", async="1", async="yes", or async="false" — is invalid HTML and will trigger this validation error. This is a common misunderstanding because developers often assume boolean attributes work like boolean values in programming languages, where you’d assign true or false.
Why this matters
While most browsers are lenient and will treat any value of async as the true state (since the attribute is present regardless of its value), using invalid values creates several problems:
- Standards compliance: Invalid HTML may cause issues with strict parsers, validators, or tools that process your markup.
- Misleading intent: Writing async="false" does not disable async behavior — the attribute is still present, so the browser treats it as enabled. This can lead to confusing bugs where a script behaves asynchronously even though the developer intended otherwise.
- Maintainability: Other developers reading the code may misinterpret async="false" as actually disabling async loading.
To disable async behavior, you must remove the attribute entirely rather than setting it to "false".
How async works
For classic scripts with a src attribute, the async attribute causes the script to be fetched in parallel with HTML parsing and executed as soon as it’s available, without waiting for the document to finish parsing.
For module scripts (type="module"), the async attribute causes the module and all its dependencies to be fetched in parallel and executed as soon as they are ready, rather than waiting until the document has been parsed (which is the default deferred behavior for modules).
Examples
❌ Invalid: arbitrary values on async
<!-- Bad: "true" is not a valid boolean attribute value -->
<script async="true" src="app.js"></script>
<!-- Bad: "1" is not a valid boolean attribute value -->
<script async="1" src="analytics.js"></script>
<!-- Bad: "yes" is not a valid boolean attribute value -->
<script async="yes" src="tracker.js"></script>
<!-- Bad and misleading: this does NOT disable async -->
<script async="false" src="app.js"></script>
✅ Valid: correct boolean attribute usage
<!-- Preferred: attribute name alone -->
<script async src="app.js"></script>
<!-- Also valid: empty string value -->
<script async="" src="app.js"></script>
<!-- Also valid: value matching attribute name -->
<script async="async" src="app.js"></script>
<!-- Correct way to disable async: remove the attribute -->
<script src="app.js"></script>
✅ Valid: async with module scripts
<script async type="module" src="app.mjs"></script>
<script async type="module">
import { init } from './utils.mjs';
init();
</script>
This same rule applies to all boolean attributes in HTML, including defer, disabled, checked, required, hidden, and others. When in doubt, use the attribute name on its own with no value — it’s the cleanest and most widely recognized form.
When the browser’s HTML parser encounters a src attribute, it expects the value between the opening and closing quotes to be a valid URL. URLs have strict rules about which characters are permitted — a literal double quote (") is not one of them. If a " character appears inside the URL, the validator flags it as an illegal character in the query string (or other parts of the URL).
This error often doesn’t stem from an intentionally embedded quote in the URL itself. Instead, it’s usually a symptom of malformed HTML around the attribute. Common causes include:
- Stray quotes after the attribute value, such as writing src="https://example.com/script.js"async"" instead of properly separating attributes.
- Accidentally doubled closing quotes, like src="https://example.com/script.js"".
- Boolean attributes given empty-string values incorrectly, such as async"" instead of just async, which causes the parser to interpret the extra quotes as part of the preceding src value.
- Copy-paste errors that introduce smart quotes (" ") or extra quotation marks into the URL.
This matters for several reasons. Malformed src attributes can cause the script to fail to load entirely, breaking functionality on your page. It also violates the HTML specification, which can lead to unpredictable behavior across different browsers as each parser tries to recover from the error differently.
To fix the issue, carefully inspect the <script> tag and ensure that:
- The src attribute value contains only a valid URL with no unescaped " characters.
- The opening and closing quotes around the attribute value are properly balanced.
- Attributes are separated by whitespace — not jammed together.
- Boolean attributes like async and defer are written as bare keywords without values.
If you genuinely need a double quote character in a query string (which is rare), encode it as %22.
Examples
Incorrect — stray quotes between attributes
In this example, the async attribute is malformed as async"", which causes the parser to interpret the extra quotes as part of the src URL:
<script src="https://example.com/js/app.js?ver=3.1" async""></script>
Incorrect — doubled closing quote
Here, an extra " at the end of the src value creates an illegal character in the URL:
<script src="https://example.com/js/app.js?ver=3.1""></script>
Incorrect — smart quotes from copy-paste
Curly/smart quotes copied from a word processor are not valid HTML attribute delimiters and get treated as part of the URL:
<script src="https://example.com/js/app.js?ver=3.1"></script>
Correct — clean attributes with proper quoting
<script src="https://example.com/js/app.js?ver=3.1" async></script>
Correct — boolean attribute written as a bare keyword
Boolean attributes like async and defer don’t need a value. Simply include the attribute name:
<script src="https://example.com/js/app.js?ver=3.1" defer></script>
While async="async" is technically valid per the spec, the cleanest and most common form is the bare attribute. Avoid empty-string patterns like async="" placed without proper spacing, as they can lead to the exact quoting errors described here.
Correct — full valid document
<!DOCTYPE html>
<html lang="en">
<head>
<title>Valid Script Example</title>
<script src="https://example.com/js/app.js?ver=3.1" async></script>
</head>
<body>
<p>Page content here.</p>
</body>
</html>
If you’re generating <script> tags dynamically (through a CMS, template engine, or build tool), check the template source rather than just the rendered output. The stray quotes are often introduced by incorrect string concatenation or escaping logic in the server-side code.
The async attribute tells the browser to download and execute a script without blocking HTML parsing. For external scripts (those with a src attribute), this means the browser can continue parsing the page while fetching the file, then execute the script as soon as it’s available. For inline module scripts (type="module"), async changes how the module’s dependency graph is handled — the module and its imports execute as soon as they’re all ready, rather than waiting for HTML parsing to complete.
For a classic inline script (no src, no type="module"), there is nothing to download asynchronously. The browser encounters the code directly in the HTML and executes it immediately. Applying async in this context is meaningless and contradicts the HTML specification, which is why the W3C validator flags it as an error.
Beyond standards compliance, using async incorrectly can signal a misunderstanding of script loading behavior, which may lead to bugs. For example, a developer might mistakenly believe that async on an inline script will defer its execution, when in reality it has no effect and the script still runs synchronously during parsing.
How to Fix
You have several options depending on your intent:
- If the script should be external, move the code to a separate file and reference it with the src attribute alongside async.
- If the script should be an inline module, add type="module" to the <script> tag. Note that module scripts are deferred by default, and async makes them execute as soon as their dependencies are resolved rather than waiting for parsing to finish.
- If the script is a plain inline script, simply remove the async attribute — it has no practical effect anyway.
Examples
❌ Invalid: async on a classic inline script
<script async>
console.log("Hello, world!");
</script>
This triggers the validator error because there is no src attribute and the type is not "module".
✅ Fixed: Remove async from the inline script
<script>
console.log("Hello, world!");
</script>
✅ Fixed: Use async with an external script
<script async src="app.js"></script>
The async attribute is valid here because the browser needs to fetch app.js from the server, and async controls when that downloaded script executes relative to parsing.
✅ Fixed: Use async with an inline module
<script async type="module">
import { greet } from "./utils.js";
greet();
</script>
This is valid because module scripts have a dependency resolution phase that can happen asynchronously. The async attribute tells the browser to execute the module as soon as all its imports are resolved, without waiting for the document to finish parsing.
❌ Invalid: async with type="text/javascript" (not a module)
<script async type="text/javascript">
console.log("This is still invalid.");
</script>
Even though type is specified, only type="module" satisfies the requirement. The value "text/javascript" is the default classic script type and does not make async valid on an inline script.
Pronto para validar os seus sites?
Comece o seu teste gratuito hoje.