1

Considering a grid that contains fixed size items (not my choice), and is not fixed size.

I would like to centralize the container (.grid-container) to have same side margin no matter how many items it have and how they are placed inside container as long as they are left-aligned.

If it isn't possible to do this only with CSS how can I do using JavaScript?

It's not necessary to use twitter-bootstrap grid system like the demo code.

enter image description here

Here a code to illustrate: https://embed.plnkr.co/F6niiwaosnO8tr0ss4XF/

.container {
  background-color: #2B3643;
}

.grid-container {
  padding: 30px 30px 0 30px;
}

.grid-item-wrapper {
  width: 200px;
  margin-bottom: 15px;
}

.grid-item {
  margin-bottom: 15px;
}

.grid-item > .item-desc {
  padding: 8px;
  background-color: #333333;
  color: #CFCFCF;
} 

  

    
  <div class="container">
    <div class="grid-container row">
      <!-- grid items -->
    </div>
  </div>
  <template id="tmpl_grid_item">
    <div class="grid-item-wrapper col-xs-3">
      <div class="grid-item">
        <div class="item-picture">
          <img src="http://lorempixel.com/350/200/food/" style="width: 100%;" />
        </div>
        <div class="item-desc">
          Lorem Ipsum
        </div>
      </div>
    </div>
  </template>
m.rufca
  • 2,558
  • 2
  • 19
  • 26
  • 2
    Just use `float: left;` and give the items a margin. – jperezov Jan 27 '16 at 21:47
  • So do you want the distance between the margin arrows on the left to be equal to the distance as the margin arrows on the right? And would you want the second row to have the items offset into the middle? Trying to understand exactly what you're asking. – Jhecht Jan 27 '16 at 21:48
  • @Jhecht yes, sorry by my bad english. I want the margin arrow to have same size. I could achieve this setting grid to be `text-align: center;` but if i do this the last row will be not aligned left – m.rufca Jan 27 '16 at 21:51
  • @jperezov items are already floating left, and they have padding instead margin. The exemple code is using bootstrap grid system (col-xs) – m.rufca Jan 27 '16 at 21:53
  • You need to just center the outer container then. You can give it a fixed width and center it with `margin: 0 auto;` (and use @media for different screen widths). Alternatively, you can position it absolutely and do `left: 10%; right: 10%;` (or whatever % or pixels you want). – jperezov Jan 27 '16 at 21:57
  • @jperezov the grid is not and may not be fixed sized. As I said it's not my choice to have fixed size itens with variable widh container. My question is how center the container using only CSS. – m.rufca Jan 27 '16 at 22:00
  • @jperezov Doesn't work https://plnkr.co/edit/sehslio1Ra9SqFBvZTHO?p=preview – m.rufca Jan 27 '16 at 22:09
  • What do you mean by *center the container*? That's simple (`margin:auto`)...but if you mean that the left/right margins of the top row should be equal...that's not possible with basic CSS...it's not the way inline-boxes work. - http://stackoverflow.com/questions/34995740/css-when-inline-block-elements-line-break-parent-wrapper-does-not-fit-new-width – Paulie_D Jan 27 '16 at 22:23
  • @matheusrufca ...that link and the one in your question are both showing the behavior you're asking for. – TylerH Jan 27 '16 at 22:23
  • @Paulie_D `margin: auto` is only possible when the element width is defined. – m.rufca Jan 27 '16 at 22:30
  • or `max-width`..but that's not the point here. Getting the *container* centered is easy and there are multiple options for that. **Shrink wrapping** the container so that the inner elements margins are equal is not a basic CSS layout option. Its usually something left to JS. – Paulie_D Jan 27 '16 at 22:33
  • @TylerH I updated the question and the image. The container is not centered. – m.rufca Jan 27 '16 at 22:35
  • Related - http://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid?rq=1 – Paulie_D Jan 27 '16 at 22:44

2 Answers2

1

If you are willing to use absolute positioning and CSS3, there is a way.

HTML:

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

CSS:

 .grid{
    position: absolute;
    width: auto;
    left: 50%;
    -ms-transform: translateX(-50%); /* IE 9 */
    -webkit-transform: translateX(-50%); /* Safari */
    transform: translateX(-50%);
 }

.item{
    width: 50px;
    height: 50px;
    background: #fff;
    float: left;
    margin: 20px;
}

Here is a working fiddle. Hope it helps!

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • Classic hack using absolute positioning. I think thats it or JS. It works, thanks. – m.rufca Jan 27 '16 at 22:44
  • Except that this does not solve the top row spacing issue. – Paulie_D Jan 27 '16 at 22:46
  • What is the top row spacing issue? – m.rufca Jan 27 '16 at 22:47
  • He is probably talking about the black space that is left at the end of the first row. That's the problem with automatic calculated width. But if you play with the of the inner elements you can avoid it. Try setting the .item margin to 10px for starters. – F. Versehgi Jan 27 '16 at 23:53
1

Just so that the code is out there in case it's useful, you can get the same behavior as F. Versehgi's answer without absolute positioning. This uses flexbox (so requires IE11, but any other browser should be fine) and some media queries (to account for the Bootstrap responsive container).

Note: You'll want to view the JSFiddle or CodePen link below, because the Stack Snippet is not working properly, for some reason:

$(document).ready(function() {
    function fillGrid() {
        var $gridContainer = $('.grid-container');
        var htmlGridItem = $('#tmpl_grid_item').html();
        $gridContainer.empty();
        for (var i = 0; i < 20; i++) {
            var $gridItem = $(htmlGridItem);
            $gridContainer.append($gridItem);
        }
    };
    fillGrid();
});
.container {
    background-color: #2B3643;
}
.container * {
    box-sizing: content-box;
}
.grid-container {
    padding-top: 30px;
    padding-bottom: 0px;
    display: flex;
    flex-wrap: wrap;
    margin: 0px auto;
}
.grid-item-wrapper {
    width: 200px;
    margin-bottom: 15px;
}
.grid-item {
    margin-bottom: 15px;
}

.grid-item > .item-desc {
    padding: 8px;
    background-color: #333333;
    color: #CFCFCF;
}

body {
    padding-top: 60px;
}

@media (min-width: 762px) and (max-width: 991px) {
    .grid-item-wrapper:nth-child(3n+1) {
        margin-left: 15px;
    }
}
@media (min-width: 992px) {
    .grid-item-wrapper:nth-child(4n+1) {
        margin-left: 9px;
    }    
}
@media (min-width: 1200px) {
    .grid-item-wrapper:nth-child(4n+1) {
        margin-left: 109px;
    }  
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<div class="container">
    <div class="grid-container row">
        <!-- grid items -->
    </div>
</div>
<template id="tmpl_grid_item">
    <div class="grid-item-wrapper col-xs-3">
        <div class="grid-item">
            <div class="item-picture">
                <img src="http://lorempixel.com/350/200/food/" style="width: 100%;" />
            </div>
            <div class="item-desc">
                Lorem Ipsum
            </div>
        </div>
    </div>
</template>
TylerH
  • 20,799
  • 66
  • 75
  • 101