1

I want a dynamically generated grid of fixed size cards to be horizontally centered in a container of variable width, basically this: https://foodgawker.com/

My question is similar to Center a grid of Divs (dynamically generated) or How to center a grid of divs? (the example is from there), except they both recomend using display: inline-block instead of float : left, which only works as long as there are no further block elements inside the cards.

Here is the example from the previous question with one block element added inside the card, the whole layout breaks: http://jsbin.com/vozusukigo/1/edit?html,css,output. Also the foodgawker.com uses float : left, not display: inline-block.

Here is a JS Bin for your convenience, I am grateful for any help.

EDIT: The last row should aligned to left as in the example. To my horror the accepted answer to similar question uses JQuery (and none of the flexbox answers have fixed size gaps).

Community
  • 1
  • 1
daniel.sedlacek
  • 8,129
  • 9
  • 46
  • 77
  • The best approach for these solutions made easy is [Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes). Consider using it ? – Nikhil Nanjappa Dec 09 '16 at 11:15

3 Answers3

3

These kinda solutions especially are made easy now thanks to the Flexbox concept in CSS3.

https://jsbin.com/vetanocaxi/1/edit?html,css,output

Having the same HTML, the CSS can be written as below

.ct {
  background-color : #ffff00;
  display: flex;
  justify-content: flex-start; /* center if you want to the center */
  align-items: center;
  flex-wrap: wrap;
}

.el {
  width : 50px;
  height : 50px;
  background-color : #ff9999;
  margin : 5px;
  display: flex;
  justify-content: center; /* center inside flex items */
  align-items: center; /* center inside flex items */
}

No floats required & even better you can easily have complex structure within individual flex items without effecting the outer layout structure.

.ct {
  background-color : #ffff00;
  display: flex;
  justify-content: flex-start; /* center if you want to the center */
  align-items: center;
  flex-wrap: wrap;
}

.el {
  width : 50px;
  height : 50px;
  background-color : #ff9999;
  margin : 5px;
  display: flex;
  justify-content: center; /* center inside flex items */
  align-items: center; /* center inside flex items */
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div class="ct">
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
    <div class="el"><p>flex</p></div>
  </div>
</body>
</html>
Nikhil Nanjappa
  • 6,454
  • 3
  • 28
  • 44
  • Thanks, it works but could you make the last row align to left? I should have specifically mentioned that in my question. I found this http://stackoverflow.com/questions/19527104/left-aligned-last-row-in-centered-grid-of-elements and the accepted answer uses JQuery!!! – daniel.sedlacek Dec 09 '16 at 11:28
  • not if you use justify-content: center, at least not in the latest Chrome – daniel.sedlacek Dec 09 '16 at 11:34
  • Oh ok let me clarify then - You want to center align the contents but the overflowing contents(2nd row onwards) you want those to start from the left .. correct ? – Nikhil Nanjappa Dec 09 '16 at 11:39
  • not 2nd row onwards, just the last row - there is an illustration in the question I posted above. – daniel.sedlacek Dec 09 '16 at 11:47
  • Sorry to break it to you man but Its not at all the same unfortunately, main difference - you don't even know how many items are in the last row ? If you atleast give me a number i could target it & do something. The other question has a "fixed number of divs" in the last row which he wants left aligned but you don't. – Nikhil Nanjappa Dec 09 '16 at 12:05
  • I believe that is not the case. From the above question: "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." – daniel.sedlacek Dec 09 '16 at 12:44
1

Flexbox can be used to achieve this effect like this: http://jsbin.com/vunubuqobo/edit?html,css,output

Main assumption is a fixed width for all cards. A small nuisance is a bunch of media queries to set .center_wrapper's width right, but that is easy to overcome with Less/SCSS/etc.

Note: use jsbin link above to check out responsiveness.

.cards_wrapper {
    background: red;
}

@media(min-width: 122px) {
  .center_wrapper { width: 122px; }
}

@media(min-width: 296px) {
  .center_wrapper { width: 244px; }
}

@media(min-width: 416px) {
  .center_wrapper { width: 366px; }
}

@media(min-width: 524px) {
  .center_wrapper { width: 488px; }
}

@media(min-width: 646px) {
  .center_wrapper { width: 610px; }
}

.center_wrapper {
  display: flex;
  flex-wrap: wrap;
  padding: 10px;
  margin: 0 auto;
  background: yellow;
}

.card {
  height: 100px;
  width: 100px;
  border: 1px solid;
  margin: 10px;
  text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>



<div class="cards_wrapper">
    <div class="center_wrapper">
        <div class="card">
          
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
        <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
        <p>block element</p>
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
      <div class="card">
            <img src="./Index - My ASP.NET MVC Application_files/noImageAvailable.png">
        </div>
    </div>
</div>  
</body>
</html>
0

To be honest I can't see any problem by using display: inline-block and have block elements inside the repeating divs. Also aligning the last row to the left is simple and doesn't require a single line of JavaScript or any complex workarounds.

According to the link you have posted you could achieve the layout with the following HTML structure and CSS code

body {
  background: #eee;
}
#wrapper {
  font-size: 0;
  padding: 10px 0;
}
.item {
  width: calc(25% - 4px);
  background: white;
  overflow: hidden;
  border-radius: 3px;
  display: inline-block;
  font-size: initial;
  margin: 2px;
}
p {
  padding: 4px 20px;
}
img {
  width: 100%;
}
<div id="wrapper">
  <div class="item">
    <img src="https://photo.foodgawker.com/wp-content/uploads/2016/12/2845923.jpg" alt="" />
    <p>All the nutty deliciousness of pecan pies - these no bake Rice Krispie Pecan Pie Cookies are vegan-friendly & dairy-free friendly!</p>
  </div>

  <div class="item">
    <img src="https://photo2.foodgawker.com/wp-content/uploads/2016/12/2845735.jpg" alt="" />
    <p>This Barbecue Chicken Cornbread Casserole is an easy dinner that comes together in just 15 minutes!!</p>
  </div>

  <div class="item">
    <img src="https://photo.foodgawker.com/wp-content/uploads/2016/12/2845542.jpg" alt="" />
    <p>Vegan Meringue Kisses, made using aquafaba</p>
  </div>

  <div class="item">
    <img src="https://photo2.foodgawker.com/wp-content/uploads/2016/12/2845725.jpg" alt="" />
    <p>Healthy spicy creole pulled pork made in the slow cooker! {Gluten Free, Dairy Free, Paleo}</p>
  </div>

  <div class="item">
    <img src="https://photo.foodgawker.com/wp-content/uploads/2016/12/2845855.jpg" alt="" />
    <p>Praline chocolates with a crispy dark chocolate coating and a soft caramelized nuts filling. Chocolatey, nutty and insanely delicious!</p>
  </div>
</div>
SvenL
  • 1,904
  • 8
  • 10
  • the problem is you hardcoded the width of the card to 1/4 of the container. The correct solution has as many cards in the row as can be fitted into the container. Try to resize the foodgawker example – daniel.sedlacek Dec 09 '16 at 12:39