"Place dots" in HTML/CSS/JS slideshow - javascript

I'm trying to make a slideshow with those little navigation or placeholder dots along the bottom - the slideshow itself is working, but in the minimal example here, there's only one dot showing up at the bottom. I can't figure out what I'm doing wrong - researched, left it for a couple days and came back to it, now time for a question...
Here's the code I'm working with:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {
background-color: lightblue;
}
body {
width:1024px;
height:768px;
margin-left: auto;
margin-right: auto;
border-style: solid;
background: lightgreen;
position: relative;
}
div#banner{
position: absolute;
top:50px;
width: 100%;
height: 120px;
background: pink;
text-align: center;
padding-top: 0px;
padding-bottom: 0px;
font-size:1.5em;
}
div#minibanner{
position: absolute;
top:0px;
height:50px;
width: 100%;
background: orange;
text-align: center;
}
div#slideContainer {
position:absolute;
left:200px;
top:170px;
height:558px;
width:794px;
padding-top: 30px;
padding-left:30px;
font-size: 2em;
background: yellow;
}
div#sidenav{
position: absolute;
top:170px;
left:0px;
width: 200px;
height:558px;
}
.contentSlide{
display: none;
}
div#bottomnav{
position: absolute;
bottom:0px;
height:40px;
width: 100%;
background: pink;
text-align: center;
}
.dot {
position:absolute;
bottom:60px;
cursor: pointer;
height: 15px;
width: 15px;
margin: 22px 22px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active, .dot:hover {
background-color: #717171;
}
.fade {
-webkit-animation-name: fade;
-webkit-animation-duration: 1.5s;
animation-name: fade;
animation-duration: 1.5s;
}
#-webkit-keyframes fade {
from {opacity: .4}
to {opacity: 1}
}
#keyframes fade {
from {opacity: .4}
to {opacity: 1}
}
.prev, .next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: red;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
.prev {
left:0;
}
.prev:hover, .next:hover {
background-color: rgba(0,0,0,0.8);
}
</style>
</head>
<body>
<div id="minibanner"><h3>Title of Presentation: testing, testing testing</h3></div>
<div id="banner"><h1>Introduction</h1></div>
<div id="sidenav">
<ul>
<li>home</li>
<li>Introduction</li>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
<li>Conclusion</li>
</ul>
</div>
<div id="slideContainer">
<div class="contentSlide fade">
<p>Here's an outline:
<ul>
<li>Introduction</li>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
<li>Conclusion</li>
</ul>
</p>
</div>
<div class="contentSlide fade">
<p>Here are some themes:
<ul>
<li>Theme 1</li>
<li>Theme 2</li>
<li>Theme 3</li>
</ul>
</p>
</div>
<div class="contentSlide fade">
<p>...and the conclusions:
<ul>
<li>Conclusion A</li>
<li>Conclusion B</li>
<li>Conclusion C</li>
<li>Conclusion D</li>
<li>Conclusion E</li>
</ul>
</p>
</div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
<div style="text-align:center">
<span class="dot" onclick="currentSlide(1)"></span>
<span class="dot" onclick="currentSlide(2)"></span>
<span class="dot" onclick="currentSlide(3)"></span>
</div>
<div id="bottomnav"><p>footer</p></div>
<script>
var slideIndex = 1;
showSlides(slideIndex);
// Next/previous controls
function plusSlides(n) {
showSlides(slideIndex += n);
}
// Thumbnail image controls
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("contentSlide");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {slideIndex = 1;}
if (n < 1) {slideIndex = slides.length;}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
}
</script>
</body>
</html>
Anybody have an idea where the first two dots are and how I can fix it so the three dots are in a row?

You don't have two missing dots; all your dots are sitting on top of each other!
You gave each dot position: absolute, but they didn't have separate left or right values, so they just ended up sitting on top of each other.
The solution to this is simple: make their parent position: absolute and let the dots just be position: static.
Once you do this, the other problem you'll notice is that the dots appear off-center to the left because they are positioned relative to the overall page, whereas you probably want them centered in the yellow area.
Moving the dots' wrapper inside #slideContainer will fix this problem because #slideContainer is also position: absolute, and absolute positioning works in relation to an element's nearest positioned ancestor (i.e., any element above it in the tree that is either position: relative, position: absolute, or position: sticky).
var slideIndex = 1;
showSlides(slideIndex);
// Next/previous controls
function plusSlides(n) {
showSlides(slideIndex += n);
}
// Thumbnail image controls
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("contentSlide");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {
slideIndex = 1;
}
if (n < 1) {
slideIndex = slides.length;
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += " active";
}
html {
background-color: lightblue;
}
body {
width: 1024px;
height: 768px;
margin-left: auto;
margin-right: auto;
border-style: solid;
background: lightgreen;
position: relative;
}
div#banner {
position: absolute;
top: 50px;
width: 100%;
height: 120px;
background: pink;
text-align: center;
padding-top: 0px;
padding-bottom: 0px;
font-size: 1.5em;
}
div#minibanner {
position: absolute;
top: 0px;
height: 50px;
width: 100%;
background: orange;
text-align: center;
}
div#slideContainer {
position: absolute;
left: 200px;
top: 170px;
height: 558px;
width: 794px;
padding-top: 30px;
padding-left: 30px;
font-size: 2em;
background: yellow;
}
div#sidenav {
position: absolute;
top: 170px;
left: 0px;
width: 200px;
height: 558px;
}
.contentSlide {
display: none;
}
div#bottomnav {
position: absolute;
bottom: 0px;
height: 40px;
width: 100%;
background: pink;
text-align: center;
}
.dots-wrapper {
position: absolute;
bottom: 60px;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 22px 22px;
background-color: #bbb;
border-radius: 50%;
display: block;
transition: background-color 0.6s ease;
}
.active,
.dot:hover {
background-color: #717171;
}
.fade {
-webkit-animation-name: fade;
-webkit-animation-duration: 1.5s;
animation-name: fade;
animation-duration: 1.5s;
}
#-webkit-keyframes fade {
from {
opacity: .4
}
to {
opacity: 1
}
}
#keyframes fade {
from {
opacity: .4
}
to {
opacity: 1
}
}
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: red;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
.prev {
left: 0;
}
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
<div id="minibanner">
<h3>Title of Presentation: testing, testing testing</h3>
</div>
<div id="banner">
<h1>Introduction</h1>
</div>
<div id="sidenav">
<ul>
<li>home</li>
<li>Introduction</li>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
<li>Conclusion</li>
</ul>
</div>
<div id="slideContainer">
<div class="contentSlide fade">
<p>Here's an outline:
<ul>
<li>Introduction</li>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
<li>Conclusion</li>
</ul>
</p>
</div>
<div class="contentSlide fade">
<p>Here are some themes:
<ul>
<li>Theme 1</li>
<li>Theme 2</li>
<li>Theme 3</li>
</ul>
</p>
</div>
<div class="contentSlide fade">
<p>...and the conclusions:
<ul>
<li>Conclusion A</li>
<li>Conclusion B</li>
<li>Conclusion C</li>
<li>Conclusion D</li>
<li>Conclusion E</li>
</ul>
</p>
</div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
<div class="dots-wrapper" style="text-align:center">
<span class="dot" onclick="currentSlide(1)"></span>
<span class="dot" onclick="currentSlide(2)"></span>
<span class="dot" onclick="currentSlide(3)"></span>
</div>
</div>
<div id="bottomnav">
<p>footer</p>
</div>

