Bootstrap mobile menu icon change to x close - javascript

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 valid and very informative.
ORIGINAL QUESTION
I would like, when in mobile view, for the menu icon (defined with class icon-bar in the bootstrap basic navbar example) to change to an X shape (Something similar to what happens here: https://www.mint.com but less fancy (I just want to replace the 3 stripes with an X).
At the moment I am using a custom id: #ChangeToggle
<button id="ChangeToggle" type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
Along with the following javascript function (I know it's basic but I'm new to this):
<script>
$('#ChangeToggle').click(function () {
if($('#ChangeToggle span').hasClass('ToggleButton')) {
$('#ChangeToggle').html('<span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>');
}
else {
$('#ChangeToggle').html('<span class="ToggleButton glyphicon glyphicon-remove"></span>');
}
});
</script>
Everything works, the only issue is that when I click exactly on the X icon the menu does not close. It only closes when I click outside of it (anywhere else in the button). The only thing it does while clicking on the X icon is going back to the original 3 stripes.
Anyone knows what I am doing wrong?

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">Link <span class="sr-only">(current)</span>
</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">Link <span class="sr-only">(current)</span>
</li>
</ul>
</div>
</div>
</nav>

This worked for me
Theory
CSS provides all the necessary animation tools. Basically what's happening is this:
The top and bottom lines must rotate to form the X
The middle line must disappear
The X will be taller an more narrow than the hamburger lines, so:
The top and middle lines must move out vertically and to the right to maintain its center
Application
/* Define the shape and color of the hamburger lines */
.navbar-toggler span {
display: block;
background-color: #4f4f4f;
height: 3px;
width: 25px;
margin-top: 5px;
margin-bottom: 5px;
position: relative;
left: 0;
opacity: 1;
transition: all 0.35s ease-out;
transform-origin: center left;
}
/* top line needs a little padding */
.navbar-toggler span:nth-child(1) {
margin-top: 0.3em;
}
/**
* Animate collapse into X.
*/
/* top line rotates 45 degrees clockwise and moves up and in a bit to close the center of the X in the center of the button */
.navbar-toggler:not(.collapsed) span:nth-child(1) {
transform: translate(15%, -33%) rotate(45deg);
}
/* center line goes transparent */
.navbar-toggler:not(.collapsed) span:nth-child(2) {
opacity: 0;
}
/* bottom line rotates 45 degrees counter clockwise, in, and down a bit to close the center of the X in the center of the button */
.navbar-toggler:not(.collapsed) span:nth-child(3) {
transform: translate(15%, 33%) rotate(-45deg) ;
}
/**
* Animate collapse open into hamburger menu
*/
/* top line moves back to initial position and rotates back to 0 degrees */
.navbar-toggler span:nth-child(1) {
transform: translate(0%, 0%) rotate(0deg) ;
}
/* middle line goes back to regular color and opacity */
.navbar-toggler span:nth-child(2) {
opacity: 1;
}
/* bottom line goes back to initial position and rotates back to 0 degrees */
.navbar-toggler span:nth-child(3) {
transform: translate(0%, 0%) rotate(0deg) ;
}
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<!-- Bootstrap Navigation -->
<nav class="navbar bg-light">
<a class="navbar-toggler collapsed border-0" type="button" data-toggle="collapse" data-target="#collapsingNavbar">
<!-- these spans become the three lines -->
<span> </span>
<span> </span>
<span> </span>
</a>
<a class="navbar-brand" href="./">
Brand
</a>
<div class="collapse navbar-collapse" id="collapsingNavbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</nav>
<main class="container">
<h1>Content Here</h1>
<p>Shrink the viewport if to expose the hamburger menu.</p>
</main>
What makes it work
Specifically, since the top and bottom lines rotate by 45 degrees to form the X, their center lines take up 70% of the width, so they must move in by 15%. This can be calculated using pythagorean theorem.
As it happens, our hamburger menu is 26x21 px, or 24% wider than it is tall, but the X ends up being 20x20 square when you move the lines into place and you take into account the height of the lines (here defined as 3px).
In this particular implementation, we are defining the point of rotation of each line as being the center-left. This affects how much we move the lines up, since the lines are about 3px tall, they each add about (2.1/2)=1.05px to the height of the X, or about 33% of the height of the X.
Therefore 33% is how much they must move out vertically out so the two lines meet at the center of the X and form a 20x20px square.
Customizing
The X will always make a square, so to find out how much to move them by, you just need to know the width and height of your <span> bars and the height of the resulting hamburger icon.
Plug those numbers into this equation:
Or in code:
const line_width = 26; // px
const line_height = 3; // px
const hamburger_height = 21; // px
const x_width = x_height = 0.8 * line_width;
const line_move_y_percent = 100 * (line_width - x_width) / (2 * line_height)
const line_move_right_percent = 100 * (x_height - hamburger_height) / (2 * line_height)

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");
});

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.

