Reputation: 164
I'm using this Pure CSS hamburger menu code: https://codepen.io/erikterwan/pen/EVzeRP
/*
* Made by Erik Terwan
* 24th of November 2015
* MIT License
*
*
* If you are thinking of using this in
* production code, beware of the browser
* prefixes.
*/
body
{
margin: 0;
padding: 0;
/* make it look decent enough */
background: #232323;
color: #cdcdcd;
font-family: "Avenir Next", "Avenir", sans-serif;
}
a
{
text-decoration: none;
color: #232323;
transition: color 0.3s ease;
}
a:hover
{
color: tomato;
}
#menuToggle
{
display: block;
position: relative;
top: 50px;
left: 50px;
z-index: 1;
-webkit-user-select: none;
user-select: none;
}
#menuToggle input
{
display: block;
width: 40px;
height: 32px;
position: absolute;
top: -7px;
left: -5px;
cursor: pointer;
opacity: 0; /* hide this */
z-index: 2; /* and place it over the hamburger */
-webkit-touch-callout: none;
}
/*
* Just a quick hamburger
*/
#menuToggle span
{
display: block;
width: 33px;
height: 4px;
margin-bottom: 5px;
position: relative;
background: #cdcdcd;
border-radius: 3px;
z-index: 1;
transform-origin: 4px 0px;
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
background 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
opacity 0.55s ease;
}
#menuToggle span:first-child
{
transform-origin: 0% 0%;
}
#menuToggle span:nth-last-child(2)
{
transform-origin: 0% 100%;
}
/*
* Transform all the slices of hamburger
* into a crossmark.
*/
#menuToggle input:checked ~ span
{
opacity: 1;
transform: rotate(45deg) translate(-2px, -1px);
background: #232323;
}
/*
* But let's hide the middle one.
*/
#menuToggle input:checked ~ span:nth-last-child(3)
{
opacity: 0;
transform: rotate(0deg) scale(0.2, 0.2);
}
/*
* Ohyeah and the last one should go the other direction
*/
#menuToggle input:checked ~ span:nth-last-child(2)
{
transform: rotate(-45deg) translate(0, -1px);
}
/*
* Make this absolute positioned
* at the top left of the screen
*/
#menu
{
position: absolute;
width: 300px;
margin: -100px 0 0 -50px;
padding: 50px;
padding-top: 125px;
background: #ededed;
list-style-type: none;
-webkit-font-smoothing: antialiased;
/* to stop flickering of text in safari */
transform-origin: 0% 0%;
transform: translate(-100%, 0);
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0);
}
#menu li
{
padding: 10px 0;
font-size: 22px;
}
/*
* And let's slide it in from the left
*/
#menuToggle input:checked ~ ul
{
transform: none;
}
<!-- Made by Erik Terwan -->
<!-- 24th of November 2015 -->
<!-- MIT License -->
<nav role="navigation">
<div id="menuToggle">
<!--
A fake / hidden checkbox is used as click reciever,
so you can use the :checked selector on it.
-->
<input type="checkbox" />
<!--
Some spans to act as a hamburger.
They are acting like a real hamburger,
not that McDonalds stuff.
-->
<span></span>
<span></span>
<span></span>
<!--
Too bad the menu has to be inside of the button
but hey, it's pure CSS magic.
-->
<ul id="menu">
<a href="#"><li>Home</li></a>
<a href="#"><li>About</li></a>
<a href="#"><li>Info</li></a>
<a href="#"><li>Contact</li></a>
<a href="https://erikterwan.com/" target="_blank"><li>Show me more</li></a>
</ul>
</div>
</nav>
The problem i'm having is that it remains open when I click on a menu item as it is a one-page site with anchor links. What would be the best method to close the menu on click of any of the menu item links? Using javascript to remove the menu onclick is not a good option because the X also needs to revert back to a hamburger and it doesn't if you use this method. Any help appreciated, thanks in advance!
Upvotes: 1
Views: 6835
Reputation: 63
You can use Jquery to toggle the Menu:
Open: $('#menuToggle input').prop( "checked" ,true);
Close: $('#menuToggle input').prop( "checked" ,false);
Upvotes: 0
Reputation: 874
It is possible to add a little JavaScript without breaking the behaviour of your closing icon.
See your modified code snippet below, when adding an eventListener on click of your menu links, just uncheck the input field corresponding to toggle the menu burger icon:
var menu = document.getElementById('menu');
var closeIcon = document.getElementById("closeIcon");
menu.addEventListener('click', handleMenuClick);
function handleMenuClick(event) {
if (event.target instanceof HTMLAnchorElement) {
closeIcon.checked = false;
}
}
/*
* Made by Erik Terwan
* 24th of November 2015
* MIT License
*
*
* If you are thinking of using this in
* production code, beware of the browser
* prefixes.
*/
body
{
margin: 0;
padding: 0;
/* make it look decent enough */
background: #232323;
color: #cdcdcd;
font-family: "Avenir Next", "Avenir", sans-serif;
}
a
{
text-decoration: none;
color: #232323;
transition: color 0.3s ease;
}
a:hover
{
color: tomato;
}
#menuToggle
{
display: block;
position: relative;
top: 50px;
left: 50px;
z-index: 1;
-webkit-user-select: none;
user-select: none;
}
#menuToggle input
{
display: block;
width: 40px;
height: 32px;
position: absolute;
top: -7px;
left: -5px;
cursor: pointer;
opacity: 0; /* hide this */
z-index: 2; /* and place it over the hamburger */
-webkit-touch-callout: none;
}
/*
* Just a quick hamburger
*/
#menuToggle span
{
display: block;
width: 33px;
height: 4px;
margin-bottom: 5px;
position: relative;
background: #cdcdcd;
border-radius: 3px;
z-index: 1;
transform-origin: 4px 0px;
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
background 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
opacity 0.55s ease;
}
#menuToggle span:first-child
{
transform-origin: 0% 0%;
}
#menuToggle span:nth-last-child(2)
{
transform-origin: 0% 100%;
}
/*
* Transform all the slices of hamburger
* into a crossmark.
*/
#menuToggle input:checked ~ span
{
opacity: 1;
transform: rotate(45deg) translate(-2px, -1px);
background: #232323;
}
/*
* But let's hide the middle one.
*/
#menuToggle input:checked ~ span:nth-last-child(3)
{
opacity: 0;
transform: rotate(0deg) scale(0.2, 0.2);
}
/*
* Ohyeah and the last one should go the other direction
*/
#menuToggle input:checked ~ span:nth-last-child(2)
{
transform: rotate(-45deg) translate(0, -1px);
}
/*
* Make this absolute positioned
* at the top left of the screen
*/
#menu
{
position: absolute;
width: 300px;
margin: -100px 0 0 -50px;
padding: 50px;
padding-top: 125px;
background: #ededed;
list-style-type: none;
-webkit-font-smoothing: antialiased;
/* to stop flickering of text in safari */
transform-origin: 0% 0%;
transform: translate(-100%, 0);
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0);
}
#menu li
{
padding: 10px 0;
font-size: 22px;
}
#menu a {
display: block;
}
/*
* And let's slide it in from the left
*/
#menuToggle input:checked ~ ul
{
transform: none;
}
<!-- Made by Erik Terwan -->
<!-- 24th of November 2015 -->
<!-- MIT License -->
<nav role="navigation">
<div id="menuToggle">
<!--
A fake / hidden checkbox is used as click reciever,
so you can use the :checked selector on it.
-->
<input id="closeIcon" type="checkbox" />
<!--
Some spans to act as a hamburger.
They are acting like a real hamburger,
not that McDonalds stuff.
-->
<span></span>
<span></span>
<span></span>
<!--
Too bad the menu has to be inside of the button
but hey, it's pure CSS magic.
-->
<ul id="menu">
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">Info</a>
</li>
<li>
<a href="#">Contact</a>
</li>
<li>
<a href="https://erikterwan.com/" target="_blank">Show me more</a>
</li>
</ul>
</div>
</nav>
Notice, that I also fixed the semantic of the menu list element as putting a elements into li elements and not vice versa as it was before. Plus adding display: block;
to the menu a elements to provide them to be full width and be correctly clickable.
That, however should not effect the appearance of your menu.
Note In case you are wondering if a pure CSS only solution would be possible. In theory you would try to uncheck the burger-icons input field by clicking on a menu link. You would try that by using radio inputs with the same name, so they will toggle each other.
Unfortunately there are 2 things which speak against that:
Upvotes: 1