Alexander Gelbukh
Alexander Gelbukh

Reputation: 2230

Strange behavior of an HTML list with a specific CSS

With this CSS:

li { margin-top: -1px;   }
li:before { content: "x"; float:left; }

under <!doctype html>, a standard <ul> list shows a shifted pattern:

Why?

Removing margin-top: -1px; or making it positive cancels the effect: the list is shown normally.

Here is a jsfiddle. I checked in FireFox, Chrome, IE.

The list was

<ul>
    <li>y</li>
    <li>y</li>
    <li>y</li>
</ul>

Note: my question is not how to avoid it, but why it happens -- to understand how CSS works.

Upvotes: 2

Views: 68

Answers (5)

Imanuel
Imanuel

Reputation: 3667

The floated elements are clipping / stacking.

Use background: red; on li:before to see it.

Here is the updated fiddle

Either remove the float: left; or the margin-top: -1px to fix it.
I'd suggest both - the float does nothing and instead of the margin-top, you can use line-height.

Upvotes: 1

aug
aug

Reputation: 11714

Pretty interesting. I think there are a couple of interesting regressions happening because you do margin-top: -1px and you also float a pseudo element inside the <li> which causes some interesting things with the document flow.

Removing one or the other makes it seem to work as expected.

You could also put a clear: both on the :before pseudo element which will specify to the browser that the floating elements shouldn't try to float on the same line. That also seems to help a little.

I actually think the heart of the issue lies with the fact that <li> by default comes with its own "margin-top" with the default style of -webkit-margin-before: 1em. It seems setting li to have a style of -webkit-margin-before: 0em also solves the issue. For more information of -webkit-margin-before, see this answer

In all honesty, I'm still looking into it so I'll try to update my answer if I can. One thing I am looking into is it could be the result of margin-collapsing but I don't have enough evidence to support it.

Specifically this excerpt might suggest a clue:

When negative margins are involved, the size of the collapsed margin is the sum of the largest positive margin and the smallest (most negative) negative margin.

If both are negative, the greater negative value is used. This definition applies to adjacent elements and nested elements.

Margins of floating and absolutely positioned elements never collapse.

Upvotes: 0

Milan Chheda
Milan Chheda

Reputation: 8249

That's happening because you are using float:left, you just need to remove this property and it will work perfectly fine. Below is the updated code:

li {
  margin-top: -1px;
}

li:before {
  content: "x";
}
<ul>
  <li>y</li>
  <li>y</li>
  <li>y</li>
</ul>

Upvotes: 0

Elisa L
Elisa L

Reputation: 322

You don't need the float: left or else it considers it as aligning to the left of the end of the previous object

Upvotes: 0

itacode
itacode

Reputation: 3787

Is there a reason for floating the pseudo element? If you remove or clear the float, it works

li { margin-top: -1px;  }
li:before { content: "x";  }
<ul>
    <li>y</li>
    <li>y</li>
    <li>y</li>
</ul>

Upvotes: 0

Related Questions