I recently had the opportunity to launch Shelter In Space for the band Khruangbin which allows users to generate a Spotify or Apple Music playlist (curated by them) for a home activity of their choosing. The design of this app was inspired by the guide animations from the 1980's BBC television adaption of The Hitchhiker's Guide to the Galaxy. One of the key components I tried to recreate was the vertical scanning effect which transitioned between content. Click the image in the Codepen below to see the final solution and read on to better understand how it was developed.
First, the structure. .scanner
holds two divs which both have background images. One is a pair of touching hands and another is Buddah. Both of these are absolutely positioned on top of each other. There is a single Vue property of state which allows toggling between the two via a click event on the .scanner
div.
Let's first talk about the clipping transition which clips one image out of frame while showing the other. Vue has great documentation on ways to apply enter/leave transitions which an item is removed or added from the DOM. In our case, we'll be using the transition classes which Vue applies automatically. The clip-path
CSS property allows you to clip an element in all sorts of shapes and sizes. We're only interested in an inset rectangular shape.
For example, if you wanted to clip 50% of a div from the top.
clip-path: inset(50% 0 0 0)
What about 75% from the bottom?
clip-path: inset(0 0 75% 0)
The clip-path
property is also animatable. With this knowledge, we can setup our transition classes accordingly.
/* Clip 100% from bottom before shown */
.scan-enter{
clip-path: inset(0 0 100% 0);
}
/* Transition to no clipping from bottom */
.scan-enter-to{
clip-path: inset(0 0 0 0);
}
/* Start from no clipping */
.scan-leave{
clip-path: inset(0 0 0 0);
}
/* Transition to 100% clipping from top */
.scan-leave-to{
clip-path: inset(100% 0 0 0);
}
/* Set time and easing */
.scan-enter-active, .scan-leave-action{
transition: clip-path 2s linear;
}
Make sure to add key
attributes to your content and clicking should show the clip-path
transition. Now, let's discuss the scanner line itself. In the source material, the scanner lines sits over both the incoming and outgoing content at the point of transition and turns content beneath it white without affecting the black background. CSS has a property called backdrop-filter
which allows you to apply CSS filters such as blur or brightness to elements beneath the styled div. While most folks might use this to create blurred overlays, let's use it to brighten the illustrations. Rather than create a new div for the line, we'll add a ::before
pseudo element to each image div and position it absolutely.
.scanner div::before{
backdrop-filter: blur(1px) brightness(1000%) grayscale(100%);
-webkit-backdrop-filter: blur(1px) brightness(1000%) grayscale(100%);
content: "";
display: block;
height: 100%;
position: absolute;
transform: translateY(-50%);
width: 100%;
}
Note: I'm using the transform here to make sure the line isn't present before or after transition. There's probably a smarter way to do this but it works.
With the pseudo element in place, we can expand on our transition classes to simply move the position of the line.
/* Start at the top */
.scan-enter::before, .scan-leave::before{
top: 0%;
}
/* Transition to the bottom */
.scan-enter-to::before, .scan-leave-to::before{
top: 100%;
}
/* Set timing and ease */
.scan-enter-active::before, .scan-leave-active::before{
transition: top 2s linear;
}
And that's about it. As a Vue beginner, I was very happy with this result and I think it adds a lot of magic to our project without adding much complexity.
Top comments (0)