z-index does not work with nested absolute elements - javascript

I am trying to develop a dropdown which contains a ul list that is expandable. An element of the list is visible by default. When the list is expanded, all the elements should be visible and it should be positioned over the dropdown. I attached the snippet and as you can see, the list expands but the li elements are not over the dropdown, even though the ul has an absolute position and a greater z-index.
var dropdown = false;
var list = false;
function toggleList () {
toggle('.hidden', list);
list = !list;
}
function toggleDropdown () {
toggle('.dropdown', dropdown);
dropdown = !dropdown;
}
function toggle (selector, isAlreadyOpened) {
if(isAlreadyOpened) $(selector).hide();
else $(selector).show();
}
.parent {
position: relative;
background-color: red;
width: 50%;
}
.dropdown {
width: 40%;
height: 100px;
background-color: blue;
display: none;
position: absolute;
right: 0;
z-index: 10;
overflow: hidden;
}
.list {
position: absolute;
z-index: 20;
}
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<button onclick="toggleDropdown()">Toggle dropdown</button>
<div class="dropdown">
First Dropdown
<button onclick="toggleList()">Toggle list</button>
<ul class="list">
<li>1st element</li>
<li class="hidden">2nd element</li>
<li class="hidden">3rd element</li>
<li class="hidden">4th element</li>
<li class="hidden">5th element</li>
<li class="hidden">6th element</li>
</ul>
</div>
</div>
Someone knows how to help on this?
Thanks!

Remove overflow: hidden from .dropdown and there you go!
var dropdown = false;
var list = false;
function toggleList () {
toggle('.hidden', list);
list = !list;
}
function toggleDropdown () {
toggle('.dropdown', dropdown);
dropdown = !dropdown;
}
function toggle (selector, isAlreadyOpened) {
if(isAlreadyOpened) $(selector).hide();
else $(selector).show();
}
.parent {
position: relative;
background-color: red;
width: 50%;
}
.dropdown {
width: 40%;
height: 100px;
background-color: blue;
display: none;
position: absolute;
right: 0;
z-index: 10;
}
.list {
position: absolute;
z-index: 20;
}
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<button onclick="toggleDropdown()">Toggle dropdown</button>
<div class="dropdown">
First Dropdown
<button onclick="toggleList()">Toggle list</button>
<ul class="list">
<li>1st element</li>
<li class="hidden">2nd element</li>
<li class="hidden">3rd element</li>
<li class="hidden">4th element</li>
<li class="hidden">5th element</li>
<li class="hidden">6th element</li>
</ul>
</div>
</div>

Well, I actually feel a bit dumb. I came back to my code and I noticed the overflow: hidden on the .dropdown element. I removed it and it fixed the issue.

Related

Delete object with javascript

