Search code examples
csscss-transitionsflexboxvertical-alignment

Card with vertical aligned content, and animated states


What is the best way to vertically align content within cards, whilst still allowing them to animate on hover, to show different screens?

For example if I have cards, each with a front which is shown and a back which is faded in on hover:

<div class="items">
  <div class="item">
      <div class="front">
        <i class="material-icons">build</i>
        <span>Item 1</span>
      </div>
      <div class="back">hello there</div>
  </div>
  <div class="item">
      <div class="front">
        <i class="material-icons">build</i>
        <span>Item 1</span>
      </div>
      <div class="back">hello there</div>
  </div>
  <div class="item">
      <div class="front">
        <i class="material-icons">build</i>
        <span>Item 1</span>
      </div>
      <div class="back">hello there</div>
  </div>
</div>

Then using this css:

.item {
    align-items: center;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 200px;
    background-color: tomato;
    margin: 0 auto 1rem auto;
    width: 200px;
    position: relative;
}

.item .material-icons {
    display: block;
}

.back,
.front {
    opacity: 0;
    position: absolute;
    text-align: center;
    width: 100%;
    -webkit-transition: opacity .25s ease-in-out;
    -moz-transition: opacity .25s ease-in-out;
    -ms-transition: opacity .25s ease-in-out;
    -o-transition: opacity .25s ease-in-out;
    transition: opacity .25s ease-in-out;
}

.front {
    opacity: 1;
}

.item:hover .front {
    opacity: 0;
}

.item:hover .back {
    opacity: 1;
}

.material-icons {
    font-size: 5em !important;
}

However after using position absolute, my vertical centering doesn't work, and i'm pretty sure this might not be the best approach!

You can see a half working version here: http://jsfiddle.net/kmturley/8o29y7pd/26/

Thanks!


Solution

  • You can use transform to do the centering. It works great with absolute position elements. You won't need flexbox at all.

    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    

    http://jsfiddle.net/1354hzqb/