1

I try to make a smooth transition for my hamburger menu, but I don't find solution to do it... I'm not really fluid with the CSS and it's very difficult to find a good example on the web or a good tutorial to explain the process. below my code, I hope it's enough simple to understand my problem.

a link to the project https://github.com/StanLepunK/cafe366/blob/stan/src/components/menu/menu_small.js

export const MenuSmallImpl = () => {
  let res = Get_window();
  const [width, set_width] = useState(res[0]/2);
  const [open, set_open] = useState(false);

  const toggleMenu = () => {
    set_open(!open);
  }

  return (
    <Fragment>
      <div className={nav_bar}>
        <button
          onClick={() => toggleMenu()}
          className={toggle_menu}
        >
          <div className={hamburger_container}>
            <div className={hamburger}>
              <div className={[burger, "burger1"].join(" ")} />
              <div className={[burger, "burger2"].join(" ")} />
              <div className={[burger, "burger3"].join(" ")} />
            </div>
            <style>{`
              .burger1 {
                  transform: ${ open ? 'rotate(45deg)' : 'rotate(0)'};
              }
              .burger2 {
                  opacity: ${ open ? 0 : 1};
              }
              .burger3 {
                  transform: ${ open ? 'rotate(-45deg)' : 'rotate(0)'};
              }
            `}</style> 
          </div>
        </button>
        <div>{open ? <div className={show}><MenuContent /></div> : <div className={hidden}><MenuContent /></div> }</div>
      </div>
    </Fragment>
  )
}
.nav_bar {
  text-align: center;
  border-radius: 0;
  background-color: rgb(var(--orange_366_rgb));
  transition: height 3s ease;
}

.nav_bar .show {
  height: 100%;
  overflow: visible;
}

.nav_bar .hidden {
  height: 0;
  overflow: hidden;
}

.nav_bar:active {
  height: 100%;
  overflow: visible;
}

.toggle_menu {
  height: 50px;
  width: 50px;
  z-index: 1;
}

.hamburger_container {
  display: flex;
  justify-content: center;
  align-items: center;

}
.hamburger{
  width: 2rem;
  height: 2rem;
  display: flex;
  justify-content: space-around;
  flex-flow: column nowrap;
}

.burger{
  width: 2rem;
  height: 2px;
  border-radius: 2px;
  background-color: rgb(var(--lin_rgb));
  transform-origin: 1px;
  transition: all 0.3s linear;
}

CODE IMPROVED on the advice John Ruddell, but it's not enough, that's work but not totally only for the text not for the frame. See here use a small window to see the hamburger menu https://cafe366stan.gatsbyjs.io/ I don't understand why the text move and not the frame...

my new code

JS

import React, { useState, Fragment } from "react"
// CAFÉ 366
import MenuContent from "./menu_content"
import {  nav_bar, toggle_menu, content_menu_small, 
          hamburger, burger, hamburger_container,
          show, hidden } from "./menu_small.module.css";
// UTILS
import { Get_window } from "../../utils/canvas"

export const MenuSmallImpl = () => {
  const [open, set_open] = useState(false);

  const toggleMenu = () => {
    set_open(!open);
  }

  return (
    <Fragment>
      <div style={{textAlign:`center`}}>
        <button
          onClick={() => toggleMenu()}
          className={toggle_menu}
        >
          <div className={hamburger_container}>
            <div className={hamburger}>
              <div className={[burger, "burger1"].join(" ")} />
              <div className={[burger, "burger2"].join(" ")} />
              <div className={[burger, "burger3"].join(" ")} />
            </div>
            <style>{`
              .burger1 {
                  transform: ${ open ? 'rotate(45deg)' : 'rotate(0)'};
              }
              .burger2 {
                  opacity: ${ open ? 0 : 1};
              }
              .burger3 {
                  transform: ${ open ? 'rotate(-45deg)' : 'rotate(0)'};
              }
            `}</style> 
          </div>
        </button>
      </div>
      <div className={[nav_bar, "move"].join(" ")}>
        {/* <div>{open ? <div className={show}><MenuContent /></div> : <div className={hidden}><MenuContent /></div> }</div> */}
        <MenuContent />
      </div>
      <style>{`
          .move {
            transform: ${open ? 'translatey(0)' : 'translatey(-400px)'};
          }
        `}</style> 
    </Fragment>
  )
}

export default function MenuSmall() {
  return (
    <MenuSmallImpl/>  
  )
}

CSS

.nav_bar {
  height: 0%;
  text-align: center;
  border-radius: 0;
  background-color: rgb(var(--orange_366_rgb));
  transition: 1s ease;
  /* border-right: 1px solid; */
}

.nav_bar .show {
  height: 100%;
  overflow: visible;
}

.nav_bar .hidden {
  height: 0;
  overflow: hidden;
}

.nav_bar:active {
  height: 100%;
  overflow: visible;
}

.toggle_menu {
  height: 50px;
  width: 50px;
  z-index: 1;
  /* border: solid 1px white; */
}

.hamburger_container {
  display: flex;
  justify-content: center;
  align-items: center;

}
.hamburger{
  width: 2rem;
  height: 2rem;
  display: flex;
  justify-content: space-around;
  flex-flow: column nowrap;
  /* border: solid 1px white; */
}
.burger{
  width: 2rem;
  height: 2px;
  border-radius: 2px;
  background-color: rgb(var(--lin_rgb));
  transform-origin: 1px;
  transition: all 0.3s linear;
}

and two screenshots to understand my goal enter image description here

now when it's deploy

enter image description here

Knupel
  • 323
  • 2
  • 14
  • Changing heights will not produce a smooth animation as the content inside will bump around with the changing heights. It is better to use `transform: translate()` to move the menu, this will produce no height changes and thus a smoother transition. Also translation animations are much more performant because the browser doesn't have to repaint on each tick like it would with a height change – John Ruddell Feb 02 '22 at 21:52
  • opacity and transform are both easily animate-able / transition-able so you can add easings and different timings. You should also try adding a scale `transform: scale()` from 0 to 1 to go along with your opacity of 0 to 1. – John Ruddell Feb 02 '22 at 21:58
  • @JohnRuddell ok thanks for the advice about the best use of `translate()` instead hidden or visible. But with this solution I've problem because I don't know in advance the height of the menu. you know if it's possible to catch the height of component ? in me case ``or if I must use `Context` to do that ? – Knupel Feb 03 '22 at 11:31
  • translation can take a percentage value so if you wanted to move something its entire size you could do that. `transform: translate(0, -100%)` for instance would move something its full size upwards (vertically). I don't really understand what kind of transition / animation you're trying to accomplish so its hard to know what advice to give – John Ruddell Feb 05 '22 at 04:13
  • I updated the question here, because I move a lot the code https://stackoverflow.com/questions/70996389/hide-component-with-transition – Knupel Feb 05 '22 at 08:33

0 Answers0