Custom/Builtin Elements Inside HTML Paragraphs

26 Views Asked by At

Consider the following semi-minimal example, paying particular attention to the paragraph elements:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <style>
      h4 { display: inline-block; }
      spoiler       { background-color: black  ; }
      spoiler:hover { background-color: inherit; }
    </style>
    <title>Paragraphs Test</title>
  </head>
  <body>
    <p><h4>Heading</h4>: This is a paragraph.</p>
    <p>The following is <spoiler>spoilered text</spoiler>.</p>
  </body>
</html>

When I run this through W3 Validator, I get one error for each paragraph:

No p element in scope but a p end tag seen.
    From line 12, column 46; to line 12, column 49
    paragraph.</p>↩ <

Element spoiler not allowed as child of element p in this context. (Suppressing further errors from this subtree.)
    From line 13, column 25; to line 13, column 33
    lowing is <spoiler>spoile

I did my best to understand what the standard says on the contents of <p>: the required contents must be "Phrasing Content" which cannot be <h4>. It can be an "Autonomous Custom Element", which is a custom element with no extends option.


I don't really understand how this applies for this situation. It seems to me like any inline/block-inline element should be able to go inside <p>—the prototypical example being the contrast between <div> (block) and <span> (inline): the former can't go in, but the latter can.

In the first case, I'm explicitly marking <h4> inline. Albeit, I guess since it isn't mentioned as being allowed, I guess I'm just not allowed to do this, arbitrarily? However, in the second case, I'm using a custom element, and I'm not using extends (at least explicitly? Not even sure what it is!). Moreover custom elements are apparently display: inline by default. So why doesn't that work?


Sooo, why does the above example of putting elements inside paragraphs not work? And, how can I get what I want? (Obviously, in a way that doesn't give up semantics, like the following would: <p><b>Heading</b>...</p>, <p>...<span class="spoiler">...</span>.</p>)


Note: this is not a duplicate of e.g. "HTML tags inside paragraph <p>", which was about un-semantically nesting <p> inside <p>.

1

There are 1 best solutions below

0
geometrian On

For the first line—

<p><h4>Heading</h4>: This is a paragraph.</p>

—you answered yourself already. Indeed, <h4> is not listed as valid within a phrasing context, so you just can't do it. In fact, the <p> element, when it encounters a <h4> inside it, will auto-close itself first. Thus, you can't use <h4> inside <p>: if you try, the <p> will close itself first, and then when you try to close it later it fails because you're not in a paragraph anymore.

The stuff you said about inline elements vs. block elements is just wishful thinking, and you knew it at the time. The standard doesn't care about the display of the element for this purpose, so you shouldn't either.

Putting aside the wisdom of these design choices, or any exonerating historical circumstances explaining how they arose, your options are prettymuch just to use <b>, or something more sophisticated like a styled <span>. This is exactly what you said would be admitting defeat, but the standard says no.


For the second line—

<p>The following is <spoiler>spoilered text</spoiler>.</p>

—you were very nearly right. You can have "Autonomous Custom Elements" inside phrasing contexts. However, as MDN will highlight, custom elements must have a dash, per the grammar. If you rewrite your example from <spoiler> to <spo-iler>, for example, it will work great. You might have thought a little harder when you noticed that your IDE wasn't highlighting it.

This one, though, you can be forgiven for not getting immediately. The validator's error ("Element spoiler not allowed as child") is hilariously misleading. It's not that the element isn't allowed as a child, it's that it isn't an element at all. In my view, the error message should be corrected, and so you will be submitting a bug report.