I have designed a small panel using the following code, which will display the content to the user by clicking on it:
$('.body_panel').find('li').click(function() {
if ($(this).has("ul")) {
$(this).children('.icon-title-right_panel').hide();
$(this).children('.icon-title-down_panel').show();
} else {
$(this).children('.icon-title-right_panel').show();
$(this).children('.icon-title-down_panel').hide();
}
});
$('.MyPanel').find('li').click(function(evt) {
evt.stopPropagation();
$(this).children('ul').slideToggle();
});
.MyPanel ul li {
cursor: pointer;
position: relative;
}
.MyPanel ul li .icon-title-right_panel,
.MyPanel ul li .icon-title-down_panel {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
}
.MyPanel ul li .icon-title-down_panel {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"/>
<div class="MyPanel">
<ul class="body_panel">
<li class="title_panel">
<h5>title</h5>
<span class="fas fa-circle-chevron-right icon-title-right_panel"></span>
<span class="fas fa-circle-chevron-down icon-title-down_panel"></span>
<ul class="box-contect_panel">
<li class="contect_panel">
<h1>contect</h1>
</li>
</ul>
</li>
</ul>
</div>
By clicking on the title of any icon on the right side, it will be removed. and it appears by clicking again.
As I specified in the script code; What alternative code should I write to delete the icon on the right by clicking on the title and the icon on the bottom appears instead?
Please try to do like this. the key is to catch the toggle status when you click li.
$('.body_panel').find('li').click(function() {
if($(this).parent().find("ul").eq(0).is(':visible')) {
$(this).children('.icon-title-right_panel').show();
$(this).children('.icon-title-down_panel').hide();
} else {
$(this).children('.icon-title-right_panel').hide();
$(this).children('.icon-title-down_panel').show();
}
});
$('.MyPanel').find('li').click(function(evt) {
evt.stopPropagation();
$(this).children('ul').slideToggle();
});
.MyPanel ul li {
cursor: pointer;
position: relative;
}
.MyPanel ul li .icon-title-right_panel,
.MyPanel ul li .icon-title-down_panel {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"/>
<div class="MyPanel">
<ul class="body_panel">
<li class="title_panel">
<h5>title</h5>
<span class="fas fa-circle-chevron-right icon-title-right_panel"></span>
<span class="fas fa-circle-chevron-down icon-title-down_panel"></span>
<ul class="box-contect_panel">
<li class="contect_panel">
<h1>contect</h1>
</li>
</ul>
</li>
</ul>
</div>

Change which image is displayed on hover and click

I'm not a developer. I've been however tasked with coming up with a solution for a small project at work with jQuery and I have no clue where to begin. Here's my codepen: https://codepen.io/axo1/pen/mdBLRjL
What I need to is this (all graphics and texts are placeholders):
What I managed to achieve
Image item1 is supposed to be the first visible,
Hovering on the buttons below the graphic changes which image is displayed,
What I don't know how to achieve
The buttons below should be clickable. Clicking on a button changes the "active" graphic above. For example: if I click on the Second item button, the item2 image will be displayed even after I unhover the button, and so forth.
Any tips of what I should look into?
Unfortunately jQuery is heavily preferred here.
$(document).on({
mouseenter: function() {
$(".item1").toggleClass("active hidden");
$(".item2").toggleClass("hidden");
},
mouseleave: function() {
$(".item1").toggleClass("active hidden");
$(".item2").toggleClass("hidden");
}
}, ".item2btn");
$(document).on({
mouseenter: function() {
$(".item1").toggleClass("active hidden");
$(".item3").toggleClass("hidden");
},
mouseleave: function() {
$(".item1").toggleClass("active hidden");
$(".item3").toggleClass("hidden");
}
}, ".item3btn");
img {
max-width: 15%;
position: absolute;
top: 0;
left: 0;
}
.hidden {
visibility: hidden;
}
.active {
visibility: visible;
}
#container {
display: flex;
justify-content: flex-start;
align-items: center;
color: white;
position: absolute;
top: 250px;
}
#container ul {
padding: 1em;
}
#container ul>li {
background: black;
margin: 1em;
padding: 1em;
list-style-type: none;
display: inline;
}
#container ul>li:hover {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<img src="https://www.models-resource.com/resources/big_icons/13/12406.png" class="active items item1">
<img src="https://banner2.cleanpng.com/20180410/rce/kisspng-the-legend-of-zelda-majora-s-mask-hyrule-warriors-the-legend-of-zelda-5acc7b7a4870f6.4303262815233503942967.jpg" class="hidden items item2">
<img src="https://i.pinimg.com/originals/4a/a5/df/4aa5df83115df6c96732a2d76ccb4f1b.jpg" class="hidden items item3">
<div id="container">
<ul>
<li class="item1btn">First item</li>
<li class="item2btn">Second item</li>
<li class="item3btn">Third item</li>
</ul>
</div>
Here is a working version
I kept your style - I think it can be shortened to be more DRY
const $images = $(".items")
let $currentItem = $(".items").eq(0)
$("#container li").on({
"click": function() {
const id = $(this).data("id").replace("btn", "");
$images
.removeClass("active")
.addClass("hidden")
$currentItem = $(`.${id}`)
.removeClass("hidden")
.addClass("active");
},
"mouseover": function() {
const id = $(this).data("id").replace("btn", "");
$images
.removeClass("active")
.addClass("hidden")
$(`.${id}`)
.removeClass("hidden")
.addClass("active");
},
"mouseout": function() {
$images
.removeClass("active")
.addClass("hidden")
$currentItem
.removeClass("hidden")
.addClass("active");
}
})
img {
max-width: 15%;
position: absolute;
top: 0;
left: 0;
}
.hidden {
visibility: hidden;
}
.active {
visibility: visible;
}
#container {
display: flex;
justify-content: flex-start;
align-items: center;
color: white;
position: absolute;
top: 250px;
}
#container ul {
padding: 1em;
}
#container ul>li {
background: black;
margin: 1em;
padding: 1em;
list-style-type: none;
display: inline;
}
#container ul>li:hover {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<img src="https://www.models-resource.com/resources/big_icons/13/12406.png" class="active items item1">
<img src="https://banner2.cleanpng.com/20180410/rce/kisspng-the-legend-of-zelda-majora-s-mask-hyrule-warriors-the-legend-of-zelda-5acc7b7a4870f6.4303262815233503942967.jpg" class="hidden items item2">
<img src="https://i.pinimg.com/originals/4a/a5/df/4aa5df83115df6c96732a2d76ccb4f1b.jpg" class="hidden items item3">
<div id="container">
<ul>
<li data-id="item1">First item</li>
<li data-id="item2">Second item</li>
<li data-id="item3">Third item</li>
</ul>
</div>

