2

How can I centre the following element:

<div class="outer">
  <div class="inner">
    <div class="cards card1">Card 1</div>
    <div class="cards card2">Card 2</div>
    <div class="cards card3">Card 3</div>
    <div class="cards card4">Card 4</div>
  </div>
</div>

The number of cards is dynamically set. So is the width of outer div. Depending on the width of outer div, I would like to display them like this:

|                                    |
|    |Card 1 | |Card 2 | |Card 3|    |
|    |       | |       | |      |    |
|                                    |
|    |Card 4 |                       |
|    |       |                       |



|                           |
|    |Card 1 | |Card 2 |    |
|    |       | |       |    |
|                           |
|    |Card 3 | |Card 4 |    |
|    |       | |       |    |



|                                              |
|    |Card 1 | |Card 2 | |Card 3| |Card 4 |    |
|    |       | |       | |      | |       |    |

There are other questions like this (Centering a div block without the width), however they don't deal with multiple rows of cards. I have tried using the following:

.outer {
  text-align: center;
}

However this puts Card 4 is in the middle not on the left.

Or

.outer {
  width: 100%;
}
.inner {
  display: inline-block;
  transform: translateX(-50%); 
  left: 50%;
}

This works, but only when there is a single row of cards. When there are more cards than fit in one row, it aligns everything left.

Money_Badger
  • 537
  • 1
  • 5
  • 24

3 Answers3

2

Does this address what you're trying to do?

.outer {
  display: flex;
  justify-content: center;
}

.inner {
  display: flex;
  flex-wrap: wrap;
}

.cards {
  flex-basis: calc(100% / 3);
}
<div class="outer">
  <div class="inner">
    <div class="cards card1">Card 1</div>
    <div class="cards card2">Card 2</div>
    <div class="cards card3">Card 3</div>
    <div class="cards card4">Card 4</div>
  </div>
</div>
Andy Hoffman
  • 18,436
  • 4
  • 42
  • 61
  • Thanks for this, in case when outer div is wide enough, I would like all of the cards to be in one row. In case when it's too short for three cards, then it should have two rows of two. – Money_Badger Mar 15 '19 at 22:50
  • @Honey_Badger It feels like you're looking for a pure `CSS` solution. If so, I don't see how this will work, as it appears you would need container queries (not yet a thing) for this to work. Is `JavaScript` a no-no for this? – Andy Hoffman Mar 15 '19 at 23:12
  • I would prefer CSS only if possible. I guess alternative is to set width of `.inner` on `window.onresize` – Money_Badger Mar 15 '19 at 23:21
0

.outer {
  width: 100%;
}
.inner {
  display: flex;
  flex-flow: wrap;
  justify-content: flex-start;
}

.cards {
    width: calc(33.3333% - 40px);
    height: 270px;
    background-color: bisque;
    margin: 20px;
    box-sizing: border-box;
}
<div class="outer">
  <div class="inner">
    <div class="cards card1">Card 1</div>
    <div class="cards card2">Card 2</div>
    <div class="cards card3">Card 3</div>
    <div class="cards card4">Card 4</div>
  </div>
</div>

.outer {
  width: 100%;
}
.inner {
  display: flex;
  flex-flow: wrap;
  justify-content: center;
}

.cards {
    width: calc(33.3333% - 40px);
    height: 270px;
    background-color: bisque;
    margin: 20px;
    box-sizing: border-box;
}
<div class="outer">
  <div class="inner">
    <div class="cards card1">Card 1</div>
    <div class="cards card2">Card 2</div>
    <div class="cards card3">Card 3</div>
    <div class="cards card4">Card 4</div>
  </div>
</div>

.outer {
  width: 100%;
}
.inner {
    display: flex;
    flex-flow: wrap;
    justify-content: flex-start;
}

.cards {
    width: 200px;
    height: 270px;
    background-color: bisque;
    margin: 20px;
    box-sizing: border-box;
}
<div class="outer">
  <div class="inner">
    <div class="cards">Card 1</div>
    <div class="cards">Card 2</div>
    <div class="cards">Card 3</div>
    <div class="cards">Card 4</div>
    <div class="cards">Card 5</div>
    <div class="cards">Card 6</div>
    <div class="cards">Card 7</div>
    <div class="cards">Card 8</div>
    <div class="cards">Card 9</div>
    <div class="cards">Card 10</div>
    <div class="cards">Card 11</div>
    <div class="cards">Card 12</div>
  </div>
