Keyframes not working the way it's intended

Shouldn’t the @keyframes revert back to default value after it is finished? The tutorial guy said it will revert back to default value once the animation is finished while still hovering on it.

Did I miss something?

8:55

It does move back to its default state which is at a transform of 200% as seen in the first rule. As soon as you hover you send it to 200% here.

.parent:hover .child {
transform: translateX(200%);
}

That means that while you are still hovering the starting position is at 200%. leave out that rule and it will return to the start even when hovered.

You also setting the keyframe to 200% but keyframes run from 0% - 100%. The from and to values are 0% and 100%.

0% / from and 100% / to ),

I believe this is the code you need if I understand what you are attempting.

.parent:hover .child {
  /*transform: translateX(200%);*/
  background-color: green;
  animation: leftright 1s linear;
}

.parent {
  background-color: darkblue;
  height: 300px;
  width: 300px;
}
.child {
  background-color: lightblue;
  height: 100px;
  width: 100px;
 /*transition: transform 1s linear;*/
}

@keyframes leftright {
  100% {
    transform: translateX(200%);
  }
}

If you wanted it to slide back to the start smoothly then you would do this.

.parent:hover .child {
  background-color: green;
  animation: leftright 2s linear;
}

.parent {
  background-color: darkblue;
  height: 300px;
  width: 300px;
}
.child {
  background-color: lightblue;
  height: 100px;
  width: 100px;
}

@keyframes leftright {
  50% {
    transform: translateX(200%);
  }
}
1 Like

I don’t understand this psuedo element , I understand what hover does, but shouldn’t the animation element apply to both parent and child class? Why does the animation element only apply to child class and not father class since the father class is also there?

and when I switch the roles of the classes to .child:hover .parent {}

and hover to the child container, it doesn’t move the parent container, why?

(off-topic : To be pedantic :hover is a pseudo class whereas :before :after are pseudo elements but that is irrelevant to the question but worth remembering.)

The animation is applied to .child only. For example if you remove the hover from the selector the rule looks like this.

.parent .child {
  background-color: green;
  animation: leftright 2s linear;
}

Looking at the rule why would you think that .parent has any of those rules applied to it?

The rule above simply targets .child (assuming it has a parent called .parent). There are no implications for .parent att all. It stays the same as it always was.

Now when you add the Hover pseudo class back in you get this.

.parent:hover .child {
  background-color: green;
  animation: leftright 2s linear;
}

Again you are not changing any styles on .parent but what you are saying is that when I hover the parent box please apply these styles to .child. This means that you can hover anywhere in that parent box (even when not over the child) and the animation will take place.

If instead you said.

.parent .child:hover {
  background-color: green;
  animation: leftright 2s linear;
}

Now the animation will only occur when you hover over the child box. Nothing will happen if you hover anywhere else in the parent. That means that it will be quite hard to hover the child while its is sliding around.

Do you know what descendant selectors are and how the work? The css you posted above would assume that the element called .parent is a child of .child.

CSS selectors only work in one direction. The rules are actually parsed from right to left.

.test1 .test2 .test3{...}

(A space is a descendant selector). The browser looks at the right most element and sees test3. It then looks to see if it has a parent of .test2 and if so it looks to see if that has a parent of .test1. If matched then the rules are applied to test3. There is no reverse process where you can style the parent based on its children. (This was a commonly asked for concept known as a parent selector but does not exist in css because css was built to work that way. Although in the future there are certain things proposed that may accomplish something like that).

2 Likes

In keyframes, Why do I need to put translateY and translateX in the same box and not in separate boxes to make the child box go left to right at the bottom of parent box. when I separated them, it didn’t do that and went from down to diagonal right.

That’s because the transform property resets all its values once you declare one of them only again. If you only specify the one value then your original value is lost.

If you say this:

transform:translateX(50px);

You are in effect saying this:

transform:translateX(50px) translateY(0);

Therefore if translateY was some other value then it just got changed back to zero.

2 Likes

In descendant selectors, the ancestor can’t do anything else but add pseudo elements and classes?

Yes basically the selector is like a path to your element. You are targeting the element in question (the one at the right end of the list) as long as it is in the context of its parents as defined by the descendant selectors. You can’t apply any rules to the parent based on what child it has as mentioned above.

.test1 .test2 .test3{...}

test3 is the only thing that gets styled.

You can however style text3 when say test1 is hovered (or indeed the same for test2 etc…). You could also use the other pseudo classes (:focus :active) for similar effect assuming the elements in question respond to those states.

There is a pseudo class called :focus-within which does allow the styling of a parent if the child is focussed and is almost like a parent selector in that case but of no importance in your example.

There is on the horizon the :has selector which will be much like a parent selector (unless it gets dropped or changed again).

However none of those are really needed in your example as the usual properties are working fine to achieve what you want.

1 Like

I don’t understand top down left right in keyframes

I added 300px down, why didn’t it go down like translateY?

There is no css property called down :slight_smile: Where did you get that from?

You can’t just invent your own :slight_smile: (although that would be fun)

translate(Y) will move something up or down and is commonly used in animations as it doesn’t cause a reflow. You can use positoning or margins etc to move something but the animation may be choppy as they will reflow the page and possible make the rest of the page move around if you are moving stuff in the flow.

I’m not quite sure what effect you were after and why transform was disregarded?

As I said you can use position: relative like this but won’t be as performant as translate;

  .Animation {
    animation: title 5s infinite;
    text-align: center;
    background-color: aqua;
    position: relative;
    top: 0;
  }

  @keyframes title {
    0 {
      color: black;
    }

    50% {
      top: 300px;
    }

    100% {
      color: red;
    }
  }

Also note that you can’t mix from and to and use percentages. You can only use one or the other and not mix them. (from = 0% and to = 100%)

2 Likes

I assumed because there’s top and left.

How do I move the text starting from right to original spot? or you can’t do that

Yes you just move it to the right in the first keyframe and then let it go back to the original.

e.g.

1 Like

In keyframes, Why isn’t the animation-delay not working while other CSS code can like opacity? can you not add any animation-(set attribute) to keyframes, if so why or no reason.

It doesn’t go in the key frame! Only animatable properties go in the key frames.

The animation delay goes in the original rule where you declare the animation.

.paragraph{
  animation: paragraph 1s;
   animation-fill-mode: forwards;
  animation-delay:1s;


}

What is a amitable property? I googled, nothing popped up and ok

First result for me on google. :slight_smile: (once I corrected the spelling ;))

In the keyframes you only place properties that you want to change over the time period specified. For example you change the opacity form zero to 1 over a period of time to get a fade effect. There would be no point in sticking an animation delay in there (even if you could) because you are not changing it from one state to another.

1 Like

What did I do wrong here?

animation is not working.

You tried to run an animation called forwards and there is none.

animation: forwards

You meant to say animation-fill-mode:forwards but you could just add it on the end anyway.

e.g.

animation: flexb 1s forwards;

As you are animating back to an initial state you don’t need forwards anyway. You only need forwards when you want the animation to stay at a position that is different from its default.

That means you can also shorten the keyframe as well.

.child{
    padding: 10px;
    animation: flexb 1s;
    /*animation: forwards;*/
}
@keyframes flexb{
    0%{transform: translateY(-50px);}
}

Although for clarity its quite good to stipulate the last position so you are certain so this is fine also.

@keyframes flexb{
    0%{transform: translateY(-50px);}
    100%{transform: translateY(0px);}

}
2 Likes