App Store Card Animation With Vue JS

App Store Card Animation With Vue JS

Today I’ll show you how to make an amazing
transition to opening cards in a Vue JS project, like this card animation from the iPhone’s
app store. Let’s start right now. What’s going on, my name is Mario, welcome
to another video. If this is your first time here and you wanna
learn more about Vue JS or other related stuff, start now by subscribing and clicking the
bell so you don’t miss anything. Now, I’ve played around with the card animation
from the App Store, I have recorded this on my iPhone, I like this card opening animation,
and I have found a solution on how you can implement this without any additional library
or tool. You can also make this with vanilla JavaScript. But I like to use Vue JS because it simplifies
some things. Of course, I have already prepared something,
so let’s take a look at the source code. First the App.vue file, we have here a list
with our data, an array with objects, and each object represents a card with a title,
a description, an image, and the property open, which holds a boolean, if this card
is open or not. Then, we have a separate Component, the Card
Component, which is rendered here in the template, combined with this v-for loop, which output
for each loop this Card Component, in the end. I set the index as key, and here I provide
the card item, the complete object in this case, for the Child Component. Now the Card Component here renders, as expected,
the card item. I set here the image as a background image
and output below the title and the description. You can’t see the description, because each
card has a fixed height with the overflow hidden attribute. Here you can see the stylings for the card. So, how can you implement this card animation
here from the App Store? The first idea is, of course, to change the
position of this item, to absolute respectively to fixed and set the attributes from the top
and left spacing to zero. This works well, but you can’t animate the
CSS position property. Maybe this will be possible later, but at
least in the current CSS version, this is not possible. But, you can use the transform attribute and
set the position to fixed, if the animation is done. It sounds simple, but there are still 1 or
2 problems we have to solve. More in a few seconds. Ok, let’s stick to the Card Component, we
don’t have to do anything in the App.vue file. First, we need a new CSS class, I name it
open. And I want to set the properties if the card
is opened. So let’s set the z-index to 100, the border-radius
to zero, border as well, and set the card to fullscreen, with 100 view width and 100
view height. Next, we need a click event on the card item,
to change the open status. And here I gonna call a function, Hmm, ‘handleView’
maybe. And create this function in the method object. And change here the open status to the opposite. The next step is, to bind our new CSS class
to the card item if the status ‘’ equal to true. Time to save and let’s take a look. Hmm ok, works fine, but you see, the position
isn’t right yet. We can now easily move the position with the
transform property. To demonstrate it, I set for the first card
the properties we need, with transform and with the translate function you can move the
element on the x- and y-axis. In this case, 20 pixels to the left and 20
to the top. And you see it works well, but this doesn’t
work for the other cards, and if you scroll a little bit and click a card, then it doesn’t
work either. To resolve this issue, you should get the
offset from the card to the viewport. Especially the offset to the left side and
to the top, and change the position dynamically. So I gonna remove this transform property. And, there are many ways to fetch these values. But first, we want to know on which item was
clicked, so we can pass here on the click event as an argument the event itself, with
$event. So we get this here now in our method and
I gonna use a new variable and name it ‘viewportOffset’ and here from the target element that was
clicked, we want to receive the position relative to the viewport. There is a nice method we can use, ‘getBoundingClientRect’. And this method returns an object with the
size of this element and the position to the viewport, so everything we need. By the way, this is a vanilla JavaScript function,
nothing to do with Vue JS. Well, next I write a condition if
true, then I gonna do something here. Now what? I like to use the dynamic style binding from
Vue JS. So let’s create a new data property for
this. The great thing is you can use for the style
binding a complete object, instead of a separate CSS property you like to bind. So let’s create one, I name it simply ‘styleObject’. And in this object, you can use each CSS property
as key. We need transform and as default value, I
define translate with zero-zero pixels. With this, you can easily enhance this object
later. Now you can bind this object here at the card
element. So, let’s stick to our method, again, and
do the magic stuff now. And here I gonna change the transform property
from the ‘styleObject’ and set it to a new translate value. As the first argument, you can use now our
object ‘viewportOffset’ and the left property holds the relative offset to the left side
and I reverse this value to change the position to the left side, not to the right. And as the second argument, I use the same
syntax, but with the property top, instead of left. In the else block, I set the object back to
the default values. Time to save and take a look. Hmm works fine, but if I scroll, you see the
problem. Before we fix this issue, let’s create first
the animation. And for this, I like to use the
page. And here you can create the animation really
easy. Remember we want an animation like the card
transition in the App Store. So I think the first part is an ease-in animation,
like this. And an ease-out animation at the last part,
but if you take a look at the app store animation, so the card moves a little bit over the final
position and then back. So we need an animation curve like this. Let’s see if that fits. Hmm, yes look good. So let’s stick to the card CSS class and
add the transition, aspect to all changes, with this duration here, and the animation
we have created. Ok, I save and yes this looks quite similar
to the App Store animation. Now, let’s stick to the problem with the
scrolling. How you can solve this issue? One solution is to set the position from the
page body to fixed and set the spacing to the top, based on the scrolled pixels, to
hold the position of the document, respectively to save the scrolled position. So let’s do this quickly with
and set this to minus and here we need the value from window.scroll, Y for the vertical
axis. And I gonna set the property
to fixed. Next, If we closing the card, we need the
scrolled position. After that, you can set the changed body values
back to the default values. And now, we scroll automatically with ‘window.scrollTo’
back to the scrolled position. This is a method, which expects two arguments. As first, you can write zero, the second argument
is important. Here you should pass the scrollY variable,
but we need an integer so let’s use the parseInt function and reverse the value. Time to save and with this solution here,
you get a great card animation, like the transition from the app store. Next, you may have a problem with the click
event. If you click, for example, the title, then
is this element also used to determine the offset. But, If you want to make sure that the card
element is always used, then you can set the pointer-events from the other elements to
none. In this case, to card top, the title, the
description and the image class, and here I set pointer-events to none. And you see it works great. Have fun with Vue JS.

7 Replies to “App Store Card Animation With Vue JS”

  1. You want to learn more about Vue JS? Then you are exactly right here. Learn Vue JS – From The Ground Up

  2. Can I Ask Quz ??? I Want To Understant When I will Build Same App With Web and Mobile , With Which Size Will Start Mobile Or Web

Leave a Reply

Your email address will not be published. Required fields are marked *