Oskar Persson
Oskar Persson

Reputation: 6765

Horizontally centering a flex container

When using flex for creating a grid of images, how can I horizontally center the grid itself on the page? I still want the images to left-align on each row. I would like it to be dynamic to the number of elements per row.

Jsfiddle with what I have so far

.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-content: flex-start;
  align-items: flex-start;
}

.gallery-artwork {
  width: 400px;
  display: flex;
  margin: 10px;
}
<div class="gallery">
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
</div>

Upvotes: 7

Views: 342

Answers (5)

Mikael
Mikael

Reputation: 310

This solution will work regardless of the number of elements and width.

https://jsfiddle.net/p01mx39h/14/

function addDummies() {
  imgsPerRow = Math.floor($(".gallery").width() / $(".gallery-artwork").outerWidth(true));
  if (imgsPerRow > 1) {
    missingImages = imgsPerRow - $(".gallery-artwork").length % imgsPerRow;
    while (missingImages > 0) {
      $(".gallery").append("<div class='gallery-artwork-dummy'></div>");
      $(".gallery-artwork-dummy").css('width', $('.gallery-artwork').outerWidth(true));
      missingImages--;
    }
  }
}

$(document).ready(function() {
	addDummies();
});
.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  align-content: flex-start;
  align-items: center;
}

.gallery-artwork {
  width: 400px;
  display: flex;
  margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gallery">
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
</div>

Upvotes: 2

zessx
zessx

Reputation: 68820

As stated by many answer here and on the web, you'll need (at least, for now) dummies elements.
Here's a way to do it easily, without calculation, and in plain JavaScript:

  • Add as many dummies as the amount of .gallery-artwork elements
  • Give these dummies the same style, without any height, nor vertical margins

This method has an advantage: you don't need to do any calculation! You're sure to always have enough dummies (whatever the screen width, the number of elements and their amount per row) to push your elements on the left side of your container.

So here's the code!

var gallery = document.querySelector('.gallery'),
    artworks = gallery.querySelectorAll('.gallery-artwork'),
    dummy = document.createElement('div');
dummy.classList.add('gallery-dummy');

// One element = one dummy
[].forEach.call(artworks, function() {
  gallery.appendChild(dummy.cloneNode());
});
.gallery {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.gallery-artwork {
  width: 400px;
  margin: 10px;
}
.gallery-dummy {
  width: 400px;
  margin: 0 10px;
  height: 0;
}
<div class="gallery">
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
  <div class="gallery-artwork">
    <img src="http://placehold.it/400x225">
  </div>
</div>

Upvotes: 1

DebRaj
DebRaj

Reputation: 599

Here is your updated CSS:

.gallery {
  display: flex;
  flex-flow: row wrap;
  justify-content:center;
}

.gallery-artwork {
  width: 400px;
  display: flex;
  flex-flow: column;
  margin: 0.5em;
}

jQuery:

$(document).ready(function(){
var i = $('.gallery-artwork').length;
    if (i % 2 == 0){
    }else{
        $(".gallery").append("<div class='gallery-artwork'></div>");
    }
});

Fiddle: https://jsfiddle.net/debraj/p01mx39h/9/

Upvotes: 0

zer00ne
zer00ne

Reputation: 44086

  • You can wrap an element around the whole thing and then just center as normal.
  • The matter of having the flex items left aligned is as simple as using the default value of justify-content: flex-start, but it doesn't center. So in order to maintain center-aligned flex-items, we use justify-content: center.
  • It centers perfectly but if the second row has a smaller amount of flex-items, then it'll look like this
  • In order to maintain everything being horizontally centered, and have a nice left-aligned behavior for the last row, we can add an extra flex-item and give it this: visibility: hidden. If the number of flex-items are dynamic, we use the following selector: .gallery-artwork:last-of-type { visibility: hidden; }

Here's the Demo

CSS

/* The wrap element that surrounds and centers everything */
.exhibition {
  padding: 10px;
  margin: 20px auto;
}
/* justify-content: center is needed for centering of the flex-items */   
.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
}

.gallery-artwork {
  width: 400px;
  margin: 10px;
}
 /* This is the last of the gallery-artwork (flex-item). 
 Being of the same dimensions as the other flex-items and hidden from site,
fills in the gap of an uneven row of flex-items. */

.gallery-artwork:last-of-type {
  visibility: hidden;
}

HTML

<section class="exhibition">
  <div class="gallery">
    <div class="gallery-artwork">
      <img src="http://placehold.it/400x225">
    </div>
    <div class="gallery-artwork">
      <img src="http://placehold.it/400x225">
    </div>
    <div class="gallery-artwork">
      <img src="http://placehold.it/400x225">
    </div>
    <div class="gallery-artwork">
      <img src="http://placehold.it/400x225">
    </div>
    <div class="gallery-artwork">
      <img src="http://placehold.it/400x225">
    </div>
    <div class="gallery-artwork">
      <img src="http://placehold.it/400x225">
    </div>
  </div>
</section>

Upvotes: 0

rrd
rrd

Reputation: 5977

Slightly alter your gallery css:

justify-content: center;

I used this today, so this is why I popped it in right away. But this CSS-tricks page really helped with the flex bits and pieces.

Upvotes: -1

Related Questions