CSS animation discussion

I have a hamburger menu for small port media queries.

Initially, its display is hidden. when JS injects a clicked function the CSS transitions:

body.clicked .hide {
 display: block;
}

before click, I have put an animation + keyframe, but that doesn’t works:

.hide {
  display: none;
  position: sticky;
  top: 0px;
  animation-name: headeranimate;
  animation-duration: 1s;
}
@keyframes headeranimate {
    0%   { left:-100px;}
    100% { left:0;}
}

I want a smooth appearance of what was hidden? Animation doesn’t work is there any fundamental flaw in my approach of applying animation?

The approach works fine. My guess is that body.clicked .hide is not targeting the element properly?

Below is an example I spun up for you showing how this works. Start the page, then hover over the window to kick off the animation

Hope this helps! :slight_smile:

2 Likes

Shouldn’t the animation be applied in that rule above and not when its hidden? Otherwise it has run when you can’t see it.

1 Like

Sir, the modification that you are suggesting I already tried that I have re-modified the code and uploaded it on the live server, but still it didnt show that smooth animation appearing as if coming from left.

I don’t see any element with a class of .hide in there but then I’m not sure what you are attempting exactly:)

The clicked class only gets added when you click the hamburger but the hamburger is already in view. What do you want to happen when clicked?

1 Like

when sir hamburger is clicked, the elements that comes after that click: newsletter form, for example etc, should come animated. currently they are coming as if they are shoting by appearing immediately.

This section hold them:

<section class="hide mobilemenu">

Ah ok :slight_smile:

You are not animating anything. :slight_smile: You animate the left position but there is no left position for a static element (only for positioned elements).

You could instead just transform it.


	body.clicked .hide {
		display: block;
		
		animation-name: headeranimate;
		animation-duration: 1s;
	}

	@keyframes headeranimate {
		0%   { transform:translateX(-100%)}
		100% { transform:translateX(0%)}
	}
1 Like

Although I got it, but for sake of remembering in futuring I am summarizing my understanding.

  1. We used position:sticky here so left, right, bottom, and top doesnt works as they are reserved for position absolute, fixed and relative.
  2. Thats the reason the animation was not working.
  3. As a remedy we used translate function, which can translates object across X, Y or Z axis.

You don’t have position:sticky on the mobile menu. You have position:fixed on the sidebar but you don’t slide that. I’m not sure why you are duplicating the sidebar content anyway when you could just show and hide the sidebar as required?

As far as co-ordinates on a stick element then they don’t move the element at all but indicate a position where it becomes sticky inside a scrollable container. The co-ordinates will do nothing if scrolling hasn’t caused those co-ordinates to be active. there’s no point trying to animate the co-ordinates.

Indeed for all animation you should avoid using top.left,right and bottom with position and use transforms instead as they are much smoother and less intensive for the browser because they don’t cause reflow and are hardware accelerated.:slight_smile:

Also if you want to animate the panel when you hide it then you will need to use another method instead of display:none. Display:none happens instantly so you can’t animate anything.

You could instead hide it with a transform left of -100vw which would ensure it was hidden off screen but you would need to make it position:absolute so it takes up no space.

e.g. Very roughly.

.mobilemenu {
  display: block !important;
  position: absolute;
  transform: translateX(-100vw);
  animation: headeranimate2 1s forwards;
}

@keyframes headeranimate2 {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-100vw);
  }
}

.clicked .mobilemenu {
  animation: headeranimate 1s forwards;
}

@keyframes headeranimate {
  0% {
    transform: translateX(-100vw);
  }
  100% {
    transform: translateX(0);
  }
}
1 Like

Agree. Design is bogus. I created this HTML 1.5 years back since then the skills and code organization have improved. I tried to minimize redundancy today, and then a bit succeded.

I have deleted the repetition ↓

<div class="wrapper wrapper2">
	<section class="mobsidebar">
		<div class="mobheader-top">
      <div class="header-top">
	      <picture class="picture">
	        <img src="https://html.trafficopedia.com/producthtml/blogppr/img/warrenbuffet.png" alt="">
	      </picture>
      </div>
			<div class="hamburger">
				<div class="top"></div>
				<div class="middle"></div>
				<div class="bottom"></div>
			</div>
		</div>    		
	</section>
	<section class="hide mobilemenu">
		<div>
      <form class="tform">
        <div class="tinput">
        	<input class="email-search-box" name="q" size="40" type="text" placeholder="Search"/><input class="email-search-btn" value="Search" type="submit"/>
        </div>
      </form>
      <form class="tform">
        <div class="tinput">
        	<input class="email-search-box email-search-box-2" name="q" size="40" type="text" placeholder="Enter Email"/><input class="email-search-btn email-search-btn-2"  value="Submit" type="submit"/>
        </div>
      </form>
      <div class="menu">
        <h6>Header</h6>
        <ul>
          <li><a href="">Javascript</a></li>
          <li><a href="">Hiring Manager</a></li>
          <li><a href="">Temptational Flux</a></li>
          <li><a href="">Mood Swings</a></li>
          <li><a href="">Jump Suit</a></li>
          <li><a href="">Yes Boss</a></li>
        </ul>
      </div>
      <div class="menu">
        <h6>Header</h6>
        <ul>
          <li><a href="">Javascript</a></li>
          <li><a href="">Hiring Manager</a></li>
          <li><a href="">Temptational Flux</a></li>
          <li><a href="">Mood Swings</a></li>
          <li><a href="">Jump Suit</a></li>
          <li><a href="">Yes Boss</a></li>
        </ul>
      </div>
      <div class="menu">
        <h6>Header</h6>
        <ul>
          <li><a href="">Javascript</a></li>
          <li><a href="">Hiring Manager</a></li>
          <li><a href="">Temptational Flux</a></li>
          <li><a href="">Mood Swings</a></li>
          <li><a href="">Jump Suit</a></li>
          <li><a href="">Yes Boss</a></li>
        </ul>
      </div>
    </div>
	</section>
