CSS Floats and Its Stack Order

CSS Float Left and Right with Any Order HTML Elements and No Gaps

I've got a solution that involves absolute positioning. According to W3.org, there's something called toggle() in the works.

For now, we're stuck with this mess:

<html>
<body>

<style>

.lefties, .righties{
top: 10px;
width: 40%;
height: 100px;
position: absolute;
}

.lefties {
background: #DEF;
left: 10px;
}

.righties {
background-color: #FED;
right: 10px;
}

.lefties ~ .lefties,
.righties ~ .righties{
transform: translate(0px, 100px);
}

.lefties ~ .lefties ~ .lefties,
.righties ~ .righties ~ .righties{
transform: translate(0px, 200px);
}

.lefties ~ .lefties ~ .lefties ~ .lefties,
.righties ~ .righties ~ .righties ~ .righties{
transform: translate(0px, 300px);
}

.lefties ~ .lefties ~ .lefties ~ .lefties ~ .lefties,
.righties ~ .righties ~ .righties ~ .righties ~ .righties{
transform: translate(0px, 400px);
}

.lefties ~ .lefties ~ .lefties ~ .lefties ~ .lefties ~ .lefties,
.righties ~ .righties ~ .righties ~ .righties ~ .righties ~ .righties{
transform: translate(0px, 500px);
}
</style>

<div id="container">
<div class="lefties" >Test 1</div>
<div class="righties">Test 2</div>
<div class="lefties" >Test 3</div>
<div class="righties">Test 4</div>
<div class="lefties" >Test 5</div>
<div class="lefties" >Test 6</div>
<div class="lefties" >Test 7</div>
<div class="righties">Test 8</div>
<div class="righties">Test 9</div>
<div class="righties">Test 10</div>
<div class="lefties" >Test 11</div>
<div class="righties">Test 12</div>
</div>

</body>
</html>

But with toggle(), it looks like we could clean the .lefties ~ .lefties ~ .lefties ~ ... up to look like this:

.lefties ~ .lefties,
.righties ~ .righties{
transform: translate(0px, toggle(100px,200px,300px,400px,...));
}

Float left vs float right - why does the order change?

If they are both left, the image is pushed left first then the text is pushed left like you said. This is the same for the right. The image is pushed all the way to the right, and then the text is pushed to the right, basically bumping into the image.

The first item gets pushed in it's respective direction first, then the second item follows. You are basically just reversing the direction when you change the float to right. They move individually in the direction of the float in the order that they are laid out in the CSS but do not pass each other.

Change order of floated divs with CSS

I know that you're asking how to accomplish this utilising floats, but as far as I know using pure CSS this is impossible (at least without using nasty positioning, which you've said you don't want to do).

As far as I know the only nice way to accomplish this with pure HTML/CSS is to utilise the new flexbox spec (a good starting point would probably be this css tricks article).

When you use flexbox you can use the order property on items to dictate which order items appear in (duh)

You can see an example of this in action here, the HTML code is similar to what you have, with an added wrapper element (I also fixed the DOCTYPE declaration):

<!DOCTYPE html>
<div class="wrapper">
<div class="yellow">
</div>
<div class="red">
</div>
</div>

The CSS is a little different:

.wrapper {
display: flex;
flex-flow: row wrap;
}

.yellow {
background: yellow;
width: 20%;
height: 300px;
}

.red {
background: red;
width: 20%;
height: 300px;
}

@media screen and (max-width:600px) {
.yellow {
order: 2;
width: 100%;
}

.red {
order: 1;
width: 100%;
}
}

I've also cleaned it up a little, you had duplicate code in your media query which didn't really need to be there.

The only downside to this is that it currently only works on around 80% of browsers as of writing:

http://caniuse.com/#search=flexbox

Depending on your target market that might be OK, you could use graceful degradation so that it appears correctly in all ways except the ordering on devices that don't support flexbox fully.

I guess you're also only really targeting mobile devices with reordering things, support there is good so it might work well for you.

floats and Stacking Context

