tika tika - 6 months ago 11
CSS Question

CSS Float Left to Line Up

(JSFIddle) Using

float : left
, we can achieve this:
enter image description here

<ul>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li class="half">&nbsp;</li>
<li class="half">&nbsp;</li>
<li class="half">&nbsp;</li>
<li class="half">&nbsp;</li>
</ul>


And CSS:

li{
width:100px;
height:100px;
background:#eee;
display:inline-block !important;
border:1px solid #ccc;
}
li.half{
width:50px; height:50px
}


But, how can we achieve this? (By staying in this HTML markup - that's why HTML is not tagged!!)

enter image description here

I notice that in the first case, the second line of small images is a new line. But, any ways to go through this?

Answer

You could achieve what you're looking for, no matter where the 4 smaller items appear in your list nor how many groups of them you have and without the need for any additional markup by using adjacent sibling selectors and a bit of trickery involving margins.

UPDATE: Added the ability to have a group of 3 small items

Here's a very quick proof of concept for you, with the last 4 rules being the most important to what we're doing here. The only caveat with the below, as it stands, is that you can't have a group of small items immediately following another group of small items.

ul{
    font-size:0;
    list-style:none;
    margin:0;
    padding:0;
    width:550px;
}
li{
    background:red;
    height:100px;
    display:inline-block;
    margin:0 10px 10px 0;
    vertical-align:top;
    width:100px;
}
li.small{
    background:green;
    height:45px;
    width:45px;
}
li.small+li.small+li.small{
    margin:55px 10px 10px -110px;
}
li.small+li.small+li.small+li:not(.small){
    margin-left:55px;
}
li.small+li.small+li.small+li.small{
    margin:55px 10px 10px 0;
}
li.small+li.small+li.small+li.small+li:not(.small){
    margin-left:0;
}
<ul>
    <li></li>
    <li class="small"></li>
    <li class="small"></li>
    <li class="small"></li>
    <li class="small"></li>
    <li></li>
    <li class="small"></li>
    <li class="small"></li>
    <li class="small"></li>
    <li></li>
    <li></li>
    <li></li>
    <li class="small"></li>
    <li class="small"></li>
    <li class="small"></li>
    <li class="small"></li>
    <li></li>
    <li></li>
</ul>

To explain what's going on above in those last 4 rules:

  1. Select every item of class small that is immediately preceded by at least two other items of class small. Move them down, using a top margin by the height of one small item plus the margin size - 45+10=55px. Move them to the right, using a negative left margin by the width of 2 small items plus double the margin size - 2*(45+10)=110px.

  2. To "reset" the margins when a group only has 3 small items, we introduce the negation pseudo class to select every item that is preceded by at least three items of class small but does not itself have the small class. Using margin-left, we move that left by the width of one small item plus the margin size - 45+10=55px.

  3. Next, we need to override the margins for every fourth item of class small. Were we not to do so, the layout would be completely messed up as each fourth item also matches the first selector. For this one, we just need to move it down again by the height of one small item plus the margin size so, as in step 1, we set the top margin to 55px. No need to set the left margin here as, by using a negative margin on the preceding item, this one shifts to the right with it.

  4. And, finally, we need to remove the margin-left from every item that is not .small and is preceded by at least four items that are.

Comments