List with nested `overflow-x: hidden` hides list counter/point - why/is this a bug?
Asked Answered
T

2

10

http://jsfiddle.net/G46dK/

<ol>
    <li>
        <p>
            Moo
    <li>
        <p class="overflow-hidden">
            Moo
    <li>
        <p class="overflow-hidden">
            Moo
    <li>
        <p>
            Moo
</ol>

With the accompanying CSS:

p.overflow-hidden {
    overflow-x: hidden;
}

You'd expect something like

  1. Moo
  2. Moo
  3. Moo
  4. Moo

but on my Safari and Chrome... the "2." and "3." are hidden (but their "Moo" is still there):

Ordered list missing some counts

Why does the overflow affect the list counter/point at all? It's on a <p> tag that's inside the list... agh it hurts my brain ><

Am I losing my mind, or is this a bug?

If it's not a bug.. is anybody able to explain it?

I imagined the "2." belongs to the li whereas the overflow-x: hidden is applied to the child p. As such even though the "2." is outside the p... it's got no relationship with the overflow-x: hidden and should therefore be left unaffected - but that's not the case.. What is the case?

Tannenwald answered 14/2, 2014 at 1:36 Comment(4)
+1 for discovering an interesting phenomenon. And the behaviour in IE10 is even weirder: it adds a vertical margin to the p with the class. No idea why it would do that. (If you can't see IE, here is a screenshot: i.sstatic.net/EtBaA.png)Suber
overflow-y has the same effect as well on my tests. I am guessing it's a browser bug, yes.Seriocomic
Thanks a lot for this SO, I encountered the very same bug in a webapp. And it's not even a new issue, has been around for years. I opened code.google.com/p/chromium/issues/detail?id=344941Dasya
Pleasure.. It's a surprising bug, seems like really fundamental behaviour - I mean there's no weird CSS hacks going on hereTannenwald
A
11

Your understanding is correct; the list number (known in CSS as a list marker) should exist outside the p, not inside it. That should be the case even if you specify list-style-position: inside because like you said, you're applying overflow to the p, not the li.

Every list item in general creates a principal block box for its children, and another box for the marker to reside in. The child elements should all be rendered within the principal block box. From the CSS2.1 spec:

CSS 2.1 offers basic visual formatting of lists. An element with 'display: list-item' generates a principal block box for the element's content and, depending on the values of 'list-style-type' and 'list-style-image', possibly also a marker box as a visual indication that the element is a list item.

A slightly more detailed explanation of principal block boxes can be found here.

In your case, each li creates a principal block box and a marker box. The p.overflow-hidden elements should reside in the principal block box and not affect the marker. Here's a crude ASCII art diagram to show what I mean:

list
marker   li principal block box
+-----+  +----------------------------+
|     |  |+--------------------------+|
|  •  |  || Moo        (p block box) ||
|     |  |+--------------------------+|
+-----+  +----------------------------+

Now, the spec seems vague about the positioning of the marker box itself, but it does say that the marker box is separate from the principal block box when list-style-position is outside. It does seem to imply also that a browser could get away with placing the marker box in the principal block box so long as the marker content actually resides by itself in that marker box (which, incidentally, cannot be targeted with CSS as yet).

But Safari and Chrome appear to be doing something very different altogether: they seem to be putting the marker box not only within the principal box, but within the first child of the principal block box. That's why it gets cut off when positioned outside the p block box: because the rendering engine sees it as part of the p content, sees that it's out of its horizontal bounds, and cuts it off. (I suspect it gets clipped with overflow-y: hidden as well because it's positioned beyond the left edge, which shouldn't normally happen in LTR mode, but that's just a wild guess.)

When you add list-style-position: inside to the li, other browsers correctly shift the p block box beneath the marker, but Safari and Chrome simply move the marker into the p box. Although CSS2.1 says that it doesn't define the exact position of a list marker with respect to the list item's principal block box, it does say this about list-style-position: inside:

inside
The marker box is placed as the first inline box in the principal block box, before the element's content and before any :before pseudo-elements.

That's clearly not what Safari and Chrome are doing with the marker box.

Again, the spec is (rather deliberately) not 100% clear about this, but I would certainly not expect the list marker to be a child of, or be affected by, any of the li's child elements the way it appears to in Safari and Chrome. I'm pretty sure this is incorrect behavior, i.e. a bug.

Auriscope answered 14/2, 2014 at 11:34 Comment(3)
Or maybe I'm just sick of browsers taking advantage of loopholes and unspecified behavior in the spec and deviating from the norm just because they can.Auriscope
On the bright side, there's a new module for CSS lists in development, which introduces a dedicated pseudo-element for markers and specifies much of the behavior that was handwaved by CSS2.1.Auriscope
And that's why I often state that Safari and Chrome are the new IE.Auriscope
G
2

I found a solution, but unfortunately, I can't explain why Chrome behaves this way... It seems related to the display: block behaviour.

I changed it to display: inline-block; and adapt the vertical-align to keep displayal coherent (but it's not needed).

p.overflow-hidden {
  overflow-x: hidden;
  vertical-align: -20px;
  display: inline-block;
}

have a look at the updated fiddle.

Genoa answered 14/2, 2014 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.