HTML Guides for unrecognized at-rule
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.
The @font-feature-values at-rule lets you define human-readable names for OpenType font feature indexes, which you can then reference using properties like font-variant-alternates. For example, instead of remembering that swash index 1 maps to a "fancy" style, you can define a named value and use it semantically throughout your CSS. This is a legitimate and useful feature defined in the CSS Fonts Module Level 4 specification.
The validation error occurs because the W3C CSS validator does not always keep pace with newer CSS specifications. The @font-feature-values rule, along with its associated feature type blocks like @swash, @styleset, @character-variant, @ornaments, @annotation, and @stylistic, may simply not be in the validator's recognized grammar yet. This does not mean your CSS is broken or invalid — it means the validator has a gap in its coverage.
That said, there are practical reasons to consider alternatives. If you need to pass strict W3C validation (for example, as a project requirement or contractual obligation), or if you need to support older browsers that lack @font-feature-values support, the font-feature-settings property offers a more widely recognized way to activate OpenType features. The tradeoff is that font-feature-settings uses raw four-character OpenType feature tags instead of friendly names, making it less readable but more portable.
How to Fix
You have several options:
- Ignore the warning. If your target browsers support
@font-feature-values, the CSS is valid per the spec. The validator error is a false positive. - Move the at-rule to an external stylesheet. If you're validating HTML and the CSS is in a
<style>block, moving it to an external.cssfile may help you separate concerns and skip CSS validation during HTML checks. - Replace with
font-feature-settings. Use the lower-level property to activate OpenType features directly by their tag codes.
Examples
Code that triggers the validation error
@font-feature-values"MyFamily"{
@swash{
fancy:1;
}
}
p{
font-family:"MyFamily", serif;
font-variant-alternates:swash(fancy);
}
The validator does not recognize @font-feature-values and flags it as an error, even though this is spec-compliant CSS.
Fixed: Using font-feature-settings instead
<!DOCTYPE html>
<htmllang="en">
<head>
<title>Font Feature Example</title>
<style>
p{
font-family:"MyFamily", serif;
font-feature-settings:"swsh"1;
}
</style>
</head>
<body>
<p>This text uses OpenType swash glyphs via font-feature-settings.</p>
</body>
</html>
The font-feature-settings property accepts OpenType feature tags directly. Common tags include "swsh" for swashes, "smcp" for small caps, "liga" for standard ligatures, and "onum" for oldstyle numerals. This approach avoids the unrecognized at-rule error entirely.
Fixed: Keeping @font-feature-values with a fallback
If you want to use the more readable @font-feature-values syntax while also providing fallback support, you can combine both approaches:
p{
font-family:"MyFamily", serif;
font-feature-settings:"swsh"1;
font-variant-alternates:swash(fancy);
}
@font-feature-values"MyFamily"{
@swash{
fancy:1;
}
}
Browsers that understand font-variant-alternates and @font-feature-values will use the named value. Others will fall back to font-feature-settings. The validation error will persist with this approach, but your CSS will be robust and spec-compliant regardless.
The @media screen rule without a condition after the media type is invalid CSS syntax and will be flagged by the W3C validator.
A @media rule requires either a complete media query or a media type combined with a media feature expression. Writing @media screen alone followed by a block is actually valid CSS, so this error typically appears when the syntax inside the rule is malformed, the rule is missing curly braces, or extra characters appear between screen and the opening brace.
Common causes include:
- A missing opening or closing curly brace
{}around the media block. - Stray characters or typos between the media type and the brace.
- Placing
@mediarules inside astyleattribute (inline styles do not support at-rules). - The CSS appears inside an HTML context where the validator cannot parse it correctly, such as a malformed
<style>element.
If the intent is to target screens of a specific size, a media feature expression is required, like @media screen and (min-width: 768px). If the intent is to target all screen devices with no further conditions, @media screen is valid CSS on its own, and the real problem is likely a syntax error nearby.
Example with the issue
<style>
@media screen
.container{
width:80%;
}
</style>
The opening curly brace for the @media block is missing, so the validator cannot recognize the rule.
Fixed example
<style>
@media screen {
.container{
width:80%;
}
}
</style>
If the goal is to restrict styles to a specific viewport width, add a media feature:
<style>
@media screen and(min-width:768px){
.container{
width:80%;
}
}
</style>
Both examples use properly matched curly braces and valid @media syntax, which resolves the validator error.
The @tailwind directive is used in Tailwind CSS source files to inject Tailwind's generated styles into your stylesheet. Common usages include @tailwind base;, @tailwind components;, and @tailwind utilities;. These directives act as placeholders that Tailwind's build tool (such as the Tailwind CLI or PostCSS plugin) replaces with actual CSS rules during compilation.
The W3C CSS Validator checks stylesheets against official CSS specifications maintained by the W3C. Since @tailwind is not defined in any CSS specification — it's a framework-specific extension — the validator correctly flags it as unrecognized. This doesn't mean your CSS is broken or will cause problems in browsers; it simply means the validator doesn't know what @tailwind is.
This distinction matters because the @tailwind directives should never appear in production CSS served to browsers. If you're seeing this validation error on a live website, it could indicate one of two things: either you're linking directly to your uncompiled Tailwind source file (which is a problem), or the validator is checking your source CSS rather than the compiled output.
How to Fix It
Ensure you're serving compiled CSS
The most important step is to make sure your build pipeline is correctly processing your Tailwind source files. The compiled output should contain only standard CSS — no @tailwind directives. Verify that your <link> tags point to the compiled CSS file, not the source file.
Use the Tailwind CDN or CLI correctly
If you're using the Tailwind CLI, run the build command to generate a compiled stylesheet and reference that file in your HTML. The compiled file will contain only valid CSS.
Consider suppressing the warning
If the validator is checking your source CSS (for example, inline <style> blocks that get processed client-side), and you're confident the directives are being handled correctly, you can safely suppress or ignore this specific warning in your validation reports.
Examples
Source CSS that triggers the warning
This is a typical Tailwind CSS source file that the validator will flag:
@tailwind base;
@tailwind components;
@tailwind utilities;
.custom-button{
padding:0.5rem1rem;
border-radius:0.25rem;
}
Each @tailwind line will produce an "Unrecognized at-rule" warning from the W3C Validator.
Correct approach: serve compiled CSS
After running the Tailwind build process, the output file contains only standard CSS:
*,::before,::after{
box-sizing: border-box;
}
.custom-button{
padding:0.5rem1rem;
border-radius:0.25rem;
}
.flex{
display: flex;
}
.text-center{
text-align: center;
}
Reference this compiled file in your HTML:
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="utf-8">
<title>My Page</title>
<linkrel="stylesheet"href="css/output.css">
</head>
<body>
<pclass="text-center">Hello, world!</p>
</body>
</html>
Avoid linking to uncompiled source files
This is incorrect — it links directly to the source file containing @tailwind directives:
<!-- Don't do this -->
<linkrel="stylesheet"href="css/input.css">
Instead, always link to the build output:
<!-- Do this -->
<linkrel="stylesheet"href="css/output.css">
By ensuring your production site serves only the compiled CSS output, you eliminate the @tailwind at-rule warnings entirely and deliver valid, standards-compliant stylesheets to your users.
The @view-transition at-rule is valid CSS but is not yet recognized by the W3C CSS validator because it is a relatively new feature defined in the CSS View Transitions Module Level 2 specification.
The @view-transition at-rule opts a document into cross-document view transitions when navigating between two same-origin pages. It is placed in the CSS of the destination page (the page being navigated to) and accepts a navigation descriptor that controls when the transition activates.
@view-transition{
navigation: auto;
}
The navigation descriptor accepts these values:
none— no cross-document view transition occurs (default).auto— the transition activates for same-origin navigations where the navigation type is traverse, push, or replace, as long as the navigation does not include a cross-origin redirect.
Because the W3C CSS validator has not yet added support for this at-rule, the warning cannot be fixed by changing your code. The CSS itself is correct per the specification. Browser support is available in Chromium-based browsers (Chrome 126+, Edge 126+).
You can safely ignore this validator warning. If you want a completely clean validation output, move the @view-transition rule into a separate stylesheet so it does not interfere with validation of the rest of your CSS, or suppress the warning in your CI pipeline.
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries