7

I have a list of content items, each with a set width but different (variable) heights. Each item in the list will be floated left. The HTML and CSS are as follows:

<style type="text/css">
  li{
    float: left;
    width: 200px;
  }
  li img{
  float: right;
  }
</style>

<ul>
  <li><h3>Item One</h3>
      <img src="one.png">
      <p>First item content here</p>
  </li>
  <li><h3>Item Two</h3>
      <img src="two.png">
      <p>Second item content here</p>
  </li>
  <li><h3>Item Three</h3>
      <img src="three.png">
      <p>Third item content here</p>
  </li>
  <li><h3>Item Four</h3>
      <img src="four.png">
      <p>Fourth item content here</p>
  </li>
  <li><h3>Item Five</h3>
      <img src="five.png">
      <p>Fifth item content here</p>
  </li>
</ul>
</style>

The problem I have has to do with the way the items float left if there is enough space in a row for 3 items and the second item is taller than then fourth item. The fourth item won't start a new row but will instead place to the right of the second item like this:

enter image description here

What I want is for the list-items to form a sort of table-like structure that will align each row nicely after the previous row at a height equal to the tallest item of the previous row. Instead of what I have above, I want it to look like this:

enter image description here

I would also like to be able to scale the width of the containing div such that the items-per-row adjust as necessary. For example, if a containing div is made wider (ie. if the user re-sizes the window) the number of items per row increases to fill the space. Here is an example of the related problem on a wider container:

enter image description here

And here is what I want it to do:

enter image description here

Based on a previous question, I don't think there is an easy solution to this so I want to use jQuery to get it done.

What I'm thinking is using jQuery to do something like:

Step 1. Set the width of each element to elementWidth

var elementWidth = 200; // 200px

Step 2. Set a variable containerWidth to the width of the overall container

var containerWidth = $('#container').width();

Step 3. Divide the containerWidth by the elementWidth to determine the number of elements per row

var elementsPerRow = containerWidth / elementWidth;

Step 4. Add the property clear:left; each elementsPerRow-ith list item

for(x = 0, x < (total number of all elements), x + elementsPerRow){
  // set clear:left to this <li>
}

I'm not very good (a complete beginner) with JavaScript and jQuery. Can someone please help me put this together into a nice piece of code I can copy and paste (and learn from).

2
  • Are you looking for something like jQuery Masonry? Commented Dec 20, 2011 at 18:53
  • Thanks for the reply. I was looking at jQuery Masonry but I wasn't able to get it to work exactly how I want. Masonry seems to put the items together more tightly than I want. I want each row to be separate and to maintain the space between rows (like in my second diagram where there is space between one and four). Commented Dec 20, 2011 at 19:05

1 Answer 1

6

The problem is that you're trying to use float: left when you should be using display: inline-block. There's no need for using javascript either.

li { 
    vertical-align: top;
    display: inline-block; }

See: http://jsfiddle.net/Wexcode/zgNkA/

Sign up to request clarification or add additional context in comments.

4 Comments

just be careful if the audience can use older browsers like IE7, it might not render properly
Thank you for the great answer. It works! I'm curious, do you have any suggestions for IE7? According to my searches it has "partial support" for inline-block but I haven't tested it yet.
I haven't personally run into this problem, but it looks like this article might be able to help you.
@Wex Would you mind adding: zoom: 1; *display: inline; to the properties? These are absolutely necessary for IE7 to support inline-block from my testing. (The asterisk before "display" is not a typo.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.