I tried #Zim's solution and it worked perfectly, thanks for sharing.
I did make 2 slight adjustments:
I changed border-0 to border-1 to keep a border around the hamburger image.
I added a background color on the div since the X ended up being a similar color to my existing background.

Bootstrap v5.2:
HTML:
<button class="navbar-toggler" id="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
<span class="close py-1"><i class="bi bi-x-lg"></i></span>
</button>
CSS:
.navbar button[aria-expanded="true"] > span.close {
display: inline;
}
.navbar button[aria-expanded="true"] > span.navbar-toggler-icon {
display: none;
}
.navbar button[aria-expanded="false"] > span.close {
display: none;
}
In my example I'm using Bootstrap Icons to display the close icon. So make also sure to download or at least include the icon fonts stylesheet.

Related

Why can't I target the nav for a drop down transition?

I am trying to get a transition to activate when the burger menu is clicked. My javascript, and css work for everything but creating a slow nav drop down transition from top to bottom.
Trying to find an answer online has led me to many different ways of creating a transition. So I am lost on that, if there is a standard way to do this please assist me. Not trying to be lazy but I have seen 5 different ways. Not sure what i need to target in my css. Thank you
<header>
<button class="hamburger hamburger--squeeze" type="button">
<span class="hamburger-box">
<span class="hamburger-inner"></span>
</span>
</button>
<img class="header-logo" src="/logo/piancavallo-logo.svg" alt="">
<nav>
<ul class="nav-links">
<li>home</li>
<li>shop</li>
<li>sport</li>
<li>read</li>
<li>about</li>
</ul>
</nav>
<img class="search-icon" src="/logo/search-icon.svg" alt="">
<img class="shopping-cart" src="/logo/shopping-cart.svg" alt="">
</header>
nav {
position: absolute;
text-align: left;
top: 100%;
left: 0;
}
nav .nav-links {
display: none;
background-color: orange;
font-size: 1.4rem;
position: absolute;
width: 100vw;
}
nav .nav-active {
display: block;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
margin: 5px;
padding: 5px;
}
nav a {
text-decoration: none;
color: green;
font-weight: 700;
}
nav ul {
-webkit-transition: height 1s ease-in;
transition: height 1s ease-in;
}
const revealNav = () => {
const hamburger = document.querySelector('.hamburger');
const nav = document.querySelector('.nav-links');
hamburger.addEventListener('click', () => {
hamburger.classList.toggle('is-active');
}, false);
hamburger.addEventListener('click', () => {
nav.classList.toggle('nav-active');
});
}
revealNav();
As far as I know there isn't a standard or better way to do this, it very much depends on the visual effect you are trying to achieve.
I have a solution here and I have stripped out most of the CSS that is not needed for the top/bottom transition.
I also have a jump in opacity that may be helpful while developing as it shows you exactly when the class is added or removed.
const revealNav = () => {
const hamburger = document.querySelector('.hamburger');
const nav = document.querySelector('.nav-links');
hamburger.addEventListener('click', () => {
nav.classList.toggle('is-active');
});
}
revealNav();
nav {
overflow: hidden;
}
.nav-links {
opacity: 1; /* only to show when class is added */
background-color: orange;
margin: 0;
padding: 0;
list-style: none;
transition: transform 1s;
transform: translateY(-100%);
}
.nav-links.is-active {
opacity: 1; /* only to show when class is added */
transform: translateY(0);
}
<header>
<button class="hamburger hamburger--squeeze" type="button">
<span class="hamburger-box">
<span class="hamburger-inner">hamburger</span>
</span>
</button>
<nav>
<ul class="nav-links">
<li>home</li>
<li>shop</li>
<li>sport</li>
<li>read</li>
<li>about</li>
</ul>
</nav>
</header>

Rotating chevrons with JQuery

I need to make a chevron rotate 180deg when clicking on its parent element to indicate whether a section is expanded or collapsed to an existing (non-bootstrap) accordion.
Currently all sections are defaulted to display expanded (green). When the .BlackTitleExp_top_style div is clicked the header section closes and the divs bg-color turns a light green to indicate the section is collapsed.
Ideally, when the header turns grey, the chevron should also rotate 180deg so that is is pointing down indicating the section is closed.
Ideally I'd like to accomplish by clicking on BlackTitleExp_top_style parent element but I'm not married to this idea. Any suggestions would be greatly appreciated.
$(document).ready(function() {
var BTE_top = $(".BlackTitleExp_top_style");
var BTE_top_BG = "BlackTitleExp_top_style_BG";
$(BTE_top).click(function() {
var el = $(this);
el.not(el).removeClass(BTE_top_BG);
el.toggleClass(BTE_top_BG);
});
});
.BlackTitleExp_top_style {
cursor: pointer;
background-color: rgba(92, 132, 92, 0.35);
border-radius: 5px;
position: relative;
padding: 15px;
margin-bottom: 10px;
}
.BlackTitleExp_top_style_BG {
transition: all 300ms ease;
cursor: pointer;
background-color: rgba(128, 128, 128, 0.35);
}
.chevron {
position: absolute;
right: 20px;
}
.rotate {
transform: rotate(180deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<!-- HTML -->
<div class="wrapper">
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
</div>
Define the states that an element(s) can exist in (ex. rotated 180o/0o, expanded/collapsed,
on/off etc) then declare the condition(s) (ex. if (fart) { smell.it }) or event(s) (ex. click, hover, etc) that can occur to invoke a behavior(s) (ex. rotate, expand, do your taxes, etc). In the demo below the adding/removing of a class (.fa-rotate-180) sets the styles on each <i>.
The class .fa-rotate-180 is a Font Awesome class that will rotate any of its icons 180o when applied. CSS animation is added as well via transform: rotate(), transition, and #keyframes
Details commented in demo
// Start with all content hidden
$('.content').hide();
// When header.title is clicked...
$('.title').on('click', function(event) {
// Reference the p.content that follows the clicked header✱
const clickedContent = $(this).next('.content');
// Reference the i.chevron that is nested within clicked header
const clickedChevron = $(this).find('.chevron');
/* Slide up all p.content with the exception of the sibling p.content that follows
the clicked header✱ */
$('.content').not(clickedContent).slideUp('fast');
// Expand/Collapse the p.content of the clicked header✱
clickedContent.slideToggle('fast');
/* Remove .fa-rotate-180 class from all i.chevron with the exception of the
i.chevron nested within clicked header */
$('.chevron').not(clickedChevron).removeClass('fa-rotate-180');
/* Add/Remove .fa-rotate-180 class to/from the i.chevron nested within the
clicked header */
clickedChevron.toggleClass('fa-rotate-180');
});
/* ✱ The expand/collapse aspect of code is not required by OP question and
is only added to provide a complete functional example. */
:root {
font: 16px/1.2 Arial;
}
.title {
font-size: 1.3rem;
cursor: pointer
}
.chevron {
/* block or inline-block for smoother animation */
display: inline-block;
/* Animation when going back to collapsed state */
transform: rotate(0deg);
transition: 0.3s;
}
.fa-rotate-180 {
/* This declares the keyframes used for animation */
animation: spin;
transition: 0.4s
}
/* An #rule used to breakdown animation into steps */
#keyframes spin {
100% {
transform: rotate(180deg);
}
}
<link href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css' rel='stylesheet'>
<aside class='read-more'>
<header class='title'>
<i class="fas fa-chevron-up chevron"></i> Chevron rotates 180<sup>o</sup>...
</header>
<p class='content'>...when header is clicked</p>
</aside>
<aside class='read-more'>
<header class='title'>
<i class="fas fa-chevron-up chevron"></i> Chevron rotates 180<sup>o</sup>...
</header>
<p class='content'>...when header is clicked</p>
</aside>
<aside class='read-more'>
<header class='title'>
<i class="fas fa-chevron-up chevron"></i> Chevron rotates 180<sup>o</sup>...
</header>
<p class='content'>...when header is clicked</p>
</aside>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Try this
BTE_top.click(function() {
var el = $(this);
var icon = el.find('i');
if(!icon.hasClass('rotate')){
icon.addClass('rotate');
}
el.not(el).removeClass(BTE_top_BG);
el.toggleClass(BTE_top_BG);
});
You are very close. Just adding this little bit of CSS will get you what you want:
.chevron {
position: absolute;
right: 20px;
transition: all 300ms ease;
}
.BlackTitleExp_top_style_BG .chevron {
transform: rotate(180deg);
}
Now when the BlackTitleExp_top_style_BG is added, the chevrons transform property is updated. With a transition now defined on chevron the rest of your code works as expected.
$(document).ready(function() {
var BTE_top = $(".BlackTitleExp_top_style");
var BTE_top_BG = "BlackTitleExp_top_style_BG";
$(BTE_top).click(function() {
var el = $(this);
el.not(el).removeClass(BTE_top_BG);
el.toggleClass(BTE_top_BG);
});
});
.BlackTitleExp_top_style {
cursor: pointer;
background-color: rgba(92, 132, 92, 0.35);
border-radius: 5px;
position: relative;
padding: 15px;
margin-bottom: 10px;
}
.BlackTitleExp_top_style_BG {
transition: all 300ms ease;
cursor: pointer;
background-color: rgba(128, 128, 128, 0.35);
}
.chevron {
position: absolute;
right: 20px;
transition: all 300ms ease;
}
.BlackTitleExp_top_style_BG .chevron {
transform: rotate(180deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<!-- HTML -->
<div class="wrapper">
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
<div class="BlackTitleExp_top_style">
simulated open section
<i class="fas fa-chevron-up chevron"></i>
</div>
</div>

jquery animate makes other elemtents dance

so I have this problem with jQuery .animate() function where I animate one element and it displaces all other elements associated with it.
This is the menu I am working with:
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-9 navbar">
<ul>
<li id="home_button" class="menu_button">
<i class="fa fa-home"></i>
<p>Home</p>
</li>
<li id="projects_button" class="menu_button">
<i class="fa fa-pencil"></i>
<p>Projects</p>
</li>
<li id="about_button" class="menu_button">
<i class="fa fa-balance-scale"></i>
<p>About</p>
</li>
<li id="contact_button" class="menu_button">
<i class="fa fa-user"></i>
<p>Contact</p>
</li>
</ul>
</div>
</div>
To see what I mean, I transferred my code into jsfiddle
Any help is appreciated!
This is normal HTML behaviour. Browsers "flow" the layouts, so if you make one element bigger, it reflows the rest of the document and displaces elements where it needs to.
If you want an element to move from one position to another, you have to take it out of the normal layout. You can do this by setting the position CSS attribute of the element to something other than relative. For example position: absolute makes the element positioned relative to the whole document, position: fixed makes the element positioned relative to the window's border, etc.
Additionally, you can use CSS transforms which also don't affect layout. These allow you to do a combination of translation, rotation and scaling to an element without displacing it's nearby siblings. This is ideal for, say, a slight size increase on mouse over or to transition items in from off screen.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions
Either way, I strongly recommend using CSS animations and transitions, rather than jQuery animate. You can then use jQuery to apply classes to enable and disable animations.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations
https://developer.mozilla.org/en/docs/Web/CSS/#keyframes
$('.animation-test').on('click', function() {
$(this).toggleClass('animation-test--enabled');
});
* {
font-family: arial, helvetica, san-serif;
}
.transition-test {
padding: 20px;
background: cornflowerblue;
transition: transform 200ms ease-in-out;
}
.transition-test:hover {
transform: scale(1.1);
}
.animation-test {
padding: 20px;
background: salmon;
}
.animation-test--enabled {
animation: identifier 1s infinite;
}
#keyframes identifier {
0% { transform: translateX(0); }
33% { transform: translateX(20px); }
66% { transform: translateX(-20px); }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="transition-test">Hover over me to see a transition on a transform scale (no Javascript required)</div>
<br/>
<div class="animation-test">Click me to toggle an animation (Javscript applies and removes the class)</div>
In addition to this breaking your layout, you'd also have to consider a way to stop and reverse the animation midway or else it'll keep going and potentially repeat if the user comes back to it. Try moving your mouse back and forth across all the buttons really fast on your fiddle to see what I mean. It's entertaining, but not the effect you want I think.
Fortunately not everything needs to be solved with javascript. CSS transitions are easy to understand and do all the hard work for you. Combine it with psuedo selectors and you'll get the effect your looking for.
CSS Transitions:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions
Psuedo Classes:
https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes
.menu_button{
transition: .250s width;
}
.menu_button:hover{
width : 100px;
}
.menu_button{
transition: .250s width;
}
.menu_button:hover{
width : 100px;
}
/** Note so important **/
ul {
list-style: none;
}
.container-fluid {
margin: 0;
padding: 0;
}
.photo-placeholder {
height: 350px;
background-color: green;
}
/* Navbar menu */
.menu_button {
width: 35px;
height: 35px;
display: inline-block;
margin-top: 15px;
margin-right: 10px;
border-radius: 20px;
}
#home_button {
background-color: red;
}
#home_button i {
margin-left: 0.6em;
margin-top: 0.5em;
}
#projects_button {
background-color: blue;
}
#projects_button i {
margin-top: 0.5em;
margin-left: 0.6em;
}
#about_button {
background-color: yellow;
}
#about_button i {
margin-top: 0.55em;
margin-left: 0.55em;
}
#contact_button {
background-color: green;
}
#contact_button i {
margin-top: 0.5em;
margin-left: 0.75em;
}
stretch {
width: 80px;
}
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-9 navbar">
<ul>
<li id="home_button" class="menu_button">
<i class="fa fa-home"></i>
<p>Home</p>
</li>
<li id="projects_button" class="menu_button">
<i class="fa fa-pencil"></i>
<p>Projects</p>
</li>
<li id="about_button" class="menu_button">
<i class="fa fa-balance-scale"></i>
<p>About</p>
</li>
<li id="contact_button" class="menu_button">
<i class="fa fa-user"></i>
<p>Contact</p>
</li>
</ul>
</div>
</div>
</div>
</body>

