<!--
Animenu
-------
https://github.com/catalinred/animenu
https://twitter.com/catalinred
-->
<nav class="animenu" role="navigation" aria-label="Menu">
<button class="animenu__btn" type="button">
<span class="animenu__btn__bar"></span>
<span class="animenu__btn__bar"></span>
<span class="animenu__btn__bar"></span>
</button>
<ul class="animenu__nav">
<li><a href="#">Home</a></li>
<li>
<a href="#" class="animenu__nav__hasDropdown" aria-haspopup="true">Archive</a>
<ul class="animenu__nav__dropdown" aria-label="submenu" role="menu">
<li><a href="#" role="menuitem">Sub Item 1</a></li>
<li><a href="#" role="menuitem">Sub Item 2</a></li>
<li><a href="#" role="menuitem">Sub Item 3</a></li>
</ul>
</li>
<li>
<a href="#" class="animenu__nav__hasDropdown" aria-haspopup="true">Categories</a>
<ul class="animenu__nav__dropdown" aria-label="submenu" role="menu">
<li><a href="#" role="menuitem">Sub Item 1</a></li>
<li><a href="#" role="menuitem">Sub Item 2</a></li>
<li><a href="#" role="menuitem">Sub Item 3</a></li>
</ul>
</li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
// Animenu
// -------
// https://github.com/catalinred/animenu
// https://twitter.com/catalinred
// Variables
$baseMenuBackground: #111; // Base color theme
$secondaryMenuBackground: #0186ba; // Secondary color (highlights, triangles...)
$gutter: 10px; // Base gutter
// Latest CSS box model
*, *:after, *:before {
box-sizing: border-box;
}
// The classic hamburger icon
// <button class="animenu__btn">
// <span class="animenu__btn__bar"></span>
// <span class="animenu__btn__bar"></span>
// <span class="animenu__btn__bar"></span>
// </button>
.animenu__btn {
display: none;
cursor: pointer;
background-color: $baseMenuBackground;
border: 0;
padding: 10px;
height: 40px;
width: 40px;
&:hover {
background-color: $secondaryMenuBackground;
}
}
.animenu__btn__bar {
display: block;
width: 20px; height: 2px;
background-color: #fff;
transition: .15s cubic-bezier(0.75, -0.55, 0.25, 1.55);
&+.animenu__btn__bar {
margin-top: 4px;
}
}
.animenu__btn--active {
.animenu__btn__bar {
margin: 0;
position: absolute;
&:nth-child(1) {
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:nth-child(3) {
transform: rotate(-45deg);
}
}
}
// Clear some defaults
.animenu {
display: block;
ul {
padding: 0;
list-style: none;
font: 0 -apple-system,
BlinkMacSystemFont,
"Segoe UI",
"Roboto",
"Helvetica Neue", Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
li, a {
display: inline-block;
font-size: 15px;
}
a {
color: lighten($baseMenuBackground, 60%);
text-decoration: none;
}
}
// First level -> main menu items
// <nav class="animenu">
// <ul class="animenu__nav">
// ...
// </ul>
// </nav>
.animenu__nav {
background-color: $baseMenuBackground;
> li {
position: relative;
border-right: 1px solid lighten($baseMenuBackground, 20%);
> a {
padding: $gutter 3 * $gutter;
text-transform: uppercase;
}
&:hover {
> ul {
opacity: 1;
visibility: visible;
margin: 0;
}
> a {
color: #fff;
}
}
// Duplicate stuff due to
// https://www.w3.org/TR/2018/PR-selectors-3-20180911/#grouping
&:focus-within {
> ul {
opacity: 1;
visibility: visible;
margin: 0;
}
> a {
color: #fff;
}
}
}
&__hasDropdown:before {
content:"";
position: absolute;
border: 4px solid transparent;
border-bottom: 0;
border-top-color: currentColor;
top: 50%;
margin-top: -2px;
right: 10px;
}
}
// Second level
// <nav class="animenu">
// <ul class="animenu__nav">
// <li>
// <ul class="animenu__nav__dropdown"></ul>
// </li>
// </ul>
// </nav>
.animenu__nav__dropdown {
min-width: 100%;
position: absolute;
top: 100%; left: 0;
z-index: 1;
opacity: 0;
visibility: hidden;
margin: 2 * $gutter 0 0 0;
background-color: lighten($baseMenuBackground, 15%);
transition: margin .15s, opacity .15s;
> li {
width: 100%;
border-bottom: 1px solid lighten($baseMenuBackground, 25%);
&:first-child > a:after {
content: '';
position: absolute;
height: 0; width: 0;
left: 1em;
top: -6px;
border: 6px solid transparent;
border-top: 0;
border-bottom-color: inherit;
}
&:last-child {
border: 0;
}
}
a {
padding: $gutter;
width: 100%;
border-color: lighten($baseMenuBackground, 15%);
&:hover {
background-color: $secondaryMenuBackground;
border-color: $secondaryMenuBackground;
color: #fff;
}
// Duplicate stuff due to
// https://www.w3.org/TR/2018/PR-selectors-3-20180911/#grouping
&:focus-within {
background-color: $secondaryMenuBackground;
border-color: $secondaryMenuBackground;
color: #fff;
}
}
}
// The main breakpoint is 767px
// Adjust the first and second levels display
@media screen and (max-width: 767px) {
.animenu__btn {
display: inline-block;
}
.animenu__nav,
.animenu__nav__dropdown {
display: none;
}
// First level -> main menu items
// <nav class="animenu">
// <ul class="animenu__nav">
// ...
// </ul>
// </nav>
.animenu__nav {
margin: $gutter 0;
> li {
width: 100%;
border-right: 0;
border-bottom: 1px solid lighten($baseMenuBackground, 25%);
&:last-child {
border: 0;
}
&:first-child > a:after {
content: '';
position: absolute;
height: 0; width: 0;
left: 1em;
top: -6px;
border: 6px solid transparent;
border-top: 0;
border-bottom-color: inherit;
}
> a {
width: 100%;
padding: $gutter;
border-color: $baseMenuBackground;
position: relative; //dropdown caret
}
}
a:hover {
background-color: $secondaryMenuBackground;
border-color: $secondaryMenuBackground;
color: #fff;
}
}
// Second level
// <nav class="animenu">
// <ul class="animenu__nav">
// <li>
// <ul class="animenu__nav__dropdown"></ul>
// </li>
// </ul>
// </nav>
.animenu__nav__dropdown {
position: static;
background-color: lighten($baseMenuBackground, 15%);
margin: 0;
transition: none;
visibility: visible;
opacity: 1;
> li:first-child > a:after {
content: none;
}
a {
padding-left: 2 * $gutter;
width: 100%;
}
}
}
// Expanding the animenu
// <nav class="animenu">
// <ul class="animenu__nav animenu__nav--active">
// <li>
// <ul class="animenu__nav__dropdown"></ul>
// </li>
// </ul>
// </nav>
.animenu__nav--active {
display: block !important;
& .animenu__nav__dropdown {
display: block;
}
}
View Compiled
// Animenu
// -------
// https://github.com/catalinred/animenu
// https://twitter.com/catalinred
// ES6
// a.k.a unicorns everywhere 🙂
(() => {
let $ = el => document.querySelector(el);
$(".animenu__btn").addEventListener("click", function(){
this.classList.toggle("animenu__btn--active")
$(".animenu__nav").classList.toggle("animenu__nav--active")
});
})()
// ---
// IE 10
// https://caniuse.com/#search=classlist
// (function(){
// var $ = function(el) {
// return document.querySelector(el);
// }
// $('.animenu__btn').addEventListener('click', function() {
// this.classList.toggle("animenu__btn--active")
// $('.animenu__nav').classList.toggle("animenu__nav--active")
// });
// })();
// ---
// IE9 / IE8
// https://caniuse.com/#search=querySelector
// (function(){
// var animenuToggle = document.querySelector('.animenu__btn'),
// animenuNav = document.querySelector('.animenu__nav'),
// hasClass = function( elem, className ) {
// return new RegExp( ' ' + className + ' ' ).test( ' ' + elem.className + ' ' );
// },
// toggleClass = function( elem, className ) {
// var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ' ) + ' ';
// if( hasClass(elem, className ) ) {
// while( newClass.indexOf( ' ' + className + ' ' ) >= 0 ) {
// newClass = newClass.replace( ' ' + className + ' ' , ' ' );
// }
// elem.className = newClass.replace( /^\s+|\s+$/g, '' );
// } else {
// elem.className += ' ' + className;
// }
// },
// animenuToggleNav = function (){
// toggleClass(animenuToggle, "animenu__btn--active");
// toggleClass(animenuNav, "animenu__nav--active");
// }
// if (!animenuToggle.addEventListener) {
// animenuToggle.attachEvent("onclick", animenuToggleNav);
// }
// else {
// animenuToggle.addEventListener('click', animenuToggleNav);
// }
// })()
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.