A Pen by Matthew Daniel Brown on CodePen.
Created
December 13, 2019 10:16
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<button role="button" type="button" class="menu-button" id="menu-button"> | |
<span class="menu-button-text">Menu</span> | |
</button> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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"); | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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