Skip to content

Instantly share code, notes, and snippets.

@nfreear
Last active June 5, 2022 12:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nfreear/06c99c07d3783004b331e6c1b6f5ba28 to your computer and use it in GitHub Desktop.
Save nfreear/06c99c07d3783004b331e6c1b6f5ba28 to your computer and use it in GitHub Desktop.
Responsive navigation component - <my-nav>
<!doctype html> <title> my-nav </title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><!-- -->
<style>
:root {
--my-nav-color: navy;
--my-nav-bg-color: #f9f9f9;
--my-nav-border: 1px solid #ddd;
--my-nav-mobile-width: 8rem;
}
body { font: 1rem sans-serif; margin: 1rem auto; max-width: 36rem; X-min-width: 5rem; padding: 0 .5rem; }
main { border: 1px solid #ccc; margin: 1rem 0; padding: 0 1rem; }
pre { font-size: x-small; white-space: pre-wrap;}
input, button { font: inherit; }
[ role = search ] input { width: 5rem; }
* { X-border-radius: .2rem; }
.my-nav {
line-height: 1.3rem;
width: 100%;
}
.my-nav ul {
display: flex;
flex-direction: row;
list-style: none;
margin: 0;
padding: 0;
width: 100%;
}
.my-nav li {
display: inline-block;
margin: 0;
padding: 0;
}
.my-nav li a {
background: var(--my-nav-bg-color);
border: var(--my-nav-border);
color: var(--my-nav-color);
display: inline-block;
min-width: 5.8rem;
padding: .6rem 1rem;
text-decoration: none;
}
.my-nav > button {
display: none;
cursor: pointer;
height: 2.5rem;
width: 2.5rem;
}
.my-nav .nav-toggle i {
border-top: 2px solid var(--my-nav-color);
display: block;
height: 0;
margin: .4rem 0;
}
.my-nav :focus,
.my-nav a:hover,
.my-nav button:hover {
background: #e8e8e8;
border-color: #bbb;
transition: all 1s;
}
@keyframes MyNavExpand {
from {
border-width: 0;
font-size: 1px;
min-width: 0;
X-width: 0;
X-height: 0;
padding: 0;
}
to {
border-width: 1px;
font-size: inherit;
min-width: var(--my-nav-mobile-width);
padding: .6rem 1rem;
}
}
@media screen and (max-width: 600px) {
.my-nav ul {
flex-direction: column;
position: absolute;
}
.my-nav li a {
min-width: var(--my-nav-mobile-width);
}
.my-nav > button {
display: block;
}
/* .nav-collapsed:not(.nav-animate) ul */
.nav-collapsed ul {
display: none;
}
.nav-expanded li * {
animation-duration: 250ms;
animation-name: MyNavExpand;
animation-timing-function: linear;
}
.XX_nav-collapsed ul a {
animation-direction: reverse;
animation-duration: 250ms;
animation-name: MyNavExpand;
animation-timing-function: linear;
}
}
@media screen and (max-width: 376px) {
body { margin-top: .5rem; }
.my-nav ul {
left: 0;
right: 0;
}
.my-nav li a {
border-width: .5px;
min-width: 0;
padding: .4rem;
width: calc(100% - .8rem - 1px);
}
}
</style>
<nav class="my-nav nav-collapsed">
<button class="nav-toggle" aria-expanded="false" aria-label="Toggle" title="Toggle"><i></i><i></i><i></i><!--<hr aria-hidden="true">--></button>
<ul>
<li><a href="#_1">First item</a>
<li><a href="#_2">Second item</a>
<li><a href="#_3">Third item</a>
<li><a href="#_4">Fourth item</a>
<li><a href="#_5">Fifth item</a>
<li><a href="#_6">Sixth item</a>
<li><form role="search"><input name=q aria-label="Search" placeholder="Search"><!--<button aria-label="Search">🔎</button>--></form>
</ul>
</nav>
<main>
<h1> my-nav </h1>
<p> Hello world! </p>
</main>
<script>
const ANIMATE_MS = 1000;
const MY_NAV = document.querySelector('.my-nav');
const BTN = MY_NAV.querySelector('.nav-toggle');
BTN.addEventListener('click', ev => {
ev.preventDefault();
const IS_EXPANDED = BTN.getAttribute('aria-expanded') === 'true';
BTN.setAttribute('aria-expanded', IS_EXPANDED ? 'false' : 'true');
MY_NAV.classList.remove(IS_EXPANDED ? 'nav-expanded' : 'nav-collapsed');
MY_NAV.classList.add(IS_EXPANDED ? 'nav-collapsed' : 'nav-expanded');
MY_NAV.classList.add('nav-animate');
setTimeout(() => {
MY_NAV.classList.remove('nav-animate');
},
ANIMATE_MS);
console.debug('my-nav ~ Toggle:', IS_EXPANDED, ev);
});
const SEARCH_FORM = document.querySelector('form[ role = search]');
SEARCH_FORM.addEventListener('submit', ev => {
ev.preventDefault();
const QUERY = ev.target.elements.q.value;
console.debug('Search submit:', QUERY, ev);
})
</script>
<pre>
NDF, 04-Jun-2022.
</pre>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment