JSFiddle - React, Tailwind, and code Playground
by langdonx
HTML
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<div ui-view>
<app>
<header>
<div class="d-flex align-items-center bg-dark">
<div class="flex-grow-1 px-3">L O G O</div>
<div class="d-none d-sm-block px-3">
<a href="#" class="text-white">Sign Out</a>
</div>
<button class="hamburger d-block d-sm-none"></button>
</div>
</header>
<div class="d-flex flex-row">
<nav class="d-none d-sm-flex flex-column bg-info">
<div>Parent 1<div>Child 1-1</div><div>Child 1-2</div><div>Child 1-3</div></div>
<div>Parent 2<div>Child 2-1</div><div>Child 2-2</div><div>Child 2-3</div></div>
<div>Parent 3<div>Child 3-1</div><div>Child 3-2</div><div>Child 3-3</div></div>
<div>Parent 4<div>Child 4-1</div><div>Child 4-2</div><div>Child 4-3</div></div>
<div>Parent 5<div>Child 5-1</div><div>Child 5-2</div><div>Child 5-3</div></div>
<div>Parent 6<div>Child 6-1</div><div>Child 6-2</div><div>Child 6-3</div></div>
<div>Parent 7<div>Child 7-1</div><div>Child 7-2</div><div>Child 7-3</div></div>
<div class="d-none d-sm-block">expand/collapse</div>
</nav>
<main class="d-flex flex-column flex-grow-1">
<div class="d-flex flex-column h-100">
<sub-nav class="d-none d-sm-flex flex-row flex-shrink-0 align-items-center pl-3">
<div class="pr-3">Child 1-1</div>
<div class="pr-3">Child 1-2</div>
<div class="pr-3">Child 1-3</div>
<div class="pr-3">Child 1-4</div>
</sub-nav>
<!-- good -->
<!-- <div class="d-flex flex-column h-100" style="overflow: auto;">
<div>
content here
</div>
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>
...
SCSS
// ideally I wanted the logo size and margins to determine the height of the header,
// but Firefox and Edge (which is WebKit, but equivalent to Chrome v64 from January 28)
// don't seem to handle flexbox as well as modern Chrome (currently v72) and sub nodes
// don't inherit the height correctly (app > div need to have its height explicitly
// set in Firefox and Edge)
$header-height: 50px;
html,
body {
height: 100vh;
}
body > div[ui-view] {
height: 100vh;
}
app {
display: flex;
flex-direction: column;
height: 100vh;
> div {
max-height: calc(100vh - #{$header-height});
}
}
header {
> div {
height: $header-height;
}
}
nav {
overflow-y: auto;
overflow-x: hidden;
@media (min-width: 576px) {
> div > div {
display: none;
}
}
> div:nth-last-child(2) {
flex-grow: 1;
}
}
main {
height: calc(100vh - #{$header-height});
}
sub-nav {
background: #dfdfdf;
height: 40px;
}
button.hamburger {
/* @extend .navbar-toggler */
padding: .25rem .75rem;
font-size: 1.25rem;
line-height: 1;
background-color: transparent;
border: 1px solid transparent;
border-radius: .25rem;
}
button.hamburger:after {
/* @extend .navbar-toggler-icon */
display: inline-block;
width: 1.5em;
height: 1.5em;
vertical-align: middle;
content: "";
background: no-repeat center center;
background-size: 100% 100%;
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='white' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
// classes to add menus in mobile:
.fixed-menu {
position: fixed;
right: 0;
padding: 1em;
overflow: auto;
height: calc(100vh - #{$header-height});
}
.animated-menu {
flex-basis: calc(100vh - 56px);
overflow: hidden;
transition: flex-basis...
JavaScript
const navAndContentContainer = document.querySelector('app > div');
const navContainer = navAndContentContainer.querySelector('nav');
let toggled = false;
// bs4 style menu
/* document.querySelector('.hamburger').addEventListener('click', () => {
console.log('toggling');
navAndContentContainer.classList.toggle('flex-column');
navAndContentContainer.classList.toggle('flex-row');
navContainer.classList.toggle('flex-shrink-0');
navContainer.classList.toggle('d-flex');
navContainer.classList.toggle('d-none');
navContainer.classList.toggle('d-sm-flex');
navContainer.classList.toggle('animated-menu');
navContainer.classList.toggle('initial');
setTimeout(() => {
navContainer.classList.toggle('initial');
setTimeout(() => {
navContainer.classList.toggle('expanded');
}, 333);
});
}); */
// mobile menu toggle adam is looking for
document.querySelector('.hamburger').addEventListener('click', () => {
console.log('toggling');
navAndContentContainer.classList.toggle('flex-column');
navContainer.classList.toggle('flex-shrink-0');
navContainer.classList.toggle('d-flex');
navContainer.classList.toggle('fixed-menu');
});