</div>

Moving forward,

I also managed to change the HTML structure. All those sidebars menus, search, and email newsletter forms I have added inside a new div →

And out the hide class there. since the mobilemenu class was no needed as the whole separate section is removed now.

I am facing challenges when trying to animate. I have uploaded the live code here:

The CSS is:

.hide {
	  display: block;
		position: absolute;
		transform: translateX(-100vw);
		animation: headeranimate2 1s forwards;
	}

	@keyframes headeranimate2 {
	  0% {transform: translateX(0);}
	  100% {transform: translateX(-100vw);}
	}

	body.clicked .hide {
		display: block;
		animation-name: headeranimate;
		animation-duration: 1s;
	}

	@keyframes headeranimate {
		0%   { transform:translateX(100%)}
		100% { transform:translateX(0%)}
	}

As you said position absolute is essential else it will create a gap, currently, I have applied position: absolute, but it is creating a poor experience only search input comes in animating, excluding all other things.

Issue: I think position absolute is creating a small vertical scroll bar.

Have a play with something like this.

@media only screen and (max-width: 700px) {
  .sidebar {
    position: static;
  }
  .hide {
    top: 80px;/* magic number alert*/
    bottom: auto;
    display: block;
    position: absolute;
    transform: translateX(-100vw);
    animation: headeranimate2 1s forwards;
    background: rgba(255, 255, 255, 0.7);
  }
}
1 Like

Hi there, why did you call it a magic alert? You were able to get this number through a prudent analysis or is that something really magical in CSS?

One last problem with the animation is that when you refresh on a mobile screen, w/o click it animates partially.

	@keyframes headeranimate2 {
	  0% {transform: translateX(0);}
	  100% {transform: translateX(-100vw);}
	}

	body.clicked .hide {
		display: block;
		animation-name: headeranimate;
		animation-duration: 1s;
	}

	@keyframes headeranimate {
		0%   { transform:translateX(100%)}
		100% { transform:translateX(0%)}
	}

It’s a magic number because it only works if the header above it is less than 80px. If you were to change the size of the header then that 80px is not longer working. You want to avoid the use of magic numbers where possible so that they are automatic and not rely on something else to be the size you thought it was.

As there is only an image above your menu then its probably not an issue but generally I would avoid doing this and redesign to an automatic system even if it means changing the design a bit.

Yes the Keyframe will run when refreshed. I don’t think you actually need a keyframe animation here anyway and a transition should suffice.

e.g.Here’s a broken down version of your menu just to test the principal.

If you can still see the transition on refresh then another method is to wrap a div around the mobile menu and push that off to the side without animation. Then you can use the clicked class to remove that rule and let the original animation take place.

However I think the transition method should work unless you have a very quick page where it may be noticeable on load.

Just test and see :slight_smile:

2 Likes

Actually the transition method above will work because if you refresh the page the media query has already moved the element to the side so in fact there is no transition to be made. It never was anywhere else. When you click it then it is moved and the transition will occur in both directions. No keyframes needed at all.:slight_smile:

The menu will transition slide to the side when you resize the desktop browser from larger to smaller but I see that as a good thing as it tells you where something has gone rather than it vanishing instantly like a magic trick.

2 Likes

Thank you so much for giving additional insight, yet I am confused should I delete all these keyframes →

Why not try it and see what happens? Then tell us what you see (or don’t see).

I got the point it works.

2 Likes

I assume you have it working in your code now?

If you are stuck then post your updated code and we will see where you are going wrong. :slight_smile:

2 Likes

Hi there, Its working, but I have few doubts sir.

Part 1:
In its static state we have put a css on .hide classs →

transform: translateX(-100vw);
transition: transform 1s ease;

No issues. we have translated it to -ve X axis.

Part 2. Now the hamburger is clicked, and now this is activated →

body.clicked .hide {
	display: block;
	/*animation-name: headeranimate;*/
	/*animation-duration: 1s;*/
	transform: translateX(0);
}

My doubt is since we have put this part(transition: transform 1s ease;) in .hide class how is the animation working here: transition: transform 1s ease; (This is in .hide class)

Part 3 is ok when we click it again the clicked calss is eleimiated and this comes into picture →

transform: translateX(-100vw);
transition: transform 1s ease;

The transition is present from the start on the hide class and is never modified. It will always be in effect unless you change it.

The clicked class merely modified the transform position of the hide class. The transition is already applied and needs no further mention.

1 Like