For the second question if we check the painting order we will have this order:


  1. For all its in-flow, non-positioned, block-level descendants in tree order:
  2. If the element is a block, list-item, or other block equivalent: background color of element.

So now we have painted the background color of the block element .new


  1. All non-positioned floating descendants, in tree order. For each one of these, treat the element as if it created a new stacking
    context, but any positioned descendants and descendants which actually
    create a new stacking context are considered part of the parent
    stacking context, not this new one.

So now we have painted all the element .float (background and content) because it creates it own stacking context. So we should paint everything inside it considering the painting order rules then we move to the next elements.


  1. Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:
    1. ...

At this step we will paint the content of the .new element and the inline element .old


So the trick is that the .new element is painted in two different steps, first it's background and later it's content. Between these steps we painted the floated element.

How to change the order floated elements?

Using display: inline on <li>'s can cause problems, especially if you're eventually going for dropdown menus. I'd recommend something similar to this (only floats show, you know what other styles you want to add):

#extMenu { float: right; }
#extMenu li { float: left; }

So the menu itself will float to the right, while the menu items will float to the left.

Another solution would be to simply reverse the order of your <li>'s

HTML float right element order

That 'inverted order' is the intended result.

You can dig around in the CSS Specification if you'd like, but your example renders as it ought to.

If you'd like them to display in the same order as the markup, float the .container right, its children left.

Updated jsfiddle

How to float two elements to the right maintaining the same order visually and semantically?

The common fixes are:

Adding auxiliary element

<style>
.container { width: 200px; height: 50px; background: #333; }
.container p { width: 50px; height: 50px; background: #f00; float: left; margin: 0; }
.container .aux { float: right; }
</style>
<div class="container">
<div class="aux">
<p class="a">Simon</p>
<p class="b">Says</p>
</div>
</div>

http://jsbin.com/eravan/6/edit

The problem with this approach is the redundant auxiliary element itself.

Messing with the semantics

<style>
.container { width: 200px; height: 50px; background: #333; }
.container p { width: 50px; height: 50px; background: #f00; float: right; margin: 0; }
</style>
<div class="container">
<p class="b">Says</p>
<p class="a">Simon</p>
</div>

http://jsbin.com/eravan/9/edit

This is the worst solution and, unfortunately, the most common as well (Ali Bassam comment directly below proves it).

Neither of these is the correct answer.

Unexplained stacking of CSS float and position:relative

When dealing with stacking order, I recommend perusing the following list from section 9.9 of CSS2:

Within each stacking context, the following layers are painted in back-to-front order:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

First off, there are two things you need to remember:

  1. z-index has no effect on non-positioned elements. This includes floats. This is why setting z-index on your float, without positioning it, is not going to change anything.
  2. From my answer to a very similar question: "Floats do not establish stacking contexts on their own. They will only do so if they are positioned and have a z-index that is not auto (not counting any of the numerous other ways an element may do so)."

These two points cover why the float never appears in front of its positioned sibling in scenarios 2 and 3: the positioned sibling has stack level 0 (#6), which ensures that it's painted in front of the float (#4).

In scenario 1, the non-positioned sibling falls under #3, which is why it's painted behind the float (#4).

In scenario 4, floating becomes irrelevant altogether. You now have two positioned elements in the same stacking context, one with a greater stack level than the other (and, as implied elsewhere, greater by a completely unnecessary amount), so the one with the greater stack level is painted over the one with the smaller stack level.

CSS floats, change order on mobile layout?

Here's how I would do it. The DIVs are floated on your desktop version, but displayed on top of eachother (default block display) on mobile.

CSS:

#sidebar {
float: left;
width: 30%;
}

#content {
float: right;
width: 70%;
}

.mobile #sidebar,
.mobile #content {
float: none;
display: block;
margin-bottom: 15px;
}

Standard HTML:

<body>
<div id="content">
...
</div>
<div id="sidebar">
...
</div>
</body>

Mobile HTML:

<body class="mobile">
<div id="content">
...
</div>
<div id="sidebar">
...
</div>
</body>


Related Topics



Leave a reply



Submit