MillerMedia
MillerMedia

Reputation: 3671

Getting Certain Floating Elements to Stack Vertically (CSS)

I have a page of dynamically generated content (by jQuery) that I need to style in a certain way. I basically am drawing information from an outside source and arranging it in unordered lists on the page. Each list has a different amount of items in it and I'm trying to minimize the whitespace that's around the lists if some are significantly shorter than others.

In the Fiddle you will see a column with 6 elements, one with four and two with two. I want the ones with two to stack vertically one on top of the other so it'll essentially keep the same height as the rest of the elements on the page.

I've played around with float and clear but everything I try seems to just move the items down to the next line.

The HTML is:

<div id="columns">
<ul class="category_display" title="column1">
    <li><h3>Column 1</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
    <li>Test 3</li>
    <li>Test 4</li>
    <li>Test 5</li>
    <li>Test 6</li>
</ul>
<ul class="category_display" title="column2">
    <li><h3>Column 2</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
    <li>Test 3</li>
    <li>Test 4</li>
</ul>
<ul class="category_display" title="column3">
    <li><h3>Column 3</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
</ul>
<ul class="category_display" title="column4">
    <li><h3>Column 4</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
</ul>

And the CSS I'm using is:

#columns ul{
    list-style-type:none;
    margin:0px;
    float:left;
    width:175px;
    padding:5px 10px;
}

I've set it up on a Fiddle here.

http://jsfiddle.net/6c669/

I've assumed that there is a simple CSS rule that I can use to make it wrap a certain way if but can't seem to find it. I've seen 'columns' in CSS3 but hoping there is a more browser-friendly solution. Thanks for your help!

Upvotes: 1

Views: 105

Answers (4)

display-name-is-missing
display-name-is-missing

Reputation: 4409

This function whould do what you want:

HTML:

<div id="columns">
<ul class="category_display floating" title="column1">
    <li><h3>Column 1</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
    <li>Test 3</li>
    <li>Test 4</li>
    <li>Test 5</li>
    <li>Test 6</li>
</ul>
<ul class="category_display floating" title="column2">
    <li><h3>Column 2</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
    <li>Test 3</li>
    <li>Test 4</li>
</ul>
<ul class="category_display floating" title="column3">
    <li><h3>Column 3</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
</ul>
<ul class="category_display floating" title="column4">
    <li><h3>Column 4</h3></li>
    <li>Test 1</li>
    <li>Test 2</li>
</ul>

CSS:

#columns ul, .left {
    list-style-type:none;
    margin:0px;
    width:175px;
    padding:5px 10px;
}
.floating, .left {
    float:left;
}
.too_small {
    float:none;
}

JS:

var group_together = '';
var count_el = 0;

$("ul").each(function () {
    if ($(this).find('li').length == 3) {
        $(this).removeClass('floating').addClass('too_small');
        count_el++;
        if (count_el == 2) {
            count_el = 0;
            $(".too_small").wrapAll('<div class="left"></div>');
            $(".too_small").removeClass();
        }

    } else {
        $(".too_small").not('.floating').removeClass('too_small').addClass('floating');
    }
});

$(".too_small").wrapAll('<div class="left"></div>');

DEMO

Note

  • 2 in if (count_el == 2) { means that a maximum of 2 elements can stack on top of each other. Alter that if you like.

Upvotes: 1

user950658
user950658

Reputation:

you could use css-columns and make use of the column-break-before property (depending on browser-support)

http://jsfiddle.net/6c669/4/

just add the class break where you want to force a break

CSS

#columns ul {
    list-style-type:none;
    margin:0px;
    width:175px;
    padding:5px 10px;
}
#columns {
    -moz-column-count:3;
    -webkit-column-count:3;
    column-count:3;
}
.break {
        -moz-column-break-before: always;
        -webkit-column-break-before: always;
        column-break-before: always;
}

HTML

<div id="columns">
    <ul class="category_display" title="column1">
        <li>
            <h3>Column 1</h3>
        </li>
        <li>Test 1</li>
        <li>Test 2</li>
        <li>Test 3</li>
        <li>Test 4</li>
        <li>Test 5</li>
        <li>Test 6</li>
    </ul>
    <ul class="category_display" title="column2">
        <li>
            <h3>Column 2</h3>
        </li>
        <li>Test 1</li>
        <li>Test 2</li>
        <li>Test 3</li>
        <li>Test 4</li>
    </ul>
    <ul class="category_display break" title="column3">
        <li>
            <h3>Column 3</h3>
        </li>
        <li>Test 1</li>
        <li>Test 2</li>
    </ul>
    <ul class="category_display" title="column4">
        <li>
            <h3>Column 4</h3>
        </li>
        <li>Test 1</li>
        <li>Test 2</li>
    </ul>
</div>
<!--columns-->

Upvotes: 1

Henrik Ammer
Henrik Ammer

Reputation: 1899

If you're up for some more Javascript try out Masonry, http://masonry.desandro.com/. Or any other "brick" layout script.

You should be able to set it up using the following (based on your jsFiddle).

var msnry = new Masonry( $('#columns'), {
  columnWidth: 200,
  itemSelector: '.category_display'
});

Upvotes: 0

If you add another class to your 4th column and set a width to your #columns is one way to solve this:

The CSS:

#columns {
    width: 585px;
}

#columns ul.right {
    float: right;
}

The HTML:

<ul class="category_display right" title="column4">
    <li>
        <h3>
        Column 4
        </h3>
    </li>
    <li>Test 1</li>
    <li>Test 2</li>
</ul>

You can also see the updated fiddle:

http://jsfiddle.net/6c669/3/

Upvotes: 1

Related Questions