Read my book

I wrote books about Webpack and React. Check them out!

Friday, January 11, 2013

Minimal Split Reveal in CSS

I recently came by a post that showed how to implement a split reveal effect using some CSS and markup. Unfortunately the method seemed a tad too complex for me. I'm not particularly happy that you have to edit the images you want to use to. As a result I came up with perhaps a smarter way to achieve the same thing with minimal amount of markup and CSS.

My approach is based on the fact that you can use overflow: hidden; property to crop content. I simply set up a cropping container this way and animate the images inside that. I use some trickery to apply the same image to both and then offset them so that it looks like a split.

Here's the basic markup:
<div class="images">
  <div class="crop cat">
    <div class="upper image"></div>
    <div class="lower image"></div>
    <div class="content">Lol, cat!</div>
  </div>
  <div class="crop cattoo">
    <div class="upper image"></div>
    <div class="lower image"></div>
    <div class="content">Lol, cat!</div>
  </div>
</div>

And the CSS:
/* inspired by http://designshack.net/articles/css/perform-a-split-reveal-with-css/ */

/* images */
.cat.crop {
  width: 100px;
  height: 100px;
}
.cat.crop .image {
  background: url(http://placekitten.com/100/100);
}

.cattoo.crop {
  width: 300px;
  height: 200px;
}
.cattoo.crop .image {
  background: url(http://placekitten.com/300/200);
}

.catcat.crop {
  width: 400px;
  height: 200px;
}
.catcat.crop .image {
  background: url(http://placekitten.com/400/200);
}

/* animations */
.crop:hover .upper.image {
  top: -30%;
}

.crop:hover .lower.image {
  bottom: -30%;
}

.crop:hover .left.image {
  left: -30%;
}

.crop:hover .right.image {
  right: -30%;
}

/* necessary bits */
.crop {
  position: relative;
  overflow: hidden;
  margin: 2em;
  background: #ecb;
}

.crop .content {
  position: absolute;
  top: 50%;
  width: 100%;
  height: 100%;
  margin-top: auto;
  margin-bottom: auto;
  text-align: center;
}

.crop .image {
  z-index: 1;
  position: absolute;
  width: 100%;
  height: 100%;
  background-repeat: no-repeat;
}

.crop .upper.image, .crop .lower.image {
  height: 50%;
}

.crop .left.image, .crop .right.image {
  width: 50%;
}

.crop .upper.image {
  top: 0;
  -webkit-transition: top 0.3s ease;
  -moz-transition: top 0.3s ease;
  -o-transition: top 0.3s ease;
  -ms-transition: top 0.3s ease;
  transition: top 0.3s ease;
}

.crop .lower.image {
  bottom: 0;
  background-position: 0% 100%;
  -webkit-transition: bottom 0.3s ease;
  -moz-transition: bottom 0.3s ease;
  -o-transition: bottom 0.3s ease;
  -ms-transition: bottom 0.3s ease;
  transition: bottom 0.3s ease;
}

.crop .left.image {
  left: 0;
  background-position: 0% 50%;
  -webkit-transition: left 0.3s ease;
  -moz-transition: left 0.3s ease;
  -o-transition: left 0.3s ease;
  -ms-transition: left 0.3s ease;
  transition: left 0.3s ease;
}

.crop .right.image {
  right: 0;
  background-position: 100%;
  -webkit-transition: right 0.3s ease;
  -moz-transition: right 0.3s ease;
  -o-transition: right 0.3s ease;
  -ms-transition: right 0.3s ease;
  transition: right 0.3s ease;
}
And since just reading the code is boring, give the demo a go:
Split Reveal demo
In other news, I published a post about several Canvas libraries over at JSter.

EDIT: I added definitions for left/right reveal and changed it not to depend on top-margin anymore. That caused some issues with non-square images.