Skip to content

Instantly share code, notes, and snippets.

@matt-daniel-brown
Created December 13, 2019 10:16
Show Gist options
  • Save matt-daniel-brown/3745668d55ff3a121e1972e25aed84e7 to your computer and use it in GitHub Desktop.
Save matt-daniel-brown/3745668d55ff3a121e1972e25aed84e7 to your computer and use it in GitHub Desktop.
(Togglable) Animated Hamburger Menu Icon (Best of my attempts so far)
<button role="button" type="button" class="menu-button" id="menu-button">
<span class="menu-button-text">Menu</span>
</button>
"use strict";
const menuButton = document.getElementById("menu-button");
menuButton.addEventListener("click", function(event) {
if (this.classList.contains("open")) {
this.classList.remove("open");
} else {
this.classList.add("open");
}
});
/* The only code that's relevant is/are the
following mixin(s)/function(s),
top-level variable(s),
and the `.menu-button` class. */
$menu-button-color : white !default;
$menu-button-line-weight : 2px !default;
@function threeTimes($_num) { @return (3 * $_num); }
@function halfOf($_num) {@return (0.5 * $_num); }
@function calculateMenuLineMargin() {
$_line-height: $menu-button-line-weight;
@return ($_line-height * 4);
}
@function calculateMenuMiddleLineOffset() {
$_line-height: $menu-button-line-weight;
$_threeTimesLineheight: threeTimes($_line-height);
$_halfThreeTimesLineHeight: halfOf($_threeTimesLineheight);
@return ($_line-height * 2.5);
// @return 10px;
}
@function calculatedSize() {
@return ($menu-button-line-weight * 12);
}
%buttonReset {
appearance : none !important;
border : none !important;
outline : none !important;
user-select : none !important;
cursor : pointer !important;
vertical-align : middle;
background : transparent;
line-height : 1;
}
@mixin menuButton(
$_color : white,
$_bg : transparent,
$_border : none,
$_showText : false,
$_txtColor : white
) {
// TRUE : display as text-only button that just says "Menu"
// FALSE : hide text content;'draw' the `hamburger menu` icon
@if ($_showText == true) {
//----------------------------
// ... so just display text
//----------------------------
background: $_bg;
color: $_txtColor;
border: $_border;
span.menu-button-text {
display: block;
color: $txtColor;
}
}
/* and now the 'hambur... menu' icon 'drawing' happens */
@else {
//----------------------------
// ... hide text & draw icon
//----------------------------
//------------------------------------------------------------
// RESET (BECAUSE IT'S STYLING IS UNLIKE ALL OTHER BUTTONS)
//------------------------------------------------------------
@extend %buttonReset;
//-------------------------------------------------------------
// Shared styles amongst all states and contents
//-------------------------------------------------------------
display: block;
width: 48px !important;
height: 48px !important;
// width: calculatedSize();
// height: calculatedSize();
// padding: 0 !important;
transform: scale3d(1,1,1);
transition: all 80ms;
// display: flex;
// flex-direction: column;
// align-content: stretch;
// align-items: stretch;
// justify-content: space-around ;
//------------------------------------------
// TRICKS TO DRAW 3 BARS OF 'HAMB...' ICON
//------------------------------------------
&:before,&:after {
background-color: #fff;
content: "";
display: block;
// height: $menu-button-line-weight; // Default is : ( height: 4px; )
height: 4px;
transition: all 80ms ease-in-out;
// margin: 0 !important;
// padding: 0 !important;
}
&:before {
box-shadow: 0 10px 0 #fff;
// $_box-shadow-y: calculateMenuMiddleLineOffset();
// box-shadow: 0 $_box-shadow-y 0 #fff;
// margin-bottom: calculateMenuLineMargin(); // using Default values...
// result == (margin-bottom: 16px;)
margin-bottom: 16px;
// margin: 0 !important;
}
//------------------------------------------
// HIDING/SHOWING THE TEXT-ONLY VERSION
//------------------------------------------
.menu-button-text {
display: none;
}
//------------------------------------------
// INTERACTION STATES (hover,focus,active)
//------------------------------------------
&:hover {
opacity: 0.75 !important;
}
&:focus {
$_focus-color: lighten(mediumslateblue, 18%);
box-shadow: 0 0 0 3px rgba(mediumslateblue, 0.125);
border-radius: 4px;
//
// @NOTE:
// The following would color the bars and/or button background
// a faint blue-ish color when focused. Might be helpful in other,
// different, but still similar style/design situations...
// so that's why it's commented out but still here.
//
// background: rgba(mediumslateblue, 0.05) !important;
// &:before, &:after { background: $_focus-color !important;}
// Set box-shadow so UN-TOGGLED menu state can have highlighted middle bar
// &:before { box-shadow: 0 10px 0 $_focus-color; }
}
&:active {
opacity: 0.125 !important;
transform: scale3d(0.9, 0.9, 0.9);
}
///////////////////////////////////////////////////////
// CLICKED & TOGGLED (OPENED/CLOSED) HAMBURGER STATE //
///////////////////////////////////////////////////////
&.open {
// ==========================================================
// Set box shadow to NOTHING to 'hide' the middle bar
// ==========================================================
&:before {
box-shadow: none;
transform: translateY(10px) rotate(45deg);
}
&:after { transform: translateY(-10px) rotate(-45deg); }
//----------------------------------------------------
// ^^ and of course, rotate the 'bars' that are drawn
// on :before & :after equally, but in opposite
// directions to create `X` shape...
// (This is done in the two selectors above)
//----------------------------------------------------
}
}
}
/* ... and is finally applied to a
style/selector/element etc here */
.menu-button {
// AS LONG AS IT'S NOT TEXT ONLY....
&:not(.text-only),
&:not(.text-menu-button),
&:not(.show-text-content) {
// reset/unset button styles...
@extend %buttonReset;
// create hamburger menu icon button (with default values)
@include menuButton();
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* EVERYTHING ELSE IS JUST FOR DEMONSTRATION/DEV PURPOSES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// (class attached to <body> in CodePen's editor settings)
.demo-presentation {
background-color: #333 !important;
width: 100vw !important;
height: 100vh !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
align-content: center !important;
justify-content: center !important;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/modern-normalize/0.5.0/modern-normalize.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment