Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Left aligned last row in centered grid of elements

I have a bunch of same-size blocks set to display:inline-block inside a div that has text-align:center set to align the blocks.

|        _____   _____   _____   _____       | |       |     | |     | |     | |     |      | |       |  1  | |  2  | |  3  | |  4  |      | |       |_____| |_____| |_____| |_____|      | |        _____   _____   _____   _____       | |       |     | |     | |     | |     |      | |       |  5  | |  6  | |  7  | |  8  |      | |       |_____| |_____| |_____| |_____|      | |                                            | 

The blocks fill the div horizontally, and as the browser window shrinks, some blocks break to new lines, creating more rows and less columns. I want everything to still remain centered, with the last row aligned flush to the left, like this :

|        _____   _____   _____        | |       |     | |     | |     |       | |       |  1  | |  2  | |  3  |       | |       |_____| |_____| |_____|       | |        _____   _____   _____        | |       |     | |     | |     |       | |       |  4  | |  5  | |  6  |       | |       |_____| |_____| |_____|       | |        _____   _____                | |       |     | |     |               | |       |  7  | |  8  |               | |       |_____| |_____|               | |                                     | 

What currently happens is this:

|        _____   _____   _____        | |       |     | |     | |     |       | |       |  1  | |  2  | |  3  |       | |       |_____| |_____| |_____|       | |        _____   _____   _____        | |       |     | |     | |     |       | |       |  4  | |  5  | |  6  |       | |       |_____| |_____| |_____|       | |            _____   _____            | |           |     | |     |           | |           |  7  | |  8  |           | |           |_____| |_____|           | |                                     | 

I cannot add extra filler divs like one suggestion, because there could be any number of blocks, and the amount of rows and columns will vary depending on browser width. I also cannot style block #7 directly, for the same reason. The blocks must always remain centered no matter how many columns.

Here is a pen to better demonstrate:

http://codepen.io/anon/pen/IDsxn

Is this possible? I feel like it sure should be. I would prefer not to use flexbox as it is only ie10+, and I'd like ie9+. I would really like a pure CSS solution, but if you tell me JS is the only way, I'd love to see that in action.

For reference - similar questions, though none were thoroughly explained:

How to align left last row/line in multiple line flexbox

CSS - Left align the last row of images in a centered div

Fix centering last line of elements in fluid container grid to be left aligned while container stays centered

Center multiple inline blocks with CSS and align the last row to the left

like image 668
Ivan Durst Avatar asked Oct 22 '13 19:10

Ivan Durst


People also ask

How do you center the last row in the grid?

As an alternative, use flexbox with justify-content: center . This packs all items in the horizontal center of the row. Then your margins push them apart. On fully-filled rows, justify-content will have no effect since there's no free space for it to work.

How do I align my last flex to the left?

The simplest way to do this is with a grid instead of flex and grid template columns with repeat and auto fills , where you have to set the number of pixels that you have given to each element, 100px from your snippet code. This is the proper solution to get last row items left aligned.

How do you center items in flex grid?

We make the container a Flexbox by setting display: flex . Next, we set the align-items property to the center value, which aligns each div item in the center.

How do I center align grid?

To align the item horizontally within the grid, we use the justify-content property and set it to center . With justify-content we can align the columns start , end , stretch or center .


2 Answers

Solution with display inline-block

This adaptive grid is much simpler : less markup and less CSS so it will be easier to implement in a production site and adapt to your exact needs.

=>> DEMO <<= (resize the result window to see the effect)

html, body {      margin:0;      padding:0;  }  #container{      font-size:0;      margin:0 auto;      width:1000px;  }  .block {      font-size:20px;      width: 150px;      height: 150px;      margin:25px;      background: gold;      display:inline-block;  }    @media screen and (max-width: 430px) {      #container{          width:200px;      }  }    @media screen and (min-width: 431px) and (max-width: 630px) {     #container{          width:400px;      }  }  @media screen and (min-width: 631px) and (max-width: 830px) {     #container{          width:600px;      }  }  @media screen and (min-width: 831px) and (max-width: 1030px) {     #container{          width:800px;      }  }
<div id="container">      <div class="block">1</div>      <div class="block">2</div>      <div class="block">3</div>      <div class="block">4</div>      <div class="block">5</div>      <div class="block">6</div>      <div class="block">7</div>      <div class="block">8</div>      <div class="block">9</div>      <div class="block">10</div>      <div class="block">11</div>      <div class="block">12</div>      <div class="block">13</div>  </div>

It involves :

  1. 4 media queries for 200px wide blocks and a container expandable to 1000px. Depending on the width of your grid elements and the total width of your container you may have to make less or more

  2. removing white-spaces between inline-block elements (in the following demo I used the font-size technique but you can use other ones (see How to remove the space between inline-block elements? for other techniques)

  3. fixed margins between blocks

The number of blocks in one line adapts to the size of the container. The text-align property stay to default value left so the last items are aligned to the left.


Floats with adaptive margins between both blocks and container

=>> DEMO <<= (you need to resize the result window under 750px to see it in action)

html, body {      margin:0;      padding:0;      min-width:150px;  }  .wrap {      float:left;      position:relative;  }  .foto {      width: 150px;      height: 150px;      background: gold;      position:absolute;  }    #warning{display:none;}  @media screen and (min-width: 631px) {      .wrap {          width:20%;          padding-bottom:25%;      }      .wrap:nth-child(4n+2), .wrap:nth-child(4n+3){                }      .wrap .foto {          top:-75px;          margin-top:100%;          right:-30px;      }      .wrap:nth-child(4n+2){          margin:0 5% 0 7.5%;      }      .wrap:nth-child(4n+3){       margin-right:7.5%;      }      .wrap:nth-child(4n+2) .foto{          left:50%;          margin-left:-75px;      }      .wrap:nth-child(4n+3) .foto{          right:50%;          margin-right:-75px;      }      .wrap:nth-child(4n) .foto{          left:-30px;      }         #container{          margin-top:-45px;      }  }    @media screen and (min-width: 481px) and (max-width: 631px) {      .wrap {          width:25%;          padding-bottom:33.3%;      }      .wrap:nth-child(3n+2){          margin:0 12.5%;              }      .wrap .foto {          top:-75px;          margin-top:100%;          right:-37px;      }       .wrap:nth-child(3n+2) .foto{          left:50%;          margin-left:-75px;      }       .wrap:nth-child(3n) .foto{          left:-37px;      }      #container{          margin-top:-37px;      }  }      @media screen and (min-width: 331px) and (max-width: 480px) {      .wrap {          width:33.3%;          padding-bottom:50%;          clear:left;      }      .wrap:nth-child(even) {          float:right;          clear:right;      }      .wrap .foto {          top:-75px;          margin-top:100%;          right:-50px;      }      .wrap:nth-child(even) .foto {          left:-50px;      }      .wrap:nth-child(4n+3) .foto, .wrap:nth-child(4n+4) .foto {          bottom:-75px;          margin-bottom:100%;      }      #container{          margin-top:-25px;      }  }      @media screen and (max-width: 330px) {      .wrap {          width:50%;          padding-bottom:100%;          clear:left;      }      .wrap:nth-child(odd) .foto {          right:-75px;          bottom:0;          bottom:-75px;          margin-bottom:100%;      }      .wrap:nth-child(even) .foto {          top:0px;          right:-75px;          top:-75px;          margin-top:100%;      }  }    @media screen and (min-width: 751px) {      #warning{          color:#fff;          display:block;          position:fixed;          width:100%;          height:50%;          top:25%;          left:0;          background:#000;          text-align:center;          font-size:30px;  }
<div id="container">      <div class="wrap"><div class="foto">1</div></div>      <div class="wrap"><div class="foto">2</div></div>      <div class="wrap"><div class="foto">3</div></div>      <div class="wrap"><div class="foto">4</div></div>      <div class="wrap"><div class="foto">5</div></div>      <div class="wrap"><div class="foto">6</div></div>      <div class="wrap"><div class="foto">7</div></div>      <div class="wrap"><div class="foto">8</div></div>      <div class="wrap"><div class="foto">9</div></div>      <div class="wrap"><div class="foto">10</div></div>      <div class="wrap"><div class="foto">11</div></div>      <div class="wrap"><div class="foto">12</div></div>      <div class="wrap"><div class="foto">13</div></div>      <div class="wrap"><div class="foto">14</div></div>      <div class="wrap"><div class="foto">15</div></div>  </div>    <!-- FOLLOWING JUST FOR THE DEMO -->  <div id="warning">I haven't written the code for windows bigger than 751px.<br/>      You must resize this window under 751px.</div>

This technique involves :

  1. floats
  2. position:absolute;
  3. :nt-child() css selector
  4. media queries

It centers the blocks in their container and gives the same margin on the top/left/tight/bottom of all the blocks + sides of the container. As this solution uses floats, the last row is aligned to the left.

The number of blocks in one line adapts to the width of the window.

like image 130
web-tiki Avatar answered Sep 21 '22 09:09

web-tiki


Here's a very simple JavaScript (and some small changes in your CSS) solution for you:

http://jsfiddle.net/ha68t/

It's working fine for me.

CSS:

.container {   margin: 0 auto;   max-width:960px;   background-color: gold; }  .block {   background-color: #ddd;   border:1px solid #999;   display: block;   float: left;   height: 100px;   margin: 4px 2px;   width: 100px; } 

JavaScript:

$(document).ready(function(){     setContainerWidth(); });  $(window).resize(function(){    setContainerWidth(); });  function setContainerWidth() {     $('.container').css('width', 'auto'); //reset     var windowWidth = $(document).width();     var blockWidth = $('.block').outerWidth(true);     var maxBoxPerRow = Math.floor(windowWidth / blockWidth);     $('.container').width(maxBoxPerRow * blockWidth); } 

jQuery is required :)

like image 45
mahega Avatar answered Sep 22 '22 09:09

mahega