Achieving dynamic columns in CSS3

Problem

I hope you can help! Here are the parameters:

  • One parent container with dynamic width and height
  • Variable number of children
  • Parent's height is set with JS, dependent on the window size
  • As parent's height collapses, its width must expand according to children
  • Children must fill the container vertically first and horizontally second
  • Children must be direct descendants of the parent—there can be no nesting boxes or additional structure for rows and columns
  • Children have a uniform size
  • Children must be relatively positioned and their position cannot be calculated in JS
  • JS only allowed to set parent's height / width

HTML

<ol>
 <li>1</li>
 <li>2</li>
 <li>3</li>
 <li>4</li>
 <li>5</li>
 <li>6</li>
 <li>7</li>
 <li>8</li>
 <li>9</li>
</ol>

BOX MODEL

[-------------]
[-[1]-[4]-[7]-]
[-[2]-[5]-[8]-]
[-[3]-[6]-[9]-]
[-------------]

BOX MODEL AFTER HEIGHT SHRINKS

[---------------------]
[-[1]-[3]-[5]-[7]-[9]-]
[-[2]-[4]-[6]-[8]-----]
[---------------------]

Is this possible with CSS/CSS3 box models?

Thanks!!

Problem courtesy of: stupiddummy1989

Solution

multi-column is notoriously inconsistently implemented, although it sounds like the easiest and most standard way to implement that:

http://jsfiddle.net/383uF/1/

I should note that any strange discrepancies between implementations in your case can be very much mitigated since you can control the dimensions of the container, so you can round to the nearest x pixels or whatever, to make sure there is less jumpiness and rerendering.

Solution courtesy of: davin

Discussion

I would say to use display: inline-block but they would only collapse to new lines if there was a set width on the parent. Your parameters say that JS can set the width of the parent, so if you're willing to calculate how wide the box will need to be in order to collapse the lines correctly, then you could use this method.

Basically, each child would be set to inline-block with their set width/height and then you could add a margin-right to each one to space them apart from each other, then add a margin-left to the parent so that the left also has the appropriate amount of spacing. Then based on the height of the parent, calculate how many rows of children the parent can have in order to calculate how wide you need the parent to be for the children to collapse correctly (keep in mind that you should not include the margin-left of the parent in the width). It would all be basic CSS, no CSS3 required.

Discussion courtesy of: animuson

I do not believe it is possible to fill vertically-then-horizontally without the use of CSS3 columns; however, I do not know of a way to get the shrink-to-fit behavior from columns.

This does everything you want when in WebKit (it spills over the bottom in Gecko) except for shrink-to-fit and that it may break in the middle of an li.

<!DOCTYPE html>
<html><head>
  <title>untitled</title>
  <style type="text/css" media="screen">
    html, body { height: 100%; }
    ol {
      margin: 0;
      padding: 0;
      border: 1px solid blue;
      height: 50%;
      -webkit-column-width: 10em;
      -webkit-column-fill: auto;
    }
     li {
       -webkit-break-inside: avoid;
       position: relative;
       margin: 0;
       padding: 0;
       width: 10em;
       height: 7em;
       display: block;
       border: 1px solid red;
     }
  </style>
</head><body>
  <ol>
   <li>1</li>
   <li>2</li>
   <li>3</li>
   <li>4</li>
   <li>5</li>
   <li>6</li>
   <li>7</li>
   <li>8</li>
   <li>9</li>
  </ol>
</body></html>
Discussion courtesy of: Kevin Reid

This recipe can be found in it's original form on Stack Over Flow.