dropdown menu not opening and closing correctly

I have gotten it to open and close when hovering over the nav link but how do I keep it open so I can access the content on the menu? I need it to work exactly how a dropdown menu works.
This is what I have done so far I also need the html layout to stay the same.
$('.nav-link--dropdown').mouseover(function() {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown').mouseleave(function() {
$('.dropdown-menu').css('display', 'none');
});
ul {
list-style: none;
padding: 0px;
display: flex;
}
li {
margin-right: 10px;
}
.dropdown-menu {
display: none;
}
.dropdown-menu ul {
display: block;
background-color: grey;
color: white;
padding: 10px;
text-align: center;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
<ul>
<li class="nav-link">home</li>
<li class="nav-link--dropdown">dropdown</li>
</ul>
</div>
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
View on jsFiddle
Should remove margin use padding for that, if not when we enter that margin area mouse leave event will trigger.
$('.nav-link--dropdown').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.dropdown-menu').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
$('.dropdown-menu').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
ul {
list-style: none;
padding: 0px;
display: flex;
}
li {
padding: 10px;
}
.dropdown-menu {
display: none;
}
.dropdown-menu ul {
display: block;
background-color: grey;
color: white;
padding: 10px;
text-align: center;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="nav">
<ul>
<li class="nav-link">home</li>
<li class="nav-link--dropdown">dropdown</li>
</ul>
</div>
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
The problem you have here is that you leave the nav-link--dropdown when you move to your dropdown-menu. The simple solution: Include your dropdown-menu in your nav item.
$('.nav-link--dropdown').mouseover(function() {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown').mouseleave(function() {
$('.dropdown-menu').css('display', 'none');
});
ul {
list-style: none;
padding: 0px;
display: flex;
}
li {
margin-right: 10px;
}
.dropdown-menu {
display: none;
}
.dropdown-menu ul {
display: block;
background-color: grey;
color: white;
padding: 10px;
text-align: center;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
<ul>
<li class="nav-link">home</li>
<li class="nav-link--dropdown">
dropdown
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
</li>
</ul>
</div>
You can achieve this by bundling the menu item you want to hover over and it's dropdown in the same div.
<div class="nav">
<ul>
<li class="nav-link">home</li>
<div class="innerNav">
<li class="nav-link--dropdown">dropdown</li>
<div class="dropdown-menu">
<ul>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
<li class="dropdown-menu__link">random text</li>
</ul>
</div>
</div>
</ul>
</div>
And:
$('.innerNav').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.innerNav').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
See this JSFiddle: https://jsfiddle.net/rmdfqh6c/
Since your problem is the mouseleave event will trigger when you try to move the mouse to the bellow dropdown menu, if you really must keep the elements separated, add the dropdown-menu to the class that keeps the display:block
$('.nav-link--dropdown, .dropdown-menu').mouseover(function () {
$('.dropdown-menu').css('display', 'block');
});
$('.nav-link--dropdown, .dropdown-menu').mouseleave(function () {
$('.dropdown-menu').css('display', 'none');
});
And remove margin/padding from menu items. Use line-height instead if you want some spacing:
.nav ul li {
line-height: 40px;
}
ul {
list-style: none;
margin: 0; // <--- I changed this from padding: 0px;
display: flex;
}
Otherwise the other suggested solutions to include the dropdown within you parent <ul> element is the best.
JSFiddle

Need aid on Javascript dropdown menu

So essentially I can't figure out why this menu won't dropdown when I click on the hamburger icon, any help will be greatly appreciated
Javascript:
function myFunction(){
var hamburger=document.getElementById('nav-btn')
var dropdownContent=document.getElementsByClassName('nav')
hamburger.onclick=dropdownContent.classList.toggle("show");
//or hamburger.onclick=dropdownContent.style.display("block");
}
CSS:
#nav-btn {
display: none;
}
#media (max-width: 1099px) {
li {
display: none;
}
#nav-btn {
display: inline;
position: absolute;
right: 10px;
bottom: 110px;
}
#nav-btn:hover {
content: url('Menu.png');
}
HTML:
<html>
<body>
<span id="nav-btn"><image src="Menugreen.png" input type="button" onclick="myFunction()"/></span>
<div class="nav">
<ul>
<li id="Programs"> Programs </li>
<li> T-Shirts </li>
<li> About </li>
</ul>
</div>
</body>
</html>
Again I am just asking for advice on why the dropdown span id of nav-btn doesn't dropdown the content of ul everything else works fine. Thank you!
You are trying to toggle the show class, but don't have a show class defined. toggleClass() is for adding or removing a CSS class by its name.
// Get DOM references
var hamburger = document.getElementById('nav-btn')
var dropdownContent = document.querySelector('.nav')
// Set up event handler
hamburger.addEventListener("click", function(){
dropdownContent.classList.toggle("hide");
});
#nav-btn {
display: none;
}
#media (max-width: 1099px) {
.hide {
display: none;
}
#nav-btn {
display: inline;
position: absolute;
right: 10px;
bottom: 110px;
}
/* Change the image when you hover over the image, not the span*/
#nav-btn > img:hover {
content: url('Menu.png');
}
}
<span id="nav-btn">
<image src="Menugreen.png" alt="menu">
<input type="button" value=" - - -">
</span>
<div class="nav">
<ul>
<li id="Programs">Programs</li>
<li> T-Shirts </li>
<li> About </li>
</ul>
</div>

