Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a card flipper with front/back faces WITHOUT absolut positioning

I want to add a new feature to my site that uses the card-flipper schema from David Walsh's site: https://davidwalsh.name/css-flip. The problem is, the content in my cards is variable so the height is unknown (and it's a responsive site as well). I have a footer at the bottom of my page which needs to be below this area, but since this approach relies on absolute positioning, the footer will be at the top like in this codepen: https://codepen.io/anon/pen/ALJmGZ

Can anyone think of any css hacks or alterations to this approach that would make it so the cards don't have to be absolutely positioned?

HTML:

<div class="flip-container" ontouchstart="this.classList.toggle('hover');">
  <div class="flipper">
    <div class="front">
      <span class="name">David Walsh</span>
    </div>
    <div class="back">
      <div class="back-logo"></div>
      <div class="back-title">@davidwalshblog</div>
      <p>Mozilla Web Developer, MooTools & jQuery Consultant, MooTools Core Developer, Javascript Fanatic, CSS Tinkerer, PHP Hacker, and web lover.</p>
    </div>
  </div>
  <footer>Here is my footer</footer>
</div>

CSS:

.flip-container {
  -webkit-perspective: 1000;
  -moz-perspective: 1000;
  -o-perspective: 1000;
  perspective: 1000;

    border: 1px solid #ccc;
}

    .flip-container:hover .flipper,  
  .flip-container.hover .flipper {
        -webkit-transform: rotateY(180deg);
        -moz-transform: rotateY(180deg);
    -o-transform: rotateY(180deg);
        transform: rotateY(180deg);
    }

.flip-container, .front, .back {
    width: 320px;
    height: 427px;
}

.flipper {
    -webkit-transition: 0.6s;
    -webkit-transform-style: preserve-3d;

    -moz-transition: 0.6s;
    -moz-transform-style: preserve-3d;

  -o-transition: 0.6s;
    -o-transform-style: preserve-3d;

    transition: 0.6s;
    transform-style: preserve-3d;

    position: relative;
}

.front, .back {
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
  -o-backface-visibility: hidden;
    backface-visibility: hidden;

    position: absolute;
    top: 0;
    left: 0;
}

.front {
    background: url(http://davidwalsh.name/demo/dwflip.jpg) 0 0 no-repeat;
    z-index: 2;
}

.back {
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);
  -o-transform: rotateY(180deg);
    transform: rotateY(180deg);

    background: #f8f8f8;
}

.front .name {
    font-size: 2em;
    display: inline-block;
    background: rgba(33, 33, 33, 0.9);
    color: #f8f8f8;
    font-family: Courier;
    padding: 5px 10px;
    border-radius: 5px;
    bottom: 60px;
    left: 25%;
    position: absolute;
    text-shadow: 0.1em 0.1em 0.05em #333;

    -webkit-transform: rotate(-20deg);
    -moz-transform: rotate(-20deg);
  -o-transform: rotate(-20deg);
    transform: rotate(-20deg);
}

.back-logo {
    position: absolute;
    top: 40px;
    left: 90px;
    width: 160px;
    height: 117px;
    background: url(http://davidwalsh.name/demo/logo.png) 0 0 no-repeat;
}

.back-title {
    font-weight: bold;
    color: #00304a;
    position: absolute;
    top: 180px;
    left: 0;
    right: 0;
    text-align: center;
    text-shadow: 0.1em 0.1em 0.05em #acd7e5;
    font-family: Courier;
    font-size: 2em;
}

.back p {
    position: absolute;
    bottom: 40px;
    left: 0;
    right: 0;
    text-align: center;
    padding: 0 20px;
  font-family: arial;
  line-height: 2em;
}

footer {
  background:red;
}
like image 821
jas7457 Avatar asked Jan 06 '23 05:01

jas7457


2 Answers

I found a way to accomplish this using pure css and no position absolute. I used css animations instead of transitions and you can set the height/width of the elements to 0 at the 50% keyframe. Check out the fiddle: https://codepen.io/anon/pen/bwmkAo

Sass:

@keyframes no-show {
    0% {
        transform: rotateY(0deg);
    height: auto;
    width: 100%;
    }

    49% {
        height: auto;
        width: 100%;
    }

    50% {
        height: 0;
        width: 0;
    }

    100% {
        transform: rotateY(180deg);
        height: 0;
        width: 0;
    }
}

@keyframes show {
    0% {
        transform: rotateY(-180deg);
        height: 0;
        width: 0;
    }

    49% {
        height: 0;
        width: 0;
    }

    50% {
        height: auto;
        width: 100%;
    }

    100% {
        transform: rotateY(0deg);
        height: auto;
        width: 100%;
    }
}

.flip-container {
    border: 1px solid #ccc;
}

.flip-container, .front, .back {
    width: 320px;
}

.flipper {
    position: relative;
}

.front, .back {
  position: relative;
    perspective: 1000px;

    transform-style: preserve-3d;
    perspective-origin: top center;
    animation-duration: 2s;
    animation-timing-function: linear;
    transition-property: transform;
    animation-fill-mode: forwards;
    -webkit-animation-fill-mode: forwards;
    overflow: hidden;
}

.front {
    z-index: 2;

    transform: rotateY(0deg);
    animation-name: show;
    .flipper.active & {
        animation-name: no-show;
    }

  .inner {
    height: 300px;
    background: green;
  }
}

.back {
    transform: rotateY(-180deg);
    animation-name: no-show;

    .flipper.active & {
        animation-name: show;
    }

  .inner {
    height: 400px;
    background: blue;
  }
}

footer {
    background: red;
}
like image 56
jas7457 Avatar answered Jan 07 '23 20:01

jas7457


I don't think it's possible to make an effect similar to this without using absolute positioning.

The best way to do this would be in JS to grab the heights.

Here's a CodePen with the basics: https://codepen.io/CourtDemone/pen/vXVbGQ

Basically just move the footer out of the flip container and add some JS like this.

var heightFront, heightBack;

heightFront = $('.front').height();
heightBack = $('.back').height();

if(heightFront > heightBack){
  $('.flip-container').height(heightFront);
}else{
  $('.flip-container').height(heightBack);
}
like image 20
CourtDemone Avatar answered Jan 07 '23 20:01

CourtDemone