HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URL's added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by Skypack, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ES6 import
usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<div class="container">
<header>
<nav class="menu-container">
<div class="menu-toggler" id="menu-toggler">
<div class="hamburger"></div>
</div>
<ul class="menu-list" id="menu-list">
<li><a href="#">Element 01</a>
<div class="submenu-container">
<div>
<h4>submenu title 11</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0111</a></li>
<li><a href="#">Element 0112</a></li>
<li><a href="#">Element 0113</a></li>
<li><a href="#">Element 0114</a></li>
<li><a href="#">Element 0115</a></li>
</ul>
</div>
<div>
<h4>submenu title 12</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0121</a></li>
<li><a href="#">Element 0122</a></li>
<li><a href="#">Element 0123</a></li>
<li><a href="#">Element 0124</a></li>
<li><a href="#">Element 0125</a></li>
</ul>
</div>
<div>
<h4>submenu title 13</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0131</a></li>
<li><a href="#">Element 0132</a></li>
<li><a href="#">Element 0133</a></li>
<li><a href="#">Element 0134</a></li>
<li><a href="#">Element 0135</a></li>
</ul>
</div>
</div>
</li>
<li><a href="#" class="no-event">Element 02</a>
<div class="submenu-container">
<div>
<h4>submenu title 21</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0211</a></li>
<li><a href="#">Element 0212</a></li>
<li><a href="#">Element 0213</a></li>
<li><a href="#">Element 0214</a></li>
<li><a href="#">Element 0215</a></li>
</ul>
</div>
<div>
<h4>submenu title 22</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0221</a></li>
<li><a href="#">Element 0222</a></li>
<li><a href="#">Element 0223</a></li>
<li><a href="#">Element 0224</a></li>
<li><a href="#">Element 0225</a></li>
</ul>
</div>
<div>
<h4>submenu title 23</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0231</a></li>
<li><a href="#">Element 0232</a></li>
<li><a href="#">Element 0233</a></li>
<li><a href="#">Element 0234</a></li>
<li><a href="#">Element 0235</a></li>
</ul>
</div>
</div>
</li>
<li><a href="#">Element 03</a>
<div class="submenu-container">
<div>
<h4>submenu title 31</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0311</a></li>
<li><a href="#">Element 0312</a></li>
<li><a href="#">Element 0313</a></li>
<li><a href="#">Element 0314</a></li>
<li><a href="#">Element 0315</a></li>
</ul>
</div>
<div>
<h4>submenu title 32</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0321</a></li>
<li><a href="#">Element 0322</a></li>
<li><a href="#">Element 0323</a></li>
<li><a href="#">Element 0324</a></li>
<li><a href="#">Element 0325</a></li>
</ul>
</div>
<div>
<h4>submenu title 33</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0331</a></li>
<li><a href="#">Element 0332</a></li>
<li><a href="#">Element 0333</a></li>
<li><a href="#">Element 0334</a></li>
<li><a href="#">Element 0335</a></li>
</ul>
</div>
</div>
</li>
<li><a href="#">Element 04</a>
<div class="submenu-container">
<div>
<h4>submenu title 41</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0411</a></li>
<li><a href="#">Element 0412</a></li>
<li><a href="#">Element 0413</a></li>
<li><a href="#">Element 0414</a></li>
<li><a href="#">Element 0415</a></li>
</ul>
</div>
<div>
<h4>submenu title 42</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0421</a></li>
<li><a href="#">Element 0422</a></li>
<li><a href="#">Element 0423</a></li>
<li><a href="#">Element 0424</a></li>
<li><a href="#">Element 0425</a></li>
</ul>
</div>
<div>
<h4>submenu title 43</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0431</a></li>
<li><a href="#">Element 0432</a></li>
<li><a href="#">Element 0433</a></li>
<li><a href="#">Element 0434</a></li>
<li><a href="#">Element 0435</a></li>
</ul>
</div>
</div></li>
<li><a href="#">Element 05</a>
<div class="submenu-container">
<div>
<h4>submenu title 51</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0511</a></li>
<li><a href="#">Element 0512</a></li>
<li><a href="#">Element 0513</a></li>
<li><a href="#">Element 0514</a></li>
<li><a href="#">Element 0515</a></li>
</ul>
</div>
<div>
<h4>submenu title 52</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0521</a></li>
<li><a href="#">Element 0522</a></li>
<li><a href="#">Element 0523</a></li>
<li><a href="#">Element 0524</a></li>
<li><a href="#">Element 0525</a></li>
</ul>
</div>
<div>
<h4>submenu title 53</h4>
<ul class="menu-sublist">
<li><a href="#">Element 0531</a></li>
<li><a href="#">Element 0532</a></li>
<li><a href="#">Element 0533</a></li>
<li><a href="#">Element 0534</a></li>
<li><a href="#">Element 0535</a></li>
</ul>
</div>
</div>
</li>
</ul>
</nav>
</header>
<main>
<h3>About</h3>
<p>Illustation to blogpost <a href="https://dygresje.info/blog/webdev-menu">Frontend - menu RWD z Hamburgerem</a></p>
<ul>
<li>Minimal, easy to understand code.</li>
<li>Dropdown menu with Hamburger in mobile resolution.</li>
<li>In desktop resolution works only CSS, JS action is blocked or impossible.</li>
<li>In mobile resolution all action is only on click, because of JS.</li>
<li>Hamburger menu works like accordion, expanding any submenu collapses previously expanded.</li>
<li>Second click on menu link of expanded submenu collapses it.</li>
<li>Collapsing Hamburger collapses expanded submenu.</li>
<li>Both previous action can be easily turned off.</li>
<li>Resizing from mobile resolution to desktop one collapses expanded submenu (it also can be turned off, but IMO it's nonsense).</li>
<li>MegaMenu is gracefully transformed into linear form. Code and behavior are basically the same as in <a href="https://codepen.io/tdudkowski/pen/NWawYXr">Codepen: Dropdown menu with Hamburger</a></li>
<li>TODO: find graceful way of hiding Hamburger. Except for that as for 2022-05-14 this is final version.</li>
</ul>
</main>
</div>
.container {
max-width: 1100px;
margin: 0 auto;
min-height: 100vh;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
ul {
padding-left: 0;
list-style-type: none;
margin: 0;
}
.menu-list > li > a {
pointer-events: none;
}
/* # MENU # */
.menu-container {
height: 2rem;
position: relative;
}
.menu-list {
display: flex;
position: absolute;
flex-direction: column;
left: -100%;
width: 100%;
/* transition: all 0.3s linear; */
}
.menu-list li {
flex: 1;
/* position: relative; */
}
.menu-list a {
display: block;
text-align: center;
text-decoration: none;
height: 1.2rem;
padding: 5px 0;
user-select: none;
}
.menu-list a:hover {
text-decoration: underline;
background-color: beige;
}
.submenu-container {
/* position: absolute; */
left: 0;
display: none;
/* width: 100%; */
box-shadow: 2px 2px 5px rgba(51, 51, 51, 0.5);
background-color: #ffe;
}
.menu-toggler {
display: flex;
height: 100%;
cursor: pointer;
padding: 0 10vw;
padding-left: 1rem;
background-color: #666;
}
/* # HAMBURGER # */
.hamburger {
background-color: #ccc;
width: 30px;
height: 3px;
transition: all 0.3s linear;
align-self: center;
position: relative;
}
.hamburger::before,
.hamburger::after {
width: 30px;
height: 3px;
background-color: #ccc;
content: "";
position: absolute;
transition: all 0.3s linear;
}
.hamburger::before {
top: -10px;
}
.hamburger::after {
top: 10px;
}
/* # OPEN # */
.open .hamburger {
transform: rotate(-45deg);
}
.open .hamburger::before {
transform: rotate(-90deg) translate(-10px, 0px);
}
.open .hamburger::after {
opacity: 0;
transform: rotate(90deg);
}
.open ~ .menu-list {
left: 0;
transition: all 0.3s linear;
}
.menu-list li .open {
display: flex;
flex-direction: column;
position: relative;
}
@media (min-width: 800px) {
.menu-toggler {
display: none;
}
.menu-list {
flex-direction: row;
left: 0;
transition: all 0s;
}
.menu-list li:hover > a {
background-color: beige;
}
.menu-list li > .open {
/* display: none; */
}
.menu-list li:hover > .submenu-container {
display: flex;
flex-direction: row;
width: 100%;
position: absolute;
}
.menu-list li:hover > .submenu-container div {
flex: 1;
}
}
const toggler = document.getElementById("menu-toggler");
const sublistToggler = document.getElementById("menu-list");
// [...sublistToggler.children].forEach((element) =>
// element.addEventListener("click", (e) => e.target.children[1] ? e.target.children[1].classList.toggle("open") : null )
// );
const sublistToggle = (e) => {
if (window.visualViewport.width<800) {
const clickedItemClasslist = e.path[0].children[1].classList
// COLLAPSE IF EXPANDED
if (clickedItemClasslist.contains('open')) {clickedItemClasslist.remove("open"); return;}
// ACCORDION
for (let i = 0; i < sublistToggler.children.length; i++) {sublistToggler.children[i].children[1].classList.remove("open")}
// EXPAND
clickedItemClasslist.toggle("open");
}
};
const listToggle = () => {
toggler.classList.toggle("open");
for (let i = 0; i < sublistToggler.children.length; i++) {sublistToggler.children[i].children[1].classList.remove("open")}
}
sublistToggler.addEventListener("click", (e) => sublistToggle(e));
toggler.addEventListener("click", () => listToggle());
// CLOSE EXPANDED IF RESIZED UP
const closeExpanded = () => {
if (window.visualViewport.width>799) {
toggler.classList.remove("open");
for (let i = 0; i < sublistToggler.children.length; i++) {sublistToggler.children[i].children[1].classList.remove("open")}
}
}
window.addEventListener('resize', closeExpanded);
Also see: Tab Triggers