</div>

Hello from Russia! I love people from USA, Europe, Asia. So you want to do?

  • Thank you, I would like the cards to align depending on the width of the outer div. This will not always leave space for three cards, the number will depend on the width. – Money_Badger Mar 15 '19 at 22:58
  • @Honey_Badger In this case, you need to specify a fixed width of the cards. I made three examples for you. What you want is the last, third example. I do not perfectly know English. But, I can do any designs, structure, construction. Contact us. – Vladimir Rodichev Mar 15 '19 at 23:15
  • Yes, the width of the cards is set. The third example is correctly aligning the cards, however, as you can see, the `.inner` element is not centred but aligned left. I am trying to have equal margins on left and right. – Money_Badger Mar 15 '19 at 23:23
  • @Honey_Badger Good. I can build what you want. But for this I need more data: 1) Minimum site width 2) Maximum website width 3) Card width 4) All margin from one card to another Unit pixels – Vladimir Rodichev Mar 16 '19 at 00:51
0

Try using flex: auto on your cards.

.cards { 
   flex: auto; 
}

This is the same as flex: 1 1 auto, which in turn is short-hand for flex-grow: 1; flex-shrink: 1; flex-basis: auto;

Then on .inner use display: flex; flex-wrap: wrap;

.inner { 
   display: flex;
   flex-wrap: wrap; 
}

Have a look at the css in this snippet. It has a little playground so you can adjust the .outer container width dynamically, as well as the outer padding, card margins, and card paddings:

If you prefer, you can try the CodePen Demo:

var controlContainer=document.createElement("div");controlContainer.innerHTML='<div style="margin: 0px 0px 20px; display: flex; width: 100%; flex-direction: column; justify-content: space-around;" class="controls"><div style="display: flex; align-items: center; height: 30px;"><input class="outer-ctrl" type="range" min="100" max="1200" value="300"><label> <code>.outer { width: <span class="outer-span">300px</span> } </code></label></div><div style="display: flex; align-items: center; height: 30px;"><input class="outer-padding" type="range" min="0" max="30" value="0"><label><code>.outer: { padding: <span class="padding-span">0px</span> }</code></label></div><div style="display: flex; align-items: center; height: 30px;"><input class="card-margin" type="range" min="0" max="30" value="0"><label><code>.cards { margin: <span class="margin-span">0px</span> }</code></label></div><div style="display: flex; align-items: center; height: 30px;"><input class="card-padding" type="range" min="0" max="30" value="0"><label><code>.cards { padding: <span class="card-padding-span">0px</span> }</code></label></div></div>',document.body.prepend(controlContainer),document.querySelectorAll("span").forEach(function(e){e.style.cssText="background: black;color:white;padding: 7px;"}),document.querySelectorAll(".cards").forEach(function(e){e.style.cssText="background:yellow; border: 1px solid blue;"}),document.querySelector(".outer-ctrl").addEventListener("input",function(e){var n="".concat(e.target.value,"px");document.querySelector(".outer").style.width=n,document.querySelector(".outer-span").innerText=n}),document.querySelector(".card-margin").addEventListener("input",function(e){var n="".concat(e.target.value,"px");document.querySelectorAll(".cards").forEach(function(e){e.style.margin=n}),document.querySelector(".margin-span").innerText=n}),document.querySelector(".outer-padding").addEventListener("input",function(e){var n="".concat(e.target.value,"px");document.querySelector(".outer").style.padding=n,document.querySelector(".padding-span").innerText=n}),document.querySelectorAll(".cards").forEach(function(e){e.style.cssText="background:yellow; border: 1px solid blue;"}),document.querySelector(".card-padding").addEventListener("input",function(e){var n="".concat(e.target.value,"px");document.querySelectorAll(".cards").forEach(function(e){e.style.padding=n}),document.querySelector(".card-padding-span").innerText=n}),document.body.style.cssText="margin:0;padding:0;",document.querySelector(".outer").style.border="1px solid #333;";
.outer {
  width: 300px;
  border: 1px solid #333;
}

.inner {
  display: flex;
  flex-wrap: wrap;
}

.cards {
  flex: auto;
}
<div class="outer">
  <div class="inner">
    <div class="cards card1">Card 1</div>
    <div class="cards card2">Card 2</div>
    <div class="cards card3">Card 3</div>
    <div class="cards card4">Card 4</div>
  </div>
</div>
Dan Kreiger
  • 5,358
  • 2
  • 23
  • 27