Skip to content

Linter Rule: Require head-scoped elements inside <head>

Rule: html-head-only-elements

Description

Enforce that certain elements only appear inside the <head> section of the document.

Elements like <title>, <meta>, <base>, <link>, and <style> are permitted only inside the <head> element. They must not appear inside <body> or outside of <html>. Placing them elsewhere produces invalid HTML and relies on browser error correction.

Exception

<title> elements are allowed inside <svg> elements for accessibility purposes.

Rationale

The HTML specification requires certain elements to appear only in the <head> section because they affect document metadata, resource loading, or global behavior:

Placing these elements outside <head> leads to invalid HTML and undefined behavior across browsers.

Examples

✅ Good

erb
<head>
  <title>My Page</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="/styles.css">
</head>

<body>
  <h1>Welcome</h1>
</body>
erb
<head>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= favicon_link_tag 'favicon.ico' %>
  <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>

  <title><%= content_for?(:title) ? yield(:title) : "Default Title" %></title>
</head>
erb
<body>
  <svg>
    <title>Chart Title</title>
    <rect width="100" height="100" />
  </svg>
</body>

🚫 Bad

erb
<body>
  <title>My Page</title>
Element `<title>` must be placed inside the `<head>` tag. (html-head-only-elements)
<meta charset="UTF-8">
Element `<meta>` must be placed inside the `<head>` tag. (html-head-only-elements)
<link rel="stylesheet" href="/styles.css">
Element `<link>` must be placed inside the `<head>` tag. (html-head-only-elements)
<h1>Welcome</h1> </body>
erb
<body>
  <title><%= content_for?(:title) ? yield(:title) : "Default Title" %></title>
Element `<title>` must be placed inside the `<head>` tag. (html-head-only-elements)
</body>

References

Released under the MIT License.