Element style not allowed as child of element body in this context (<style scoped> not validating)

mikeybeck picture mikeybeck · Dec 18, 2014 · Viewed 30.6k times · Source
<!DOCTYPE html>
...
<style scoped>
/* css */
</style>

The w3.org validator is giving me this error:

Line 883, Column 17: Element style not allowed as child of element body in this context.
(Suppressing further errors from this subtree.)
        <style scoped>...
Contexts in which element style may be used:
If the scoped attribute is absent: where metadata content is expected.
If the scoped attribute is absent: in a noscript element that is a child of a head element.
If the scoped attribute is present: where flow content is expected, but before any other flow     content other than inter-element whitespace and style elements, and not as the child of an element whose content model is transparent.
Content model for element body:
Flow content.

It is my understanding that the 'scoped' property makes it ok for the style tag to be outside the head of the document. So why is the validator unhappy with it?

(I'm using Wordpress and this code is produced by a plugin, which is why I can't just put it in the head.)

EDIT: This doesn't validate -

<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<script type="text/javascript"></script>
<style scoped></style>
</body>
</html>

But it does if the script tag goes after the style tag. What is the reason for that?

Answer

Jukka K. Korpela picture Jukka K. Korpela · Dec 18, 2014

The W3C Markup Validator, when acting as an HTML5 checker, handles this issue according to various drafts such as HTML 5.1 Nightly, which right now says that the style element may appear only inside the head element, except when the scoped attribute is present, in which case it may appear “where flow content is expected, but before any other flow content other than inter-element whitespace and style elements, and not as the child of an element whose content model is transparent”. In your actual example, the element appears after a script element (which is counted as flow content). Changing the order of the elements thus changes the syntax to valid, under the given definition.

Alternatively, you can just wrap the style element in a div element:

<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<script type="text/javascript"></script>
<div>
  <style scoped></style>
</div>
</body>
</html>

The scoped attribute is not valid at all according to the W3C Recommendation HTML5. It was present in HTML5 drafts, but it was dropped from the Recommendation due to lack of implementations, but it is still in the “standardization track” and may make its way to HTML 5.1.

Note that existing browsers generally ignore the scoped attribute and allow a style element almost anywhere and apply its content to the entire HTML document (even parts that precede the style element).