简体   繁体   中英

Nested <p> tag auto-closing/opening

I'm seeing some weird behavior around nested <p> tags. See this for the test case.

Given:

<p>
  <p>
    <p>
      <p>
        <p>
          <p>
          </p>
        </p>
      </p>
    </p>
  </p>
</p>

In Chrome, this results in

<p>
  </p><p>
    </p><p>
      </p><p>
        </p><p>
          </p><p>
          </p>
        <p></p>
      <p></p>
    <p></p>
  <p></p>
<p></p>

That is, it closes opening tags and opens closing tags. I've heard (of course) of "self-closing tags"; I've never heard of "self-opening tags".

IE11 does it a different (and arguably, even wronger) way:

<p>
  <p>
    <p>
      <p>
        <p>
          <p>
          </p>
        <p></p>
      <p></p>
    <p></p>
  <p></p>
<p></p>

So it does not auto-close opening tags, but it does auto-open close tags, resulting in an unbalanced DOM tree.

Anyway, I'm curious what the proper path to address this; should I open issues on Chrome and IE bug trackers? I'm not particularly well versed in the W3C specs, where would I go to try and find the "correct" behavior (I'm not aware of any tags apart from <p> that exhibit this behavior, although I haven't done extensive testing)?

For what it's worth, I realize nesting <p> tags is invalid; this is a result of a third party library that I am working to address with them, I just found this to be bizarre behavior).

EDIT: I was wrong about IE: see https://jsbin.com/ripaxe/5/edit?html,js,output . Turns out innerHTML is browser dependent. Didn't realize that.

This isn't a bug. <p> elements cannot be nested within other <p> elements as you've said.

Chrome is attempting to fix your code by closing your <p> tags for you, and is thus generating this markup. I'd suggest raising a bug report with the third-party library you're using instead as this isn't a browser-specific problem.

Your test case uses innerHTML to display the serializations of your markup. Unsurprisingly IE tends to do things differently to other browsers, but neither browser's representation of your markup is wrong per se .

Chrome (and Firefox) inserts explicit </p> end tags to show exactly where each <p> start tag terminates. Each start tag terminates immediately before the next start tag (except the last one, which is terminated by its end tag). Notice that the whitespace is enclosed within each pair.

But the explicit end tags are not needed, and IE simply chooses not to insert end tags to match any of the start tags for that reason. That doesn't mean that there is any nesting going on — all of the p elements are still siblings, and you can verify this with the fact that document.querySelector('p p') returns null and document.querySelector('p:nth-child(11):last-child') returns the element represented by the very last </p> end tag in all browsers.

The end tags that are in your original markup are preserved, of course, but the reason all but the first end tag are matched with their own start tags ( without enclosing the whitespace this time) is described in Why does a stray </p> end tag generate an empty paragraph? — in short, it's specced by HTML5 for consistency with legacy browser behavior.

The end tag for the p element being optional is also the reason why both representations are equally valid (and, in fact, functionally equivalent) HTML fragments. So, there is nothing wrong with what IE is doing, but it does create headaches for authors relying on the innerHTML property simply because it does things differently.

But this is why you shouldn't rely on innerHTML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM