EDIT
@zim answer uses 2020 CSS to easily solve the issue and better applies to Bootstrap 4.
The original question and selected answer are still
You don't need Javascript, CSS will do the Job
.navbar-toggle {
.icon-bar {
transition: 300ms ease-in-out;
background-color: #fff;
position: relative;
width: 24px;
height: 3px;
}
.icon-bar:last-child {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
transform: rotate(-45deg);
top: -7px;
}
.icon-bar:nth-child(2) {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
top: 0px;
}
.icon-bar:nth-child(3) {
opacity: 0;
}
&.collapsed {
.icon-bar {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
top: 0;
opacity: 1;
}
}
}
As of Bootstrap 4.1, the "hamburger" toggler is no longer <span>
tags, and is now a single SVG icon background image.
Therefore it's simplest to swap it out with a little CSS. Then you can use another font icon (like FontAwesome) or a simple '✖' character...
<button class="navbar-toggler collapsed border-0" type="button" data-toggle="collapse" data-target="#collapsingNavbar">
<span class="navbar-toggler-icon"></span>
<div class="close-icon py-1">✖</div>
</button>
/* hide close when burger shown */
.navbar-toggler.collapsed .close-icon {
display: none;
}
.navbar-toggler:not(.collapsed) .navbar-toggler-icon {
display: inline;
}
Demo
Another option is this animated hamburger:
https://codeply.com/p/L9HT5GaUtt
Smart decision helped me in codepen
HTML
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
CSS
.navbar-toggle .icon-bar:nth-of-type(2) {
top: 1px;
}
.navbar-toggle .icon-bar {
position: relative;
transition: all 500ms ease-in-out;
}
.navbar-toggle.active .icon-bar:nth-of-type(1) {
top: 6px;
transform: rotate(45deg);
}
.navbar-toggle.active .icon-bar:nth-of-type(2) {
background-color: transparent;
}
.navbar-toggle.active .icon-bar:nth-of-type(3) {
top: -6px;
transform: rotate(-45deg);
}
JS
$(".navbar-toggle").on("click", function () {
$(this).toggleClass("active");
});
Your JavaScript replaces the inner html of the #ChangeToggle
element to show either the X or the hamburger icon. Precisely clicking on the X or the hamburger menu instead of the #ChangeToggle
will remove the element being clicked on which I think prevents it from bubbling up. As Bootstrap's collapse plugin uses an event handler on the document to determine if an element has been clicked, the collapse plugin will never get notified.
I've created a small example where a click handler on the pink .outer
area replaces the green .inner
area. Note that clicking on the pink area (your #ChangeToggle
) will lead to two events, where clicking on the green area (your X icon) will lead to a single event.
$(function() {
$('.outer')
.click(function() {
$('.outer').html('<div class="inner"></div>');
fired('.js-outer');
});
$(document).on('click', '.outer', function() {
fired('.js-document');
});
});
function fired(el) {
$(el).addClass('event--fire');
window.setTimeout(function() {
$(el).removeClass('event--fire')
}, 100);
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
}
.outer,
.inner {
display: inline-block;
padding: 20px;
}
.outer {
border: 1px solid #c66;
background-color: #f99;
}
.inner {
border: 1px solid #6c6;
background-color: #9f9;
}
.event {
margin: 10px 0;
}
.event::before {
display: inline-block;
content: '';
border: 1px solid #ccc;
padding: 10px;
vertical-align: middle;
margin-right: 10px;
}
.event--fire:before {
background-color: #ff9;
}
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<div class="outer">
<div class="inner">
</div>
</div>
<div class="event js-outer">Event fires on .outer</div>
<div class="event js-document">Event fires on document</div>
The easiest way to solve this issue for your navigation bar is to hide/show the X or hamburger icon instead of replacing. In the example below both the X and the hamburger icon are in the html, and toggling the class .hidden
is used to show the correct icon.
$(function() {
$('#ChangeToggle').click(function() {
$('#navbar-hamburger').toggleClass('hidden');
$('#navbar-close').toggleClass('hidden');
});
});
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button id="ChangeToggle" type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<div id="navbar-hamburger">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</div>
<div id="navbar-close" class="hidden">
<span class="glyphicon glyphicon-remove"></span>
</div>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a>
</li>
</ul>
</div>
</div>
</nav>
Instead of adding a jQuery click handler next to Bootstrap's collapse plugin, you could also use the events fired by the collapse plugin to hide or show the correct icon. Use the shown.bs.collapse
event to show the X icon, and the hidden.bs.collapse
event to show the hamburger icon.
$(function() {
$('#bs-example-navbar-collapse-1')
.on('shown.bs.collapse', function() {
$('#navbar-hamburger').addClass('hidden');
$('#navbar-close').removeClass('hidden');
})
.on('hidden.bs.collapse', function() {
$('#navbar-hamburger').removeClass('hidden');
$('#navbar-close').addClass('hidden');
});
});
#navbar-close {
color: #888;
width: 22px;
height: 14px;
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button id="ChangeToggle" type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<div id="navbar-hamburger">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</div>
<div id="navbar-close" class="hidden">
<span class="glyphicon glyphicon-remove"></span>
</div>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a>
</li>
</ul>
</div>
</div>
</nav>
No need to use javascript through css also you can do please follow below code.
HTML
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
CSS (in css use :not
which will perform faster animation rather than javascript)
.navbar-toggle .icon-bar {
position: relative;
transition: all 200ms ease-in-out;
}
.navbar-toggle:not(.collapsed) .icon-bar:nth-of-type(1) {
top: 6px;
transform: rotate(45deg);
}
.navbar-toggle:not(.collapsed) .icon-bar:nth-of-type(2) {
background-color: transparent;
}
.navbar-toggle:not(.collapsed) .icon-bar:nth-of-type(3) {
top: -6px;
transform: rotate(-45deg);
}
The below code helps you to solve this issue.
Html:
<div class="content">
<h1>Mobile Navigation menu using css and jquery</h1>
<div class="icons">
<button class="icon">
<span></span>
<span></span>
<span></span>
</button>
</div>
</div>
css:
.btn {
background-color: #ffd200;
color: #00174f;
display: inline-block;
text-decoration: none;
padding: 13px 30px;
margin: 30px 0 0 0;
border-radius: 3px;
font-weight: bold;
}
.btn:hover {
background-color: #fff;
}
.btn--transition {
-webkit-transition: -webkit-transform 0.2s;
-webkit-transition: all 200ms ease-in-out;
transition: all 200ms ease-in-out;
}
:focus {
outline: none;
}
.icons {
margin: 50px 0;
}
.icon {
margin: 0 30px 0 0;
}
.icon {
background-color: #ff3000;
border: 0;
height: 79px;
width: 79px;
border-radius: 50%;
cursor: pointer;
position: relative;
}
.icon span {
display: block;
height: 5px;
width: 33px;
background-color: #ffffff;
border-radius: 2px;
position: absolute;
left: 23px;
-webkit-transition: -webkit-transform 0.3s;
-webkit-transition: all 300ms ease-in-out;
transition: all 300ms ease-in-out;
}
.icon span:first-child {
top: 28px;
}
.icon span:nth-child(2) {
top: 37px;
}
.icon span:last-child {
top: 46px;
}
.icon--active span:first-child {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
top: 37px;
}
.icon--active span:last-child {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
position: absolute;
top: 37px;
}
.icon--active span:nth-child(2) {
opacity: 0;
}
.icon--button {
border-radius: 10px;
}
.icon-transition {
-webkit-transition: -webkit-transform 0.3s;
-webkit-transition: all 300ms ease-in-out;
transition: all 300ms ease-in-out;
}
javascript
<script>
var animation = 'rubberBand';
$('.icon').on('click', function () {
$(this).toggleClass('icon--active');
});
$('.icon').on('click', function () {
$(this).addClass('animated ' + animation).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
$(this).removeClass('animated ' + animation);
});
});
</script>
This snippets is used to change the mobile icon to close icon on click the button. Demo