Floated elements jump when hiding another floated elements

I have grid of floated elements, for which I created a filter. I want this filter to hide and show the items and while doing so I want the items to re adjust with transitions and fades.. At the moment the items just jump around.
As you can see here:
JSFIDDLE
How can I make the items slide to their position?
Heres the code:
HTML
<ul class="filters">
<li data="1">filter 1</li>
<li data="2">filter 2</li>
<li data="3">filter 3</li>
<li data="4">filter 4</li>
</ul>
<br>
<ul class="items">
<li data="1">1</li>
<li data="2">2</li>
<li data="1">3</li>
<li data="3">4</li>
<li data="4">5</li>
<li data="2">6</li>
<li data="3">7</li>
<li data="4">8</li>
</ul>
CSS
ul {
list-style: none;
padding: 0;
}
.filters li {
float:left;
margin-right: 10px;
cursor: pointer;
}
.items li {
width: 100px;
height: 100px;
background: #ccc;
float: left;
margin: 20px;
}
JQUERY
$(document).ready( function() {
$('.filters li').click( function () {
var data;
data = $(this).attr('data');
$('.items li').each( function() {
if($(this).attr('data') !== data) {
$(this).fadeOut();
}
else {
$(this).fadeIn();
}
});
});
});
As I mentioned in the comments you would need a different operation than fadeIn/Out as that involves the display property and that cannot be animated or transitioned.
Animating non-display values seems more optimal.
Something like this:
$(document).ready(function() {
$('.filters li').click(function() {
var data;
data = $(this).attr('data');
$('.items li').each(function() {
if ($(this).attr('data') !== data) {
$(this).addClass('hidden');
} else {
$(this).removeClass('hidden');
}
});
});
});
ul {
list-style: none;
padding: 0;
}
.filters li {
float: left;
margin-right: 10px;
cursor: pointer;
}
.items li {
width: 100px;
height: 100px;
background: #ccc;
float: left;
margin: 20px;
transition: all .5s ease;
}
li.hidden {
height: 0;
width: 0;
margin: 0;
opacity: 0;
font-size: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="filters">
<li data="1">filter 1</li>
<li data="2">filter 2</li>
<li data="3">filter 3</li>
<li data="4">filter 4</li>
</ul>
<br>
<ul class="items">
<li data="1">1</li>
<li data="2">2</li>
<li data="1">3</li>
<li data="3">4</li>
<li data="4">5</li>
<li data="2">6</li>
<li data="3">7</li>
<li data="4">8</li>
</ul>
You could set a delay for the fade in to ensure the fade out has completed.
The 500ms delay below is is a slightly longer duration as the fade in.
$(document).ready(function() {
$('.filters li').click(function() {
var data;
data = $(this).attr('data');
$('.items li').each(function() {
if ($(this).attr('data') !== data) {
$(this).fadeOut();
} else {
$(this).delay(525).fadeIn();
}
});
});
});
ul {
list-style: none;
padding: 0;
}
.filters li {
float: left;
margin-right: 10px;
cursor: pointer;
}
.items li {
width: 100px;
height: 100px;
background: #ccc;
float: left;
margin: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="filters">
<li data="1">filter 1</li>
<li data="2">filter 2</li>
<li data="3">filter 3</li>
<li data="4">filter 4</li>
</ul>
<br>
<ul class="items">
<li data="1">1</li>
<li data="2">2</li>
<li data="1">3</li>
<li data="3">4</li>
<li data="4">5</li>
<li data="2">6</li>
<li data="3">7</li>
<li data="4">8</li>
</ul>
It's the overlap of fadeOut and fadeIn that makes it look like they are jumping.
Try hiding the filtered out items quick and slideDown the applicable boxes:
$(document).ready( function() {
$('.filters li').click( function () {
var data;
data = $(this).attr('data');
$('.items li').each( function() {
if($(this).attr('data') !== data) {
$(this).slideUp();
}
else {
$(this).delay(525).slideDown();
}
});
});
});

Categories

Resources