4

Is there any way in CSS to create this:

-----------------------------------
| lorem ipsum dolor | consectetur |
| sit amet          |             |
-----------------------------------
| adipiscing        | elit        |
-----------------------------------

from this:

<ul>
  <li>lorem ipsum dolor sit amet</li>
  <li>consectetur</li>
  <li>adipiscing</li>
  <li>elit</li>
</ul>

(the order of the elements is not that important)

UPDATE

I need 'columns' to be as wide as their widest 'cell'; and I need 'rows' to be as tall as their tallest 'cell'; in short... a table! There are no 'table headers': all cells are on the same level, hierarchically.

UPDATE 2

Something like: every cell on the first virtual row (i.e. every cell before the line wraps) fills all the available space based on in its contents; the subsequent rows are formed by the same number of cells per row as the first. Every column is still as wide as its widest cell, without increasing the number of columns established by the first row.

Thinking some more about it, the thing up there would require more magic than the table layout module, and that's too magic to begin with!

A picture, to say a thousand words:

Table-like grid

(you can ignore the unordered lists inside the 'cells')

How would you implement it with just a simple HTML list. At this point, I guess the anwser is: you wouldn't; but let's see...

wc.matteo
  • 41
  • 4
  • 6
  • 2
    If it's tabular content, use a table. – Kyle Jun 01 '16 at 07:59
  • I would rather use dl, dt and dd instead of ul and li. – Salman A Jun 02 '16 at 13:35
  • @SalmanA The markup is just an example to make the point clear that I can't add any rows (i.e. non `li` elements) in there. Semantically, all elements should be cells, so it's seems to me only right that they share the same element type (`li`). – wc.matteo Jun 02 '16 at 13:44

3 Answers3

5

A simple way is to use floats on your li elements. Below you'll find an example which you can edit to meet your needs.

ul {
  width: 500px;
}
li {
  width: 50%;
  float: left;
  border: 1px solid #000;
  margin: 0;
  list-style-type: none;
  box-sizing: border-box;
}
li:nth-child(odd) {
  clear: left;
}
<ul>
  <li>lorem ipsum dolor</li>
  <li>sit amet</li>
  <li>foo</li>
  <li>bar</li>
</ul>
Paul
  • 8,974
  • 3
  • 28
  • 48
  • 1
    Thanks for the answer. Alas, it's not what I'm looking for: I need the columns to be only as wide as their contents; and not be of an arbitrary width (e.g. 50%). I'm updating my question to be more clear. – wc.matteo Jun 02 '16 at 08:26
  • 1
    This will not be possible with CSS alone since sibling elements don't know each others size. Therefore, you can't make the third `li` as wide as the first one using auto-sized width. See https://jsfiddle.net/dmxL4v6j/ for a demo how this would look like. – Paul Jun 02 '16 at 08:37
  • That was fast! :) Yes, that's what I thought; you need the physical rows to be there... I know there's a _grid_ css layout module, do you know if that includes something like this? – wc.matteo Jun 02 '16 at 08:53
  • Grids (even flexible ones) also depend on at least relative widths, so it will still not be possible to have the columns auto-sized. – Paul Jun 02 '16 at 09:58
  • An alternative would be to use some javascript, get all the odd `li`elements, find the one with the longest text and then set all odd `li` to that width. – Paul Jun 02 '16 at 09:59
  • See **update 2** on the question. I suppose I'd need a custom layout engine in js then, and that's out of the question for the moment. – wc.matteo Jun 02 '16 at 12:44
2

Simple with flexbox:

  • Allow flex items to wrap
  • Give each item a 50% width, forcing two per row

ul {
    display: flex;              /* establish flex container */
    flex-wrap: wrap;            /* enable flex items to wrap */
    padding: 0;                 /* remove default padding */
    list-style-type: none;      
}

li {
    flex: 0 0 50%;              /* don't grow, don't shrink, fixed width of 50% */
}

/* non-essential decorative styles */
li              { text-align: center;           }
li:nth-child(1) { background-color: lightgreen; }
li:nth-child(2) { background-color: lightblue;  }
li:nth-child(3) { background-color: lightpink;  }
li:nth-child(4) { background-color: lightgray;  }
<ul>
  <li>lorem ipsum dolor</li>
  <li>sit amet</li>
  <li>foo</li>
  <li>bar</li>
</ul>

Benefits of flexbox:

  1. minimal code; very efficient
  2. centering, both vertically and horizontally, is simple and easy
  3. equal height columns are simple and easy
  4. multiple options for aligning flex elements
  5. it's responsive
  6. unlike floats and tables, which offer limited layout capacity because they were never intended for building layouts, flexbox is a modern (CSS3) technique with a broad range of options.

To learn more about flexbox visit:


Browser support:

Flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add all the prefixes you need, use Autoprefixer. More details in this answer.

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Thanks for the answer. I know about flexbox, and I tried many of its combinations but I wasn't able to achieve what I'm looking for. I'm updating my question to be more clear. – wc.matteo Jun 02 '16 at 08:26
  • As a curiosity: I read about it, but in _your_ opinion, what would you say is the main advantange of using `flex-basis` instead of `width`? The fact that works only on the _main axis_? – wc.matteo Jun 02 '16 at 09:14
  • When you say you *read about it*, you mean you already read my answer here? http://stackoverflow.com/q/34352140/3597276 – Michael Benjamin Jun 02 '16 at 10:55
  • I'm pretty new around here as you've noticed... do you think I should upvote answers that are well constructed and generally useful but that do NOT resolve my question? – wc.matteo Jun 02 '16 at 13:04
  • 1
    My general rule is to always upvote answers that are useful to me in some way. I'm constantly upvoting answers that teach me something new. However, I *wouldn't accept* (checkmark) an answer unless it fully answers my question. – Michael Benjamin Jun 02 '16 at 13:09
  • 1
    Then I'm upvoting your answer because it certainly is usefull and well made! ;) – wc.matteo Jun 02 '16 at 13:12
  • 1
    For other views on voting see [**here**](http://meta.stackexchange.com/q/13390/300177) and [**here**](http://meta.stackexchange.com/q/139/300177). – Michael Benjamin Jun 02 '16 at 13:16
0

You can float li next to each other, here is the solution

ul {
  margin:0; 
  padding:0;
  list-style-type: none;
  box-sizing: border-box;
}
li {
  width: 49%;
  float: left;
  border: 1px solid #000;
}
<ul>
  <li>lorem ipsum dolor</li>
  <li>sit amet</li>
  <li>foo</li>
  <li>bar</li>
  <li>lorem ipsum dolor</li>
  <li>sit amet</li>
  <li>foo</li>
  <li>bar</li>
</ul>
Shahil M
  • 3,836
  • 4
  • 25
  • 44