Your dots (aka pips) have an absolute position so they're all going to overlap. Absolute positioning does exactly what it says and puts things at an exact position. It will ignore the normal "flow" that HTML typically does (also known as "has layout"), even though you've got them displaying as inline-block.
Instead, you should wrap them in a container element and position that accordingly. Then, the pips inside the container will "have layout" and flow side-by-side according to the inline-block display type.
Here's a basic working example
.slideshow {
position: relative;
width: 100%;
height: 80vh;
background: rebeccapurple;
}
.navigation {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center; /* buttons align like text */
}
.pip {
display: inline-block;
width: 10px;
height: 10px;
padding: 0;
border: 0;
border-radius: 9999px;
cursor: pointer;
background: rgba(255, 255, 255, 0.5);
}
.pip--active {
background: rgba(255, 255, 255, 1);
}
<div class="slideshow">
<div class="navigation">
<button type="button" class="pip pip--active"></button>
<button type="button" class="pip"></button>
<button type="button" class="pip"></button>
</div>
</div>
Notice that I've used buttons instead of links for the pips. This is because the pips don't actually link anywhere when clicked; They simply updates the state of the slideshow.

Related

How to animate menu background changing image?

i am trying to animate when i hover a li.. background image will be the zoom out
$(function () {
var image = $('.menu').find('img').attr('src');
$('.menu ul li').mouseover(function () {
var currentImage = $(this).attr('data-img');
$(this).parent().parent().parent().parent().find('img').attr('src', currentImage); })});
::-webkit-scrollbar{display: none; visibility: hidden;}
body{margin: 0; background: burlywood; }
.menu { position: relative; text-align: center; margin: auto; height: 100%; padding-top: 2%; padding-bottom: 10%; z-index: 99;}
.menu li{ display: block; font-size: 1.5rem; font-family: "Raleway SemiBold", Serif, sans-serif; padding-bottom: 20px;}
.menu li+li{margin-top: 30px;}
.menu a{ font-size: 3.5rem;}
.navigationGif{ position: fixed; top: 0; bottom: 0; left: 0; right: 0; animation: menuBG 0.7s ease-in;}
.homeGif{ position: fixed;}
.menu img{ width: 100%; }
#keyframes menuBG { from{ opacity: 0; transform: scale(1.05); }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu">
<div class="navigationGif">
<div class=""> <img src="https://images.unsplash.com/photo-1532109513327-3b32b2a9bd57?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" alt="" class="src"> </div> </div>
<div class="menu"> <div class="data"><ul>
<li>Navigation</li>
<li data-img="https://images.unsplash.com/photo-1532109513327-3b32b2a9bd57?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" class="navLink home active"><span>H</span><span>o</span><span>m</span><span>e</span></li>
<li data-img="https://images.unsplash.com/photo-1589986118236-64c32953ab27?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" class="navLink works">Works</li>
<li data-img="https://images.unsplash.com/photo-1589892889837-e0236f8dd22e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=753&q=80" class="navLink about">About</li>
<li data-img="https://images.unsplash.com/photo-1558567083-b8cb6bb5f7d9?ixlib=rb-1.2.1&auto=format&fit=crop&w=763&q=80" class="navLink contact">Contact</li></ul> </div></div></div>
Try to reset the animation, also avoid too many parent() call as possible by select closest element or create better class names.
So here I make a small modification to get what you need, by add a class name to the background img that trigger animation, every time you change the hover to other menu item (LI element) it will toggle the class name so the animation will restart each time.
$(function () {
var image = $('.menu').find('img').attr('src');
var lastImage
$('.menu ul li.navLink').mouseover(function () {
var currentImage = $(this).attr('data-img');
$('.navigationGif img').attr('src', currentImage);
if(lastImage !== currentImage) {
$('.navigationGif').removeClass('animation')
setTimeout(() => {
$('.navigationGif').addClass('animation')
}, 10);
lastImage = currentImage
}
})
});
::-webkit-scrollbar {
display: none;
visibility: hidden;
}
body {
margin: 0;
background: burlywood;
}
.menu {
position: relative;
text-align: center;
margin: auto;
height: 100%;
padding-top: 2%;
padding-bottom: 10%;
z-index: 99;
}
.menu li {
display: block;
font-size: 1.5rem;
font-family: "Raleway SemiBold", Serif, sans-serif;
padding-bottom: 20px;
}
.menu li+li {
margin-top: 30px;
}
.menu a {
font-size: 3.5rem;
}
.navigationGif {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.navigationGif.animation {
animation: menuBG 0.7s ease-in;
}
.homeGif {
position: fixed;
}
.menu img {
width: 100%;
}
#keyframes menuBG {
from {
opacity: 0;
transform: scale(1.05);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu">
<div class="navigationGif animation">
<div class=""> <img
src="https://images.unsplash.com/photo-1532109513327-3b32b2a9bd57?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80"
alt="" class="src"> </div>
</div>
<div class="menu">
<div class="data">
<ul>
<li>Navigation</li>
<li
data-img="https://images.unsplash.com/photo-1532109513327-3b32b2a9bd57?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80"
class="navLink home active"><a href=""
class="navItem"><span>H</span><span>o</span><span>m</span><span>e</span></a></li>
<li
data-img="https://images.unsplash.com/photo-1589986118236-64c32953ab27?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80"
class="navLink works">Works</li>
<li
data-img="https://images.unsplash.com/photo-1589892889837-e0236f8dd22e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=753&q=80"
class="navLink about">About</li>
<li
data-img="https://images.unsplash.com/photo-1558567083-b8cb6bb5f7d9?ixlib=rb-1.2.1&auto=format&fit=crop&w=763&q=80"
class="navLink contact">Contact</li>
</ul>
</div>
</div>
</div>

toggle text fade when nav slides open and closes

I'm trying to have the nav links slowly fade in when you open the nav and disappear as soon as you click close on the nav. Currently it shows the links instantly and continues to display while they close.
Maybe jQuery toggle? or is there something in CSS I can do?
Codepen: https://codepen.io/mattmcgilton/pen/GRJVBxz
<div class="col-4 d-flex flex-column align-items-end">
<button id="open-btn" onclick="openNav()">Menu</button>
</div>
<nav class="primary__nav">
<div id="myNav" class="overlay">
close
<div class="container overlay-content">
<ul>
<li>this is text 123</li>
<li>this is text 123</li>
<li>this is text 123</li>
<li>this is text 123</li>
</ul>
</div>
</div>
</nav>
function openNav() {
document.getElementById("myNav").style.width = "100%";
document.getElementById("open-btn").style.display = "none";
}
function closeNav() {
document.getElementById("myNav").style.width = "0%";
document.getElementById("open-btn").style.display = "block";
}
body {
background-color: gray;
}
.overlay {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: red;
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
margin-top: 30px;
ul {
padding-left: 0;
li {
padding-bottom: 5rem;
}
}
}
.overlay a {
text-decoration: none;
text-transform: uppercase;
font-size: 30px;
color: red;
display: block;
transition: 0.3s;
letter-spacing: 5px;
#include bodyLight();
}
.overlay .closebtn {
position: absolute;
top: 50px;
right: 70px;
#include bodyBold();
font-size: 12px;
color: black;
}
If I understood your requirement correctly you want have a timer slider in and out? if so you have to set the timer correctly in 'overlay class. At present I have set it for 2 seconds.
function openNav() {
$(".overlay-content").fadeIn(2000);
document.getElementById("myNav").style.width = "100%";
document.getElementById("open-btn").style.display = "none";
}
function closeNav() {
$(".overlay-content").fadeOut(500);
document.getElementById("myNav").style.width = "0%";
document.getElementById("open-btn").style.display = "block";
}
body {
background-color: gray;
}
elementToFadeInAndOut {
animation: fadeInOut 4s linear forwards;
}
.overlay {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: red;
overflow-x: hidden;
transition: 2s;
/* here */
}
.overlay-content {
position: relative;
top: 25%;
margin-top: 30px;
display:none;
ul {
padding-left: 0;
li {
padding-bottom: 5rem;
}
}
}
.overlay a {
text-decoration: none;
text-transform: uppercase;
font-size: 30px;
color: red;
display: block;
transition: 0.3s;
letter-spacing: 5px;
#include bodyLight();
}
.overlay .closebtn {
position: absolute;
top: 50px;
right: 70px;
#include bodyBold();
font-size: 12px;
color: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="col-4 d-flex flex-column align-items-end">
<button id="open-btn" onclick="openNav()">Menu</button>
</div>
<nav class="primary__nav">
<div id="myNav" class="overlay">
close
<div id="hide" class="container overlay-content">
<ul>
<li>this is text 123</li>
<li>this is text 123</li>
<li>this is text 123</li>
<li>this is text 123</li>
</ul>
</div>
</div>
</nav>
I made a simple fade-in animation which you can attach to any element via a class (element.classList.add("fadeIn")) on opening the nav and removing it (element.classList.remove("fadeIn")) on nav close. For hiding the text immediately, you can make a hidden class which will have display: none and use it in the same way.
.fadeIn{
animation: fadeIn 1s ease-in;
}
#keyframes fadeIn{
from {
opacity:0
}
to {
opacity:1
}
}

Align divs next to each other CSS (Cards Style)

I'm trying to align cards that are wrapped up in divs. What I want to do is align those cards beside each other until it reaches maximum screen width, then I want it to move to the next line automatically.
The problem is that once I copy the html code, the new copied card spawns on top of the previous card rather than next to each other.
HTML:
<div class="fighter-card">
<div class="front active">
<div class="ranking-position">1</div>
<div class="more">
<i class="fa fa-info-circle" aria-hidden="true"></i>
</div>
<div class="fighter-picture">
<img src="~/images/Resources/RankingsPhotos/Lomachenko.png" />
</div>
<ul class="information">
<li>
<div class="information-left">Name:</div>
<div class="information-right">aa</div>
</li>
<li>
<div class="information-left">Weight:</div>
<div class="information-right">aa</div>
</li>
<li>
<div class="information-left">Belts:</div>
<div class="information-right">aa</div>
</li>
</ul>
</div>
<div class="back">
<div class="go-back">
<i class="fa fa-chevron-circle-left" aria-hidden="true"></i>
</div>
<ul class="information">
<li>
<div class="information-left">Yesterday</div>
<div class="information-right">9<sup>o</sup></div>
</li>
<li>
<div class="information-left">Today</div>
<div class="information-right">9<sup>o</sup></div>
</li>
<li>
<div class="information-left">None of your business</div>
<div class="information-right">9<sup>o</sup></div>
</li>
<li>
<div class="information-left">Yesterday</div>
<div class="information-right">9<sup>o</sup></div>
</li>
<li>
<div class="information-left">Today</div>
<div class="information-right">9<sup>o</sup></div>
</li>
<li>
<div class="information-left">aa</div>
<div class="information-right">9<sup>o</sup></div>
</li>
</ul>
</div>
</div>
<div class="fighter-card">
//Next div with the same content for testing
</div>
CSS:
.fighter-card {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
min-height: 400px;
}
.fighter-card .front {
width: 100%;
height: 100%;
background: #171717;
padding: 30px;
box-sizing: border-box;
transition: .5s;
transform-origin: right;
float: left;
}
.ranking-position {
font-weight: bold;
width: 50%;
text-align: left;
float: left;
color: #fff;
font-size: 40px;
}
.more {
width: 50%;
text-align: right;
cursor: pointer;
float: right;
font-size: 24px;
color: #fff;
display: block;
}
.fighter-picture {
background-size: cover;
}
.information {
margin: 0;
padding: 0;
}
.information li {
padding: 10px 0;
border-bottom: 2px solid #fff;
display: flex;
font-weight: bold;
cursor: pointer;
color: #fff;
}
.information li:last-child {
border-bottom: none;
}
.information li .information-left {
width: 50%;
}
.information li .information-right {
width: 50%;
text-align: right;
}
.fighter-card .back {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 30px;
background: rgba(0,0,0,0.7);
box-sizing: border-box;
transform-origin: left;
transition: .5s;
transform: translateX(100%) rotateY(90deg);
}
.fighter-card .back.active {
transform: translateX(0) rotateY(0deg);
}
.fighter-card .front.active {
transform: translateX(0) rotateY(0deg);
}
.fighter-card .front {
transform: translateX(-100%) rotateY(90deg);
}
.go-back {
font-size: 24px;
color: #fff;
text-align: right;
}
.go-back .fa {
cursor: pointer;
}
Javascript:
<script type="text/javascript">
$(document).ready(function () {
$('.more').click(function () {
$('.back').addClass('active')
$('.front').removeClass('active')
});
$('.go-back').click(function () {
$('.back').removeClass('active')
$('.front').addClass('active')
});
});
I know it's a lot of code here entered. Just want to make sure that everything that could be related to this problem is included.
Thanks in advance.
If you use absolute positioning and specify the location, then you should do that for each card. If not, let the browser do the positioning by using display: inline-block or float: left (if there is other content on the line).

JQuery Hover Flicker On Dropdowns

I'm trying to toggle between the categories in the JSFiddle below, it works fine aside from there's a flicker when hides and shows the new content.
Is there a way to fix this?
https://jsfiddle.net/0q7fzh6u/1/
Cheers
// Overlay dropdown menu
var menuItem = $(".header-categories-item");
var categoriesDropdown = $(".header-categories-dropdown");
menuItem.hover(function() {
$("body").toggleClass("overlay-visible");
$(this).children(categoriesDropdown).toggleClass("categories-dropdown-visible");
});
.header-categories {
position: relative;
clear: both;
background: #fff;
z-index: 10;
}
.header-categories-list {
margin-bottom: 0;
}
.header-categories-item {
display: inline-block;
vertical-align: top;
letter-spacing: 0.2rem;
line-height: 1;
font-size: 13px;
padding-top: 15px;
padding-bottom: 15px;
padding-left: 15px;
padding-right: 15px;
}
.header-categories-item a {
color: #000;
}
.header-categories-item-block {
display: block;
padding: 0;
border-top: 1px solid $black;
}
/* overlay */
#site-overlay {
visibility: hidden;
opacity: 0;
z-index: 5;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #999;
transition: .25s;
}
.overlay-visible #site-overlay {
visibility: visible;
opacity: 1;
}
/* Dropdown */
.header-categories-dropdown {
visibility: hidden;
opacity: 0;
position: absolute;
top: 100%;
left: 0;
width: 100%;
min-height: 300px;
padding: 15px 0;
background: #fff;
}
li {
padding-bottom: 15px;
padding-left: 15px;
padding-right: 15px;
}
.header-categories-dropdown.categories-dropdown-visible {
visibility: visible;
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML
<div id="site-overlay"></div>
<div class="header-categories pull-right hidden-xs hidden-sm">
<ul class="header-categories-list list-unstyled">
<li class="header-categories-item header-categories-item-active">category name 1
<ul class="header-categories-dropdown list-unstyled">
<li>test 1</li>
<li>test 2</li>
</ul>
</li>
<li class="header-categories-item header-categories-item-active">category name 2
<ul class="header-categories-dropdown list-unstyled">
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
</ul>
</div>
What's causing this problem is that there is a gap between the li tags .header-categories-item, so whenever you hover over this gap you get the flick
You can remove the gap by adding margin-right: -5px; to .header-categories-item
See updated fiddle
If you remove the whitespace between the two li-tags, the flicker is gone.
I don't know how to remove the gap in CSS, though. Removing it by margin-right: -5px as Chiller has proposed seems not very reliable to me - maybe the gap is smaller or bigger in a different browser?
Edit
Found a solution: You can set font-size: 0; on the ul to remove the gap.
// Overlay dropdown menu
var menuItem = $(".header-categories-item");
var categoriesDropdown = $(".header-categories-dropdown");
menuItem.hover(function() {
$("body").toggleClass("overlay-visible");
$(this).children(categoriesDropdown).toggleClass("categories-dropdown-visible");
});
.header-categories {
position: relative;
clear: both;
background: #fff;
z-index: 10;
}
.header-categories-list {
margin-bottom: 0;
font-size: 0;
}
.header-categories-item {
display: inline-block;
vertical-align: top;
letter-spacing: 0.2rem;
line-height: 1;
font-size: 13px;
padding-top: 15px;
padding-bottom: 15px;
padding-left: 15px;
padding-right: 15px;
}
.header-categories-item a {
color: #000;
}
.header-categories-item-block {
display: block;
padding: 0;
border-top: 1px solid $black;
}
/* overlay */
#site-overlay {
visibility: hidden;
opacity: 0;
z-index: 5;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #999;
transition: .25s;
}
.overlay-visible #site-overlay {
visibility: visible;
opacity: 1;
}
/* Dropdown */
.header-categories-dropdown {
visibility: hidden;
opacity: 0;
position: absolute;
top: 100%;
left: 0;
width: 100%;
min-height: 300px;
padding: 15px 0;
background: #fff;
}
li {
padding-bottom: 15px;
padding-left: 15px;
padding-right: 15px;
}
.header-categories-dropdown.categories-dropdown-visible {
visibility: visible;
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML
<div id="site-overlay"></div>
<div class="header-categories pull-right hidden-xs hidden-sm">
<ul class="header-categories-list list-unstyled">
<li class="header-categories-item header-categories-item-active">category name 1
<ul class="header-categories-dropdown list-unstyled">
<li>test 1</li>
<li>test 2</li>
</ul>
</li>
<li class="header-categories-item header-categories-item-active">category name 2
<ul class="header-categories-dropdown list-unstyled">
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
</ul>
</div>
So either this, or you remove the whitespace in the HTML code:
<!-- ... -->
</li><li class="header-categories-item header-categories-item-active">
<!-- ... -->
// Overlay dropdown menu
var menuItem = $(".header-categories-item");
var categoriesDropdown = $(".header-categories-dropdown");
menuItem.hover(function() {
$("body").toggleClass("overlay-visible");
$(this).children(categoriesDropdown).toggleClass("categories-dropdown-visible");
});
.header-categories {
position: relative;
clear: both;
background: #fff;
z-index: 10;
}
.header-categories-list {
margin-bottom: 0;
}
.header-categories-item {
display: inline-block;
vertical-align: top;
letter-spacing: 0.2rem;
line-height: 1;
font-size: 13px;
padding-top: 15px;
padding-bottom: 15px;
padding-left: 15px;
padding-right: 15px;
}
.header-categories-item a {
color: #000;
}
.header-categories-item-block {
display: block;
padding: 0;
border-top: 1px solid $black;
}
/* overlay */
#site-overlay {
visibility: hidden;
opacity: 0;
z-index: 5;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #999;
transition: .25s;
}
.overlay-visible #site-overlay {
visibility: visible;
opacity: 1;
}
/* Dropdown */
.header-categories-dropdown {
visibility: hidden;
opacity: 0;
position: absolute;
top: 100%;
left: 0;
width: 100%;
min-height: 300px;
padding: 15px 0;
background: #fff;
}
li {
padding-bottom: 15px;
padding-left: 15px;
padding-right: 15px;
}
.header-categories-dropdown.categories-dropdown-visible {
visibility: visible;
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML
<div id="site-overlay"></div>
<div class="header-categories pull-right hidden-xs hidden-sm">
<ul class="header-categories-list list-unstyled">
<li class="header-categories-item header-categories-item-active">category name 1
<ul class="header-categories-dropdown list-unstyled">
<li>test 1</li>
<li>test 2</li>
</ul>
</li><li class="header-categories-item header-categories-item-active">category name 2
<ul class="header-categories-dropdown list-unstyled">
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
</ul>
</div>
Both work, but I'd prefer the CSS solution (or both).

Messy mouse events in chrome

In IE or Firefox the site works like this (IE11):
(Tabs are clickable)
but not in chrome. Click on tabs not get fired. I tried to reveal element in Developer Tools, but it reveals #container element instead of the lielement I clicked on.
It looks like the layering of the elements are not the same as you see it and when you raise an event (ex.: click). The first/parent div is the top element and the tabs (li) are nested behind.
Why is it working in IE and Firefox, and why does not in Chrome? What is the differecnce?
$('button').click(function() {
$('.box').toggleClass('flipped');
})
$('li').click(function() {
var text = 'You selected ' + $(this).html();
alert(text);
});
* {
margin: 0;
padding: 0
}
button {
position: fixed;
right: 5px;
bottom: 5px;
}
.box {
position: relative;
width: 300px;
height: 300px;
transform-origin: right center;
transition-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
transition: all 300ms, transform 500ms ease;
}
.box figure {
position: absolute;
width: 100%;
height: 100%;
transition: visibility 0s ease 140ms;
}
.box:not(.flipped) figure.back {
visibility: hidden;
}
.box.flipped {
transform: translateX(-100%) rotateY(-180deg);
}
.box .front {
background-color: skyblue;
}
.box .back {
transform: rotateY(180deg);
background-color: lightgreen;
}
.box .back .nav {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 32px;
width: 100%;
background-color: skyblue;
text-align: center;
}
.box .back .nav li {
background-color: white;
width: 24%;
display: inline-block;
height: 30px;
line-height: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class='box'>
<figure class='front'>
<p>FRONT SIDE</p>
</figure>
<figure class='back'>
<ul class='nav'>
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
</ul>
<div class='content'>
<p>BACK SIDE</p>
</div>
</figure>
</div>
</div>
<button>FLIP</button>
Thanks in advance for any help!
To be 100% saint with your work, wrap your JS code in
$(document).ready(function(){ ... })
Secondly I would not advise to use such big qualifiers $('li'). This will scan every list element in DOM tree-slow and not advised. Here you are interested in list elements from menu only.
I would also find Flip button by id, you have only one button, so it doesn't cost much:)
I would propose something like this :
var navContainer = $('.box > figure.back > ul.nav');
navContainer.on('click', 'li', function(){ ... })
This code should work, even when you add more li items to DOM.
Secondly you could in debug mode find, if this navContainer has been found or not.
I found a workaround for my problem. If I set z-index: 0 and position: relative to body and the body > div then clicks get fired.
SOLUTION : CSS
body, body > div { position: relative; z-index: 0; }
$('button, .front').click(function() {
$('.box').toggleClass('flipped');
})
$('li').click(function() {
var text = 'You selected ' + $(this).html();
alert(text);
});
/*Workaround*/
body,
body > div {
position: relative;
z-index: 0;
}
/************/
* {
margin: 0;
padding: 0
}
button {
position: fixed;
right: 5px;
bottom: 5px;
}
.box {
position: relative;
width: 300px;
height: 300px;
transform-origin: right center;
transition-timing-function: cubic-bezier(1.000, 0.000, 0.000, 1.000);
transition: all 300ms, transform 500ms ease;
}
.box figure {
position: absolute;
width: 100%;
height: 100%;
transition: visibility 0s ease 140ms;
}
.box:not(.flipped) figure.back {
visibility: hidden;
}
.box.flipped {
transform: translateX(-100%) rotateY(-180deg);
}
.box .front {
background-color: skyblue;
}
.box .back {
transform: rotateY(180deg);
background-color: lightgreen;
}
.box .back .nav {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 32px;
width: 100%;
background-color: skyblue;
text-align: center;
}
.box .back .nav li {
background-color: white;
width: 24%;
display: inline-block;
height: 30px;
line-height: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='container'>
<div class='box'>
<figure class='front'>
<p>FRONT SIDE</p>
</figure>
<figure class='back'>
<ul class='nav'>
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
</ul>
<div class='content'>
<p>BACK SIDE</p>
</div>
</figure>
</div>
</div>
<button>FLIP</button>

Categories