Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Centering a variable width grid while aligning its elements to the left

Consider the following

<div class="container">
     <div class="grid">
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
          ....
      </div>
</div>

Using images, basically what I have is something like this

enter image description here

As you can see the green blocks and the container are aligned to the left

What I want to acheive is something like this.

enter image description here

The .unit elements have constant width

The .grid element should expand with width (so that more unit elements would fit into 1 line) while being always centered within .container.

Any clue how to achieve that using only CSS (and maybe some html wrappers if necessary) ?

like image 616
man Avatar asked Nov 11 '22 05:11

man


1 Answers

Let me begin by saying that this is an interesting question and my first thought was that flexbox is the way to solve this. I have tried all manner of flexbox arrangements, but this type of solution eluded me. So, below is the solution that uses floating, clearing, and media queries.

For this example, I have assumed that each row would have at least 3 and no more than 9 boxes. However, you can extend this solution to handle anywhere between 1 and more than 9 boxes.

Here's HTML:

<div class="grid">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

Here's a CSS that (1) performs a mini-reset to eliminate browser-applied paddings and margins that may interfere with sizing and (2) formats the .grid and its div children:

* {
    margin: 0;
    padding: 0;
}

.grid {
    display: table;
    outline: 1px solid blue;
    min-width: 330px;
    margin: 0 auto;
}

.grid > div {
    width: 100px;
    height: 61px;
    margin: 5px;
    background-color: teal;
    float: left;
}

The .container block was eliminated because .grid is displayed as a table. The latter is a block that shrinkwraps around its children and margin: 0 auto can be applied to center it on the page. The .grid's min-width of 330px assures that a minimum of three blocks can fit per line. Whenever floating happens within a table element, its margins do not collapse, therefore no explicit clearing of floats (e.g., via clearfix) is necessary.

Each .grid div child takes 110px of horizontal space (100px width + 10px in left and right margins). This number is important for the media queries code that follows below:

@media screen and (min-width: 330px) and (max-width: 439px) {
    .grid > div:nth-of-type(3n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 440px) and (max-width: 549px) {
    .grid > div:nth-of-type(4n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 550px) and (max-width: 659px) {
    .grid > div:nth-of-type(5n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 660px) and (max-width: 769px) {
    .grid > div:nth-of-type(6n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 770px) and (max-width: 879px) {
    .grid > div:nth-of-type(7n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 880px) and (max-width: 989px) {
    .grid > div:nth-of-type(8n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 990px) {
    .grid > div:nth-of-type(9n + 1) {
        clear: left;
    }    
}

The rationale behind the code is this: if there is enough space to include only n blocks per line, then every (n + 1)th block's left edge is cleared, which moves the block to a new line.

And, here's a fiddle: http://jsfiddle.net/5hWXw/. Resize the preview window to see the adjustments.

like image 134
DRD Avatar answered Nov 12 '22 19:11

DRD