Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I break a single list into multiple columns semantically? [duplicate]

The current approach our site is using to break a single list into multiple columns is to use multiple uls:

<ul>
  <li>one</li>
  <li>two</li>
</ul>
<ul>
  <li>three</li>
  <li>four</li>
</ul>

This doesn't seem ideal to me, since semantically, it's not two lists, it's one. I've seen a lot of inadequate solutions for multi-columns lists. I'm looking for a solution that:

  1. Uses the following markup structure

    <ul>
      <li>one</li>
      <li>two</li>
      <li>three</li>
      <li>four</li>
    </ul>
    
  2. Organizes like this:

    one    three
    two    four
    

    Not this:

    one    two
    three  four
    
  3. Works without modification if list-length changes, or if items wrap multiple lines.

  4. Uses valid, semantic HTML.
  5. Works down to IE8.

The ideal solution is CSS only, but I'm open to using jQuery UI or light-weight Javascript.

(PS, here's my CSS attempt, with notable problems.)

Edit: This question is specific to semantic lists. The other supposedly "duplicate" question is regarding <div> elements, which is a different ballgame because additional markup is allowed. No additional markup is allowed between a <ul> and an <li>. This question is focused on semantics which means there is an emphasis on using HTML to indicate with as much detail as possible the meaning of the content.

like image 526
brentonstrine Avatar asked Aug 15 '13 20:08

brentonstrine


2 Answers

You could use columns for browsers that support it

DEMO http://jsfiddle.net/kevinPHPkevin/eaewX/33/

Here is a jQuery example for full browser support

DEMO http://jsfiddle.net/kevinPHPkevin/MKL4g/131/

var postsArr = new Array(),
    $postsList = $('ul.posts');

//Create array of all posts in lists
$postsList.find('li').each(function(){
    postsArr.push($(this).html());
})

//Split the array at this point. The original array is altered.
var firstList = postsArr.splice(0, Math.round(postsArr.length / 2)),
    secondList = postsArr,
    ListHTML = '';

function createHTML(list){
    ListHTML = '';
    for (var i = 0; i < list.length; i++) {
        ListHTML += '<li>' + list[i] + '</li>'
    };
}

//Generate HTML for first list
createHTML(firstList);
$postsList.html(ListHTML);

//Generate HTML for second list
createHTML(secondList);
//Create new list after original one
$postsList.after('<ul class="posts"></ul>').next().html(ListHTML);
like image 183
Kevin Lynch Avatar answered Sep 20 '22 07:09

Kevin Lynch


Sorry to answer my own question, but I think I got a CSS only solution.

Here it is on jsFiddle.

Basically, I use the general sibling selector (This symbol: ~, works in IE7 too!) to highlight all elements after the breakpoint, and move them over and up. As long as you set a line-height, seems to work cross browser down to IE7.

HTML:

<ul>
  <li>one</li>
  <li>two</li>
  <li class="newline">three</li>
  <li>four</li>
</ul>

CSS:

.newrow,
.newrow ~ li {
    margin-left: 120px;
    margin-top: -100px;
    margin-bottom: 100px;
}

Am I missing anything obvious here?

like image 22
brentonstrine Avatar answered Sep 20 '22 07:09

brentonstrine