Why is my preloader animation continuing to display on my website after the preload is finished?

Why is my preloaded animation continuing to display on my website after the preloaded animation is finished and my website launches?
I only want the preloaded animation to display for the amount of seconds specified and for it not to continue over when my website launches. Just to confirm I want to remove the preload animation from my active website after it launches. I only want the animation to be there for the specified seconds and when the site launches I don't want to see it. How can I remove this?
This is an jsfiddle example example of how it looks currently with the loading animation carrying over to my website in the JSFIDDLE, this is what I want to be removed and only have the preload animation before the website launches
I believe the issue is with my html. I have two sets of <body> tags due to the preloaded page being separate to my website. Could this be confusing the process and causing the preloading animation to carry over to my actual site when it launches?
Please Note
The splash divrepresents the webpage which displays for a few seconds at the start.
The app divrepresents my actual website.
Here is what I want removed this whole preloaded animation part with the text and black background from my website after it launches.
I want my website to look like this when it launches after the preloaded animation is finished.
This is because you have set .splash as the class of that div. And you are trying to get document.getElementById('splash'), which as the name says, gets the element by id attribute which is why it is giving you an error. Simply change the class attribute to id or just change the js to-
document.getElementsByClassName('splash')[0]
I have demonstrated that in your code using the id-
//jQuery to collapse the navbar on scroll
$(window).scroll(function() {
if ($(".navbar").offset().top > 50) {
$(".navbar-fixed-top").addClass("top-nav-collapse");
} else {
$(".navbar-fixed-top").removeClass("top-nav-collapse");
}
});
//jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
$(document).on('click', 'a.page-scroll', function(event) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1500, 'easeInOutExpo');
event.preventDefault();
});
});
body{
background:#333;
background: -webkit-gradient(radial, center center, 120, center center, 900, from(#111), to(#111));
background:-moz-radial-gradient(circle, #111, #111);
}
#app {
display: none;
}
#splash{
margin:200px auto;
}
h1{
font-family: 'Actor', sans-serif;
color:#FFF;
font-size:16px;
letter-spacing:1px;
font-weight:200;
text-align:center;
}
#splash span{
width:16px;
height:16px;
border-radius:50%;
display:inline-block;
position:absolute;
left:50%;
margin-left:-10px;
-webkit-animation:3s infinite linear;
-moz-animation:3s infinite linear;
-o-animation:3s infinite linear;
}
#splash span:nth-child(2){
background:blue;
-webkit-animation:kiri 1.2s infinite linear;
-moz-animation:kiri 1.2s infinite linear;
-o-animation:kiri 1.2s infinite linear;
}
#splash span:nth-child(3){
background:red;
z-index:100;
}
#splash span:nth-child(4){
background:red;
-webkit-animation:kanan 1.2s infinite linear;
-moz-animation:kanan 1.2s infinite linear;
-o-animation:kanan 1.2s infinite linear;
}
#-webkit-keyframes kanan {
0% {-webkit-transform:translateX(20px);
}
50%{-webkit-transform:translateX(-20px);
}
100%{-webkit-transform:translateX(20px);
z-index:200;
}
}
#-moz-keyframes kanan {
0% {-moz-transform:translateX(20px);
}
50%{-moz-transform:translateX(-20px);
}
100%{-moz-transform:translateX(20px);
z-index:200;
}
}
#-o-keyframes kanan {
0% {-o-transform:translateX(20px);
}
50%{-o-transform:translateX(-20px);
}
100%{-o-transform:translateX(20px);
z-index:200;
}
}
#-webkit-keyframes kiri {
0% {-webkit-transform:translateX(-20px);
z-index:200;
}
50%{-webkit-transform:translateX(20px);
}
100%{-webkit-transform:translateX(-20px);
}
}
#-moz-keyframes kiri {
0% {-moz-transform:translateX(-20px);
z-index:200;
}
50%{-moz-transform:translateX(20px);
}
100%{-moz-transform:translateX(-20px);
}
}
#-o-keyframes kiri {
0% {-o-transform:translateX(-20px);
z-index:200;
}
50%{-o-transform:translateX(20px);
}
100%{-o-transform:translateX(-20px);
}
}
body, {
width: 100%;
height: 100%;
}
html, body {
width: 100%;
height: 100%;
}
#media(min-width:767px) {
.navbar {
padding: 10px 0;
-webkit-transition: background .1s ease-in-out,padding .5s ease-in-out;
-moz-transition: background .1s ease-in-out,padding .5s ease-in-out;
transition: background .1 ease-in-out,padding .1s ease-in-out;
//background-color: transparent;
background-color: white;
}
.top-nav-collapse {
padding: 0;
}
}
.nav.navbar-nav li a {
color: black;
}
.navbar-brand>img {
max-height: 100%;
height: 100%;
width: auto;
margin: 0 auto;
}
.intro-section {
height: 100%;
padding-top: 70px;
text-align: center;
min-height: auto;
background: #333;
}
.main1 {
color: #FFFFFF;
font-family: "Helvetica";
font-weight: bold;
font-size: 2em
}
.about-section {
height: 100%;
padding-top: 150px;
text-align: center;
background: #eee;
}
.contact-section {
height: 100%;
padding-top: 150px;
text-align: center;
background: #eee;
}
p {
color: white;
font-family: "Helvetica";
font-size: 1.3em;
margin: 10px auto;
white-space: nowrap;
overflow: hidden;
width: 0px
}
.main1 {
animation: type 1s 0s forwards steps(60, end);
}
.main2 {
animation: type2 1s 1s forwards steps(60, end);
}
.main3 {
animation: type3 1s 2s forwards steps(60, end);
}
span {
animation: blink 1s infinite;
}
#keyframes type{
from { width: 0; }
to { width: 430px; }
}
#keyframes type2{
from { width: 0; }
to { width: 224px; }
}
#keyframes type3{
from { width: 0; }
to { width: 364px; }
}
#keyframes blink{
to{opacity: .0;}
}
::selection{
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
setTimeout(function(){
document.getElementById('app').style['display'] = 'block';
document.getElementById('splash').style['display'] = 'none';
}, 3000);
</script>
<!--The script above in my code is placed in my code is head-->
<body>
<div id="splash">
<h1>LIAM DOCHERTY'S PORTFOLIO IS</h1>
<span></span>
<span></span>
<span></span>
<br>
<h1>LOADING</h1>
</div>
<div id="app">
<!-- Navigation -->
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header page-scroll">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand page-scroll" <img src="##############" alt="Personal Logo Design"></a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav navbar-right">
<!-- Hidden li included to remove active class from about link when scrolled up past about section -->
<li>
<a class="page-scroll" href="#page-top">Home</a>
</li>
<li>
<a class="page-scroll" href="#about">About</a>
</li>
<li>
<a class="page-scroll" href="#contact">Contact</a>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<body id="page-top" data-spy="scroll" data-target=".navbar-fixed-top">
<!-- Intro Section -->
<section id="intro" class="intro-section">
<div class="container header-container">
<div class="row">
<div class="col-lg-12 text-center">
<p class="main1">Welcome To My Digital Portfolio</p>
<p class="main2">My name is Liam Docherty</p>
<p class="main3">I'm a front end web developer from London.</p>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section id="about" class="about-section">
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1>About Section</h1>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="contact-section">
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1>Contact Section</h1>
</div>
</div>
</div>
</section>
</div>

making a menu that pops out of screen right

I am writing a bootstrap site, and want to make a sort of pop out menu from the right of the screen. This menu needs to be hidden' and when a button "Menu" is clicked it pops out of screen right, and covers whatever is on screen right. it does not push the content out of the way. Kind of like the windows 8 menu when you slide your finger from screen right.
I've thought of making a dropdown menu, since it behaves almost like I want, except for it's position. But I need to change the dropdown behaviour, So that instead of the dropdown menu popping out attached to the dropdown button, it pops out of screen right, but I can't find out how to do this.
<head>
...
<link href ="CSS/Bootstrap.min.css" rel ="stylesheet"/>
</head>
<div class="col-xs-3">
<!--some side content-->
</div>
<div class="col-xs-9">
<!--some side content-->
</div>
<div class="col-xs-12">
<nav class="navbar navbar-inverse navbar-fixed-bottom">
<div class="container-fluid">
<li class="dropup">
<a class="dropdown-toggle" data-toggle="dropdown">Menu
<ul> class="dropdown-menu">
<li>
</li>
<li>
</li>
</ul>
</a>
</li>
</div>
</nav>
</div>
<script src="JS/jquery-1.11.3.min.js"></script>
<script src="JS/bootstrap.min.js"></script>
I have three folders in my project:
Css with bootstrap css files(bootstrap-theme, bootstrap-theme min, bootstrap, bootstrap min)
Fonts
JS with bootstrap.js and bootstrap.min.js
Please show me how to do this.
If you know of a different way of making the menu I want in bootstrap I'd love to hear it as well.
Here is a simple example to get you going:
jsFiddle Demo
Note that an id was added to the a tag that opens the menu, to make it easy for jQuery to capture the click event on that element.
In the jQuery, we are using a variable mnuOut to keep track of whether the menu is IN or OUT (visible or hidden).
Also, we use the .animate() method to animate the slide out from the right. This works by changing the css attribute right:
FROM right:-80px (slid 80px beyond the right side of the screen)
TO right:0 where the right-most edge of the myMenu DIV is flush against the right side of the screen.
HTML:
<div id="myMenu">
<div id="item1" class="submenu">Item 1</div>
<div id="item2" class="submenu">Item 2</div>
<div id="item3" class="submenu">Item 3</div>
</div>
<a id="menuTrigger" class="dropdown-toggle" data-toggle="dropdown">Menu
CSS:
#myMenu{position:fixed;top:20px;right:-80px;width:80px;height:300px;background:palegreen;}
.submenu{width:100%;height:20px;padding:20px 5px;border:1px solid green;}
#menuTrigger:hover{cursor:pointer;}
jQuery:
mnuOut=false;
$('#menuTrigger').click(function(){
if (mnuOut){
//Menu is visible, so HIDE menu
$('#myMenu').animate({
right: '-80px'
},800);
mnuOut = false;
}else{
//Menu is hidden, so SHOW menu
$('#myMenu').animate({
right: 0
},800);
mnuOut = true;
}
})
If you want your menu to cover the content make sure you add
position: absolute;
Or
position: fixed;
Then after that give it
right: 500px;
But instead of 500px use the width of your menu
And to make it popout just override the
right: 0;
Making it 0 will make it stick to the right back to its original position
What you want requires a little more than just a couple of lines of css but I think this will give you a good start. Just style according to your theme:
HTML
<div id="oneout">
<span class="onetitle">
menu
</span>
<div id="oneout_inner">
<center>
menu info here
<br>
</center>
</div>
</div>
CSS
#oneout {
z-index: 1000;
position: fixed;
top: 64px;
right: 1px;
width: 18px;
padding: 40px 0;
text-align: center;
-webkit-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
-o-transition-duration: 0.3s;
transition-duration: 0.3s;
}
#oneout_inner {
top: 60px;
right: -250px;
position: fixed;
width: 230px;
padding: 10px;
background: #FFFFFF;
height: auto;
-webkit-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
-o-transition-duration: 0.3s;
transition-duration: 0.3s;
text-align: left;
border:1px solid #333;
}
#oneout:hover {
z-index: 1000;
right: 250px;
}
#oneout:hover #oneout_inner {
z-index: 1000;
right: 0px;
}
.onetitle {
display: block;
writing-mode: lr-tb;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
transform: rotate(-90deg);
position: absolute;
right: -11px;
top: 3px;
font-family: Lucida Sans;
font-size: 16px;
font-weight: normal;
text-transform: uppercase;
letter-spacing: -1px;
}
Here is a working DEMO

Categories