1

I need to center a set of children in a container.

My requirements are:

  1. Each child needs a gutter to its left and right.
  2. I cannot set a margin or padding on the container.
  3. I cannot set padding on the children, but I can set margins.
  4. Each child should have a space/gutter to its left and right.
  5. Each child can have a different max-width set.
  6. If the child's max-width is greater than the container width, it should take up the full width (minus its gutters).
  7. If the child is narrower than the container it should be centered. I thought I would be able to achieve this with flexbox, because align-items: stretch; respects max-widths, however it will not center the children.

I cannot use margin: 0 auto; because I need to use the childrens' margins to set up the gutters to their left and right.

Here is my attempt using flexbox:

* {
  box-sizing: border-box;
}

main {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: center;
  max-width: 600px;
  outline: 1px dashed black;
  box-
}

section {
  min-height: 40px;
  margin-left: 20px;
  margin-right: 20px;
}

section + section {
  margin-top: 20px;
}
  
.s1 {
  background-color: red;
  max-width: 100px
}
  
.s2 {
  background-color: blue;
  max-width: 200px
}
  
.s3 {
  background-color: green;
  max-width: 300px
}
<main>
  <section class='s1'></section>
  <section class='s2'></section>
  <section class='s3'></section>
</main>

Is there any way to reliably achieve what I'm after?

Undistraction
  • 42,754
  • 56
  • 195
  • 331

2 Answers2

3

Yes, though you need to give the section a width, and use align-items: center

To preserve the gutter when a child reach its parent's width, you can use CSS calc(), and do e.g. width: calc(100% - 40px);, and since a narrower child is always centered, you should be able to drop the margin-left/right as well (and if, you will be able to use auto margins).

Do note, using align-items: center can cause overflow issues if not using the safe keyword, and using auto margins solves that being more cross browser than safe.

Stack snippet

* {
  box-sizing: border-box;
}

main {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 600px;
  outline: 1px dashed black;
}

section {
  width: calc(100% - 40px);
  min-height: 40px;
  margin-left: 20px;
  margin-right: 20px;
}

section + section {
  margin-top: 20px;
}
  
.s1 {
  background-color: red;
  max-width: 100px
}
  
.s2 {
  background-color: blue;
  max-width: 200px
}
  
.s3 {
  background-color: green;
  max-width: 700px
}
<main>
  <section class='s1'></section>
  <section class='s2'></section>
  <section class='s3'></section>
</main>

If you are able to drop the fixed margins, here's how using auto margin.

Stack snippet

* {
  box-sizing: border-box;
}

main {
  display: flex;
  flex-direction: column;
  text-align: center;
  max-width: 600px;
  outline: 1px dashed black;
}

section {
  width: calc(100% - 40px);
  min-height: 40px;
  margin: 0 auto;
}

section + section {
  margin-top: 20px;
}
  
.s1 {
  background-color: red;
  max-width: 100px
}
  
.s2 {
  background-color: blue;
  max-width: 200px
}
  
.s3 {
  background-color: green;
  max-width: 700px
}
<main>
  <section class='s1'></section>
  <section class='s2'></section>
  <section class='s3'></section>
</main>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • @SudiptoRoy Maybe...I might have misread it, and using `calc(100% - gutter)` will fix that – Asons Sep 16 '19 at 18:04
1

If you replace your max-width of the children with width, you can achieve what you are trying to. But I don't know if there is any limitation to do this change.

Add these rules to all sections

section {
  max-width: calc(100% - 40px);
  margin: 0 auto;
}

And if you replace max-width of .s1, .s2 and .s3 with width you can completely omit the style-rule of the main.

Sudipto Roy
  • 948
  • 8
  • 15