Center align container and left align child elements

I've got X number of images (all the same height and width), and I want to display them on a web page. But I want to make the page automatically display the maximum number of images on a row (without resizing the images) when the browser is resized, and to show the images a fixed distance apart.

Also the images should be grouped together in the centre of the page, and displayed one after the other.

e.g. When the browser window is only wide enough to display 3 images on a row, they should be displayed as follows.

3 images per row grouped together a fixed distance apart, in the centre of the page, one after the other. enter image description here

And if the browser is made wider so 4 images can be displayed on a row they should be displayed like so.

4 images per row (without resizing the images), grouped together a fixed distance apart, in the centre of the page, one after the other. enter image description here

So far I've written the following code:

HTML

<div class="outer-div">
    <div class="inner-div">
        <div class="image-div"><img src="images/1.png"></div>
        <div class="image-div"><img src="images/2.png"></div>
        <div class="image-div"><img src="images/3.png"></div>
        <div class="image-div"><img src="images/4.png"></div>
        <div class="image-div"><img src="images/5.png"></div>
    </div>
</div>

CSS

img {
    height: 200px;
    width: 200px;
    padding: 10px;
}

.image-div {
    display: inline;
}

.outer-div {
    text-align: center;
    width: 100%;
}

.inner-div {
    text-align: left;
    display: inline;
}

So the images are displayed inline with a 10px padding inside a div (inner-div) which is then centred inside the outer-div. And the images are text-aligned to the left inside the inner-div.

But the problem is they are displayed as follows:

enter image description here

And like follows when the browser is made wider enter image description here

Can someone please show me how to display the images like the first set of images?

i.e. Maximum number of images per row (without resizing the images), one after another, grouped together in the centre of the page, fixed distance apart (wrapped).


Solution 1:

There isn't an easy way to achieve the layout with plain CSS as far as I know. The following approach uses media queries to set the width of inner divs for different viewport sizes.

Consider to use Javascript if you have a rather large number of items, CSS preprocessors might be helpful too.

See code snippet and comments inline, also check out the jsfiddle example for easy testing.

body {
    margin: 10px 0;
}
.outer {
    text-align: center;
}
.inner {
    font-size: 0; /* fix for inline gaps */
    display: inline-block;
    text-align: left;
}
.item {
    font-size: 16px; /* reset font size */
    display: inline-block;
    margin: 5px; /* gutter */
}
.item img {
    vertical-align: top;
}
@media (max-width: 551px) { /* ((100+5+5)x5)+1 */
    .inner {
        width: 440px; /* (100+5+5)x4 */
    }
}
@media (max-width: 441px) {
    .inner {
        width: 330px;
    }
}
@media (max-width: 331px) {
    .inner {
        width: 220px;
    }
}
@media (max-width: 221px) {
    .inner {
        width: 110px;
    }
}
<div class="outer">
    <div class="inner">
        <div class="item"><img src="//dummyimage.com/100"></div>
        <div class="item"><img src="//dummyimage.com/100"></div>
        <div class="item"><img src="//dummyimage.com/100"></div>
        <div class="item"><img src="//dummyimage.com/100"></div>
        <div class="item"><img src="//dummyimage.com/100"></div>
    </div>
</div>

Solution 2:

Maximum number of images per row (without resizing the images), one after another, grouped together in the centre of the page, fixed distance apart (wrapped).

That was a really good question. It seems very simple at first, but the optimum result is hard to achieve.

I don't really believe there's an way to achieve the expected behavior without using media queries.

However, making use of some media queries and knowing exactly the width of the images and the maximum possible number of images per row we can solve the issue using display: inline-* based properties.


display: inline-block

Should support old browsers, since it's around since CSS2. We have to use a little trick to prevent the rendering of an undesired blank space between the items.

The trick is setting the CSS property font-size: 0.


display: inline-flex

This solution makes use of the CSS flexbox and its a good option for modern browers.


display: inline-table

Supported since CSS2 also and no tricks needed in order to make it work.


display: inline

The final result is not the one expected by the author, since the elements in the second row will be center aligned and not left aligned. The good part about this solution is that it will work without previous knowledge of the image width and media queries.


.wrapper {
  text-align: center;
}
.inline {
  font-size: 0;
  display: inline;
}
.inline-block {
  display: inline-block;
  font-size: 0;
  text-align: left;
}
.inline-flex {
  display: inline-flex;
  flex-wrap: wrap;
}
.inline-table {
  display: inline-table;
  text-align: left;
}
.item {
  margin: 10px;
}
@media (max-width: 240px) {
  .inline-block,
  .inline-flex,
  .inline-table {
    width: 120px;
  }
}
@media (min-width: 241px) and (max-width: 360px) {
  .inline-block,
  .inline-flex,
  .inline-table {
    width: 240px;
  }
}
@media (min-width: 361px) and (max-width: 480px) {
  .inline-block,
  .inline-flex,
  .inline-table {
    width: 360px;
  }
}
@media (min-width: 481px) and (max-width: 600px) {
  .inline-block,
  .inline-flex,
  .inline-table {
    width: 480px;
  }
}
@media (min-width: 601px) and (max-width: 720px) {
  .inline-block,
  .inline-flex,
  .inline-table {
    width: 600px;
  }
}
@media (min-width: 721px) and (max-width: 840px) {
  .inline-block,
  .inline-flex,
  .inline-table {
    width: 720px;
  }
}
<h1>display: inline-block</h1>

<div class="wrapper">

  <div class="inline-block">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

  </div>

</div>

<h1>display: inline-flex</h1>

<div class="wrapper">

  <div class="inline-flex">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

  </div>

</div>

<h1>display: inline-table</h1>

<div class="wrapper">

  <div class="inline-table">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

  </div>

</div>

<h1>display: inline</h1>

<div class="wrapper">

  <div class="inline">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

    <img class="item" src="http://dummyimage.com/100">

  </div>

</div>

Solution 3:

Here's a generic solution that may work for you and others.

HTML

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>

CSS

ul {
    margin: 0 auto;              /* center container */
    width: 1000px;
    padding-left: 0;             /* remove list padding */
    list-style-type: none;
    font-size: 0;                /* remove inline-block white space;
                                    see https://stackoverflow.com/a/32801275/3597276 */
}

li {
    display: inline-block;
    font-size: 60px;             /* restore font size removed in container */
    width: 150px;
    height: 150px;
    padding: 5px;
    margin: 15px 25px;
    box-sizing: border-box;
    text-align: center;
    line-height: 150px;
}

@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width: 600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }

DEMO

Re: Flexbox: Although flexbox is an awesome tool, it's not the best solution for this particular problem. I explain my reasoning here: How to center a flex container but left-align flex items