1

I was meddling with vertical alignment in CSS, using a flexbox model, and there's a layout I'm struggling to fit:

Layout needed

The images in yellow have different max-height or max-width.

What I already did is:

.flex {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}

img {
    max-width: 100px;
}

.small {
    max-width: 50px; /* for example, this could be 30 or 40 */
}
<html>
<body>
  <div class="flex">
    <div class="child">
      <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
      <p> Text </p>
      <p> Text </p>
    </div>
    <div class="child">
      <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" class="small" />
      <p> Text </p>
    </div>
    <div class="child">
      <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
      <p> Text </p>
      <p> Text </p>
    </div>
  </div>
</body>
</html>

The main issues with this code are:

  • Images are not vertically centered (the center Google is a little lower than the other two)
  • It would be cool to have the caption vertically centered, but a baseline model would suffice.

Is it possible to do this with flexbox? If not, what is a good way of doing it?

sergdenisov
  • 8,327
  • 9
  • 48
  • 63
gandem
  • 13
  • 5

3 Answers3

1

.flex {
  display: flex;
  justify-content: space-around;
  height: 200px; /* for demo */
}

.child {
  display: flex;
  flex-direction: column;
  text-align: center;
}

img {
  margin: auto 0; /* explanation: http://stackoverflow.com/a/33856609/3597276 */
  max-width: 100px;
}

.small {
  max-width: 50px;
}

p {
  margin: 0;
}
<div class="flex">
  <div class="child">
    <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
    <p> Text </p>
    <p> Text </p>
  </div>
  <div class="child">
    <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" class="small" />
    <p> Text </p>
  </div>
  <div class="child">
    <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
    <p> Text </p>
    <p> Text </p>
  </div>
</div>

jsFiddle

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Thanks a lot ! I noticed my question wasn't precise enough ! I want images to be vertically centered, and same goes for captions ! – gandem Feb 27 '17 at 18:13
  • The images are still bottom-aligned and not center-aligned: the middle image is "lower" than the right and left one ! – gandem Feb 27 '17 at 18:31
1

You can do it with a HTML <table> or CSS table, both requires some markup changes.

.table {
  display: table;
  width: 100%;
  table-layout: fixed;
}

.tr {
  display: table-row;
}

.td {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
  outline: 1px solid pink;
}

img {
  max-width: 100%;
}
<div class="table">
  <div class="tr">
    <div class="td">
      <img src="//dummyimage.com/200x100">
    </div>
    <div class="td">
      <img src="//dummyimage.com/200x50">
    </div>
    <div class="td">
      <img src="//dummyimage.com/200x100">
    </div>
  </div>
  <div class="tr">
    <div class="td">
      <p>Text</p>
      <p>Text</p>
    </div>
    <div class="td">
      <p>Text</p>
    </div>
    <div class="td">
      <p>Text</p>
      <p>Text</p>
    </div>
  </div>
</div>
Stickers
  • 75,527
  • 23
  • 147
  • 186
0

you can use flex and still update your structure using figure and figcaption witch meets the content here :

.flex,
figure {
  display: flex;
  text-align: center;
}

figure {
  margin: 5px;/*optionnal*/
  flex-flow: column;
  flex: 1;
  justify-content: space-around;
  align-items: center;
  background: lightgray;
}

p {
  margin: 5px;
}

img,
figcaption {
  max-width: 100%;
}

.small {
  width: 50%;
}
<div class="flex">
  <figure>
    <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
    <figcaption>
      <p> Text </p>
      <p> Text </p>
    </figcaption>
  </figure>
  <figure>
    <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" class="small" />
    <figcaption>
      <p> Text </p>
    </figcaption>
  </figure>
  <figure>
    <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
    <figcaption>
      <p> Text </p>
      <p> Text </p>
    </figcaption>
  </figure>
</div>

You can add min-height to .flex or figure, also padding.

THis answer is a mix in between Michael_B and Pangloss answers (flex + new HTML structure)

Edit:

display:grid; will be done for that kind of jobs in close future hopefully:

img {
    max-width: 100px;
}

.small {
    max-width: 50px; /* for example, this could be 30 or 40 */
}
.flex, figure{
  display:grid;
  grid-template-columns: 1fr 1fr 1fr;/* 3 cols */
}
figure {
  grid-template-columns: 1fr ;/* reset to 1 col */
  grid-template-rows: 50% 50%; /* 2 rows of same height */
}
img, figcaption {
  align-self:center;
  justify-self:center;
}
<div class="flex">
  <figure>
      <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
    <figcaption>
      <p> Text </p>
      <p> Text </p>
    </figcaption>
  </figure>
  <figure>
      <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" class="small" />
    <figcaption>
      <p> Text </p>
    </figcaption>
  </figure>
  <figure>
      <img src="https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
    <figcaption>
      <p> Text </p>
      <p> Text </p>
    </figcaption>
  </figure>
</div>

see https://css-tricks.com/snippets/css/complete-guide-grid/

Note,

that you need to flag on : experimental CSS on chrome or firefox to play around with the grid CSS system at this answer's time.

Community
  • 1
  • 1
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • Thank you ! It works well here because : `.small { width: 50%; }` If we put width to 30% the image would not be centered anymore. I will add this in my question, as I noticed it wasn't clear enough, sorry ! – gandem Feb 27 '17 at 19:17
  • @gandem Then you definitly need 2 rows on top of each others , table could be the best way to do it using th and td to keep image and its caption clearly related. or use the display:grid properties, unfortunately not really avalaible yet ( added a snippet) – G-Cyrillus Feb 27 '17 at 19:44
  • @gandem flex is not yet avalaible for this unless you set an height on the container to contain img and caption in 2 different sibling containers where height is shared to 50% . Only the grid CSS will be able to do this in my opinion. Javascript can be used to retrieve the tallest height of your element in the row, then set this height to each containers ... flex will be then able to center image and text in those containers – G-Cyrillus Feb 27 '17 at 19:59