<div class="wrapper">
<input type="checkbox" id="menuToggler" class="input-toggler" value="1" autofocus="true"/>
<label for="menuToggler" id="menuTogglerLabel" class="menu-toggler" role="button" aria-pressed="false" aria-expanded="false" aria-label="Navigation button">
<span class="menu-toggler__line"></span>
<span class="menu-toggler__line"></span>
<span class="menu-toggler__line"></span>
</label>
<nav id="sidebar" class="sidebar" role="navigation" aria-labelledby="menuTogglerLabel" aria-hidden="true">
<ul id="menubar" class="menu" role="menubar" aria-orientation="vertical">
<li class="menu__item" role"none"><a class="menu__link" href="#" role="menuitem" tabindex="-1">Home</a></li>
<li class="menu__item" role"none"><a class="menu__link" href="#" role="menuitem" tabindex="-1">Blog</a></li>
<li class="menu__item" role"none"><a class="menu__link" href="#" role="menuitem" tabindex="-1">Portfolio</a></li>
<li class="menu__item" role"none"><a class="menu__link" href="#" role="menuitem" tabindex="-1">About</a></li>
<li class="menu__item" role"none"><a class="menu__link" href="#" role="menuitem" tabindex="-1">Contact</a></li>
</ul>
</nav>
<main class="content">
<h1>CSS sidebar toggle</h1>
<p>Pure CSS solution for hiding and showing sidebar.</p>
</main>
</div>
<a class="sb-link" href="//silvestar.codes/articles/css-sidebar-toggle/">silvestar.codes</a>
@mixin fluid-type($properties, $min-vw, $max-vw, $min-value, $max-value) {
@each $property in $properties {
#{$property}: $min-value;
}
@media screen and (min-width: $min-vw) {
@each $property in $properties {
#{$property}: calc(#{$min-value} + #{strip-unit($max-value - $min-value)} * (100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)});
}
}
@media screen and (min-width: $max-vw) {
@each $property in $properties {
#{$property}: $max-value;
}
}
}
@function strip-unit($value) {
@return $value / ($value * 0 + 1);
}
@function em($pixels, $context: $default-font-size) {
@return #{$pixels/$context}em;
}
// variables
:root {
--sidebar-width: 100%;
--toggler-size: 30px;
--toggler-line-number: 3;
--toggler-line-size: calc(var(--toggler-size) / (var(--toggler-line-number) + var(--toggler-line-number) - 1));
--toggler-offset-left: 10px;
--toggler-offset-top: 10px;
--toggler-color: Tomato;
--toggler-color-hover: Wheat;
}
// same as var(--toggler-line-number)
$total: 3;
// reset
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
// styling
html {
font-family: -apple-system, BlinkMacSystemFont,
"Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans",
"Droid Sans", "Helvetica Neue", sans-serif;
@include fluid-type(font-size, 20em, 75em, .8rem, 1.2rem);
}
.wrapper {
min-width: 100vw;
background: AliceBlue;
display: flex;
}
.sidebar,
.content {
transition: all .25s ease-out;
}
.sidebar {
width: var(--sidebar-width);
transform: translateX(calc(var(--sidebar-width) * -1));
background: linear-gradient(to bottom right, Tomato, Wheat);
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
height: 100vh;
opacity: .5;
}
.content {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.menu {
list-style-type: none;
}
.menu__link {
color: white;
font-weight: 100;
text-decoration: none;
font-size: 10vmin;
line-height: 15vmin;
transition: all .25s ease-out;
&:hover,
&:focus,
&:active {
color: Gold;
}
}
.menu-toggler {
border-radius: calc(var(--toggler-line-size) / 2);
display: block;
width: var(--toggler-size);
height: var(--toggler-size);
position: fixed;
top: var(--toggler-offset-top);
left: var(--toggler-offset-left);
cursor: pointer;
z-index: 1;
}
.menu-toggler__line {
height: var(--toggler-line-size);
background: var(--toggler-color);
position: absolute;
border-radius: calc(var(--toggler-line-size) / 2);
left: 0;
right: 0;
transition: all .25s ease-out;
$num: 1;
@while $num <= $total {
&:nth-child(#{$num}) {
top: calc(var(--toggler-line-size) * #{$num} + (var(--toggler-line-size) * (#{$num} - 2)));
}
$num: $num + 1;
}
}
.input-toggler {
position: absolute;
left: -100%;
&:focus ~ .menu-toggler {
outline: 1px dotted;
}
&:checked ~ .menu-toggler {
.menu-toggler__line:not(:first-child):not(:last-child) {
opacity: 0;
}
.menu-toggler__line:first-child,
.menu-toggler__line:last-child {
background-color: var(--toggler-color-hover);
}
.menu-toggler__line:first-child {
transform: translateY(calc(var(--toggler-line-size) * (var(--toggler-line-number) - 1))) rotate(45deg);
}
.menu-toggler__line:last-child {
transform: translateY(calc(-1 * var(--toggler-line-size) * (var(--toggler-line-number) - 1))) rotate(-45deg);
}
}
&:checked ~ .sidebar {
transform: translateX(0);
opacity: .98;
}
}
// sig
.wrapper {
height: calc(100vh - 50px);
}
.sb-link {
display: flex;
height: 50px;
align-content: center;
align-items: center;
justify-content: center;
text-decoration: none;
color: #bb5555;
transition: background .3s;
}
.sb-link:hover,
.sb-link:focus,
.sb-link:active {
background: #f7f7f7;
}
View Compiled
let menuToggler = document.getElementById('menuToggler')
let menuTogglerLabel = document.getElementById('menuTogglerLabel');
let sidebar = document.getElementById('sidebar');
let menuItems = document.getElementsByClassName('menu__link');
menuToggler.addEventListener('change', function() {
if(menuToggler.checked) {
menuTogglerLabel.setAttribute('aria-pressed', 'true');
sidebar.setAttribute('aria-hidden', 'false');
} else {
menuTogglerLabel.setAttribute('aria-pressed', 'false');
sidebar.setAttribute('aria-hidden', 'true');
}
for(let menuItem of menuItems) {
if(menuToggler.checked) {
menuItem.setAttribute('tabindex', '0');
} else {
menuItem.setAttribute('tabindex', '-1');
}
}
});
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.