Issue
I'm attempting to develop a burger menu > minimalist arrow animation for mobile pages using exclusively CSS and HTML as I'm trying to get better at using CSS. I'm using keyframes to animate and a checkbox input to trigger animations. I've got the burger to turn into the arrow on click but I can't figure out how to animate it from the arrow back into the burger when the checkbox is unchecked. The HTML and CSS can be found below:
html,
body {
padding: 0;
margin: 0;
height: 100%;
}
.container {
margin-top: 10px;
margin-left: 10px;
width: 660px;
height: 660px;
background: black;
display: flex;
flex-direction: column;
cursor: pointer;
}
.burger-input {
opacity: 0;
visibility: hidden;
z-index: 1;
display: none;
}
.bar {
height: 33.333%;
width: 100%;
display: flex;
flex-direction: column;
justify-self: center;
align-self: center;
justify-content: center;
}
.bar-child {
background-color: aqua;
align-self: center;
width: 90%;
height: 55%;
}
.burger-input:checked+.burger-label .bar-child {
transition: border-radius 0.4s ease-in-out 0.4s;
border-radius: 250px;
}
.burger-input:checked+.burger-label .bar:nth-child(1) {
align-self: end;
animation: width20 0.4s ease-in 0s 1 normal forwards, centerBurger 0.4s linear 0.4s 1 normal forwards;
}
.burger-input:checked+.burger-label .bar:nth-child(2) {
align-self: start;
animation: width20 0.4s ease-in 0s 1 normal forwards, leftArrowHead 0.4s ease-in-out 0.8s 1 normal forwards;
}
.burger-input:checked+.burger-label .bar:nth-child(3) {
align-self: end;
animation: width20 0.4s ease-in 0s 1 normal forwards, moveBurgerUp 0.4s linear 0.4s 1 normal forwards, rightArrowHead 0.4s ease-in-out 0.8s 1 normal forwards;
}
@keyframes leftArrowHead {
0% {
transform: rotate(-30deg);
}
100% {
transform: translateY(-46%) rotate(-50deg);
width: 70%;
}
}
@keyframes rightArrowHead {
0% {
transform: translateY(-100%) rotate(30deg);
}
100% {
transform: translateY(-146%) rotate(50deg);
width: 70%;
}
}
@keyframes moveBurgerUp {
from {}
to {
transform: translateY(-100%);
}
}
@keyframes centerBurger {
from {}
to {
transform: translateX(calc(-330px + 50%));
}
}
@keyframes width20 {
from {
width: 90%;
}
to {
width: 20%;
}
}
<div class="burger-btn-body">
<input type="checkbox" class="burger-input" id="burger-input">
<label for="burger-input" class="burger-label">
<div class="container">
<div class="bar">
<div class="bar-child" id="bar-child1"></div>
</div>
<div class="bar">
<div class="bar-child" id="bar-child2"></div>
</div>
<div class="bar">
<div class="bar-child" id="bar-child3"></div>
</div>
</div>
</label>
</div>
I'm willing to swap to SCSS if necessary but I'd really like to not use any JavaScript code as I feel it would defeat the purpose of this exercise for me. I believe this comment may have solved my problem with it using SCSS but is this possible in pure CSS?
I've tried just applying a standard reverse on the animations as they were
.burger-input:not(:checked) + .burger-label .bar:nth-child(2) {
align-self: start;
animation:
width20 0.4s ease-in 0.8s 1 normal reverse,
leftArrowHead 0.4s ease-in-out 0s 1 normal reverse;
}
I've also tried using transitions on unchecked as per this answer
.burger-input:not(:checked) + .burger-label .bar:nth-child(1) {
align-self: end;
transition: transform 0.4s linear 0s;
transform: translateX(calc(330px - 50%));
}
I've also tried new custom animations for the reverse mode
.burger-input:not(:checked) + .burger-label .bar:nth-child(1) {
align-self: end;
animation:
width20 0.4s ease-in 0.4s 1 normal reverse,
centerBurgerReverse 0.4s linear 0s 1 normal forwards;
}
@keyframes centerBurgerReverse {
from{
}
to{
transform: translateX(calc(330px - 50%));
}
}
Solution
The problem was the timing used on the animation CSS property.
.burger-input:not(:checked) + .burger-label .bar:nth-child(1) {
align-self: end;
animation:
width20 0.4s ease-in 0.4s 1 normal reverse,
centerBurgerReverse 0.4s linear 0s 1 normal forwards;
}
The above code doesn't work because the delay for width20 is longer than the delay on centerBurgerReverse. The code should be:
.burger-input:not(:checked) + .burger-label .bar:nth-child(1) {
align-self: end;
animation:
centerBurgerReverse 0.4s linear 0s 1 normal forwards,
width20 0.4s ease-in 0.4s 1 normal reverse;
}
The full code (in SCSS as it was pointed out that it compiles to CSS anyway) is as follows:
html,
body {
padding: 0;
margin: 0;
height: 100%;
}
.container{
margin-top: 10px;
margin-left: 10px;
width: 660px;
height: 660px;
background: black;
display: flex;
flex-direction: column;
cursor: pointer;
}
.burger-input{
opacity: 0;
visibility: hidden;
z-index: 1;
display: none;
}
.bar{
height: 33.333%;
width: 100%;
display: flex;
flex-direction: column;
justify-self: center;
justify-content: center;
}
.bar-child{
background-color: aqua;
justify-self: center;
width: 100%;
height: 60%;
}
.burger-input{
&:not(:checked) + .burger-label {
& .bar-child{
transition: border-radius 0.4s ease-in-out 0.5s;
border-radius: 25px;
}
& .bar{
&:nth-child(1) {
align-self: end;
animation:
width20Reverse 0.4s ease-in 0s 1 normal forwards,centerBurgerReverse 0.4s linear 0s 1 normal forwards;
}
&:nth-child(2) {
align-self: start;
animation:
leftArrowHeadReverse 0.4s ease-in-out 0s 1 normal forwards,width20Reverse 0.4s ease-in 0.8s 1 normal forwards;
}
&:nth-child(3) {
align-self: end;
animation:
rightArrowHeadReverse 0.4s ease-in-out 0s 1 normal forwards, moveBurgerUpReverse 0.4s linear 0.4s 1 normal forwards, width20Reverse 0.4s ease-in 0.8s 1 normal forwards;
}
}
}
&:checked + .burger-label {
& .bar-child{
transition: border-radius 0.4s ease-in-out 0.4s;
border-radius: 250px;
}
& .bar{
&:nth-child(1) {
align-self: end;
animation:
width20 0.4s ease-in 0s 1 normal forwards,centerBurger 0.4s linear 0.4s 1 normal forwards;
}
&:nth-child(2) {
align-self: start;
animation:
width20 0.4s ease-in 0s 1 normal forwards,leftArrowHead 0.4s ease-in-out 0.8s 1 normal forwards;
}
&:nth-child(3) {
align-self: end;
animation:
width20 0.4s ease-in 0s 1 normal forwards,moveBurgerUp 0.4s linear 0.4s 1 normal forwards,rightArrowHead 0.4s ease-in-out 0.8s 1 normal forwards;
}
}
}
}
@keyframes leftArrowHead {
0%{
transform: rotate(0deg);
}
100%{
transform: translateY(-46%) rotate(-50deg);
width: 68%;
}
}
@keyframes rightArrowHead {
0%{
transform: translateY(-100%) rotate(30deg);
}
100%{
transform: translateY(-146%) rotate(50deg);
width: 68%;
}
}
@keyframes moveBurgerUp {
from{
}
to{
transform: translateY(-100%);
}
}
@keyframes centerBurger {
from{
}
to{
transform: translateX(calc(-330px + 50%));
}
}
@keyframes width20 {
from {
width: 90%;
}
to {
width: 20%;
}
}
/* Reverse animations when unchecked */
@keyframes leftArrowHeadReverse {
0%{
transform: translateY(-46%) rotate(-50deg);
width: 70%;
}
100%{
transform: rotate(0deg);
width: 20%;
}
}
@keyframes rightArrowHeadReverse {
0%{
transform: translateY(-146%) rotate(50deg);
width: 70%;
}
100%{
transform: translateY(-100%) rotate(0deg);
width: 20%;
}
}
@keyframes moveBurgerUpReverse {
from{
transform: translateY(-100%);
}
to{
transform: translateY(0%);
}
}
@keyframes centerBurgerReverse {
from{
transform: translateX(calc(-330px + 50%));
}
to{
transform: translateX(calc(330px - 50%));
}
}
@keyframes width20Reverse {
from {
width: 20%;
}
to {
width: 100%;
}
}
This code is messy but can be neatened up as needed
Answered By - Garry
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.