Search code examples
csscss-float

Why “clear: left” on a left float also affects right floats, and how to avoid it


Consider this HTML example (minimal example shown below):

<p><svg style="float: left" width="300" height="300"><circle cx="150" cy="150" r="150" style="fill: red"
/></svg>First float here.</p>
<p><svg style="float: left; clear: left" width="300" height="300"><circle cx="150" cy="150" r="150" style="fill: green"
/></svg>Second float here.</p>
<p><svg style="float: right" width="300" height="300"><circle cx="150" cy="150" r="150" style="fill: blue"
/></svg>Third float here.</p>

We have some text which embeds three floats:

  1. a left float (red circle),

  2. another left float (green circle), this one with clear: left to make sure it goes below the first float,

  3. a right float (blue circle).

The desired effect is for the right float to be completely independent of the left floats, i.e., the right float goes to the right of the place it was inserted (provided the line is long enough for both left and right floats to exist simultaneously, otherwise it goes below the left floats). The actual effect is that the right float is pushed below the first left float, because the clear: left directive on the second left float also pushes the right float down.

In short, clear: left on a left float also affects right floats.

Two questions:

  • Where in the CSS spec is this behavior specified? (The right float does not have any clear property set, so I don't understand what part of the spec implies that it is affected by the previous left float's clear.) I'm also interested in the underlying logic: why would we want right floats to be affected by clear: left properties on left floats?

  • And more importantly, how can I produce the desired effect (without any JavaScript)?


Solution

  • To answer your first question:
    The documentation specifies this:
    9.5.1 5.The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.
    This means the top of your Blue float can't be higher than the top of your Green float.

    To answer your second question:
    There are a few ways of achieving this without js by changing the html structure, but none I can think are exactly what you want. For example you could wrap the red and green floats inside the same container and make it float left. The blue float will be in the position you want. However, in very small screens the text won't wrap beteen the red and green floats like the are doing at they moment.