2

I have a problem with a z-index change with js: I have a bunch of cards

.card
{
    background: rgb(70, 70, 70);
    width: 300px;
    padding-bottom: 10px;
    float: left;
    margin: 100px 5px 0 5px;
    opacity: 0;
    box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
    transition: 1s;
    z-index: -1 !important;
}

and I change some properties with js:

window.onload = function()
{
    var cards = document.querySelectorAll(".card");
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].style.margin = "0 5px 0 5px";
        cards[i].style.opacity = "1";
    }
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].style.transition = ".4s";
    }
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].onmouseover = function()
        {
            cards[i].style.zIndex = "9";
            cards[i].style.transform = "scale(1.1)";
        }
        cards[i].onmouseout = function()
        {
            cards[i].style.zIndex = "-1";
            cards[i].style.transform = "scale(1)";
        }
    }
}

If you hover the first card everything is fine, it goes over the second one but as soon as I hover the second one and try to hover over the first one again it breaks: Gif for a better understanding of my problem

I am not an expert in js so if something is horribly wrong point it out but don't be mean.

I've tried the !important tag in the default CSS but it didn't do anything when I inspect the elements the second card keeps the z-index: -1 and the first card has the z-index: 9 but it still draws it beneath it. I've also tried to set the card[i + 1] to -1 before setting the card[i] to 9 but it did not work.

I've stumbled upon the setAttribute() for the style but it looks like it overrides all the other CSS and that would result in a long string of text in my case ("haven't tested if I put all the CSS in that if it works because it seemed like an ugly solution")

I am out of ideas... P.S. not allowed to use jQuery or another external library.

EDIT code snippet:

window.onload = function()
{
    var cards = document.querySelectorAll(".card");
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].style.margin = "0 5px 0 5px";
        cards[i].style.opacity = "1";
    }
    setTimeout(1000);
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].style.transition = ".4s";
    }
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].onmouseover = function()
        {
            cards[i].style.zIndex = "9";
            cards[i].style.transform = "scale(1.1)";
        }
        cards[i].onmouseout = function()
        {
            cards[i].style.zIndex = "-1";
            cards[i].style.transform = "scale(1)";
        }
    }
}
.card
{
    background: rgb(70, 70, 70);
    width: 300px;
    padding-bottom: 10px;
    float: left;
    margin: 100px 5px 0 5px;
    opacity: 0;
    box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
    transition: 1s;
    z-index: -1;
}
.card:hover
{
    box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
}
.card > img
{
    width: 300px;
}
.card-title
{
    margin-top: 5px;
    font-family: 'Roboto', sans-serif;
    font-weight: 900;
}
.card-text
{
    margin-top: 5px;
    font-family: 'Roboto', sans-serif;
    font-weight: 400;
}
<div class="card">
                <img src="https://flipsy.com/blog/images/OldGameConsoles99.jpg">
                <div class="card-title">
                    Consoles
                </div>
                <div class="card-text">
                    some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text 
                </div>
            </div>
<div class="card">
                <img src="https://flipsy.com/blog/images/OldGameConsoles99.jpg">
                <div class="card-title">
                    Consoles
                </div>
                <div class="card-text">
                    some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text some random text 
                </div>
            </div>
Dddsasul
  • 85
  • 2
  • 10
  • It's much simpler to set up CSS classes ahead of time and then just add/remove/toggle them with `element.classList.add()`, `element.classList.remove()` and `element.classList.toggle()`. – Scott Marcus Nov 21 '18 at 17:05
  • Also, your GIF doesn't really illustrate a problem. It seems like hovering over either card scales that card and then hovering the other does the same to that card. Then going back to the first card seems to work again. – Scott Marcus Nov 21 '18 at 17:07
  • [CSS Overrides](https://css-tricks.com/override-inline-styles-with-css/) `!important` will override all inline styles set on the element. – pmkro Nov 21 '18 at 17:07
  • @ScottMarcus I wasn't. Its in his `.card` class. Its what's causing the issue. – pmkro Nov 21 '18 at 17:09
  • Also, your first two loops just override the initial styles for your cards that were set in the CSS class. That seems a waste. Just set the class to the initial state you want. – Scott Marcus Nov 21 '18 at 17:09
  • @ScottMarcus on it! – pmkro Nov 21 '18 at 17:11
  • @ScottMarcus first hover, 1st card is over 2nd, second fover 2nd card over 1st (till here is normal), third hover 1st card is under second and it should have been above also the !important does absolutely nothing, tried with and without it, no change – Dddsasul Nov 21 '18 at 17:18
  • @ScottMarcus regarding the first 2 loops that override the initial state that is intentional, I have a transition that animates the style change, when the window loads the cards float from bottom and fade in: https://gyazo.com/ae75af9f2e18ecf48932d28e351d006e – Dddsasul Nov 21 '18 at 17:23

1 Answers1

5

z-index only works on positioned elements. You are using float, which isn't the same thing.

The whole point of z-index is to be able to layer elements. But, layering (beyond one item overlapping another due to overflow) can't happen when all the elements are in the normal document "flow". In order for true layering to be able to happen, you must take items that need to be layered out of the normal document flow and that is done by specifying the CSS position as relative, absolute or fixed.

From MDN:

The z-index CSS property sets the z-order of a positioned element and its descendants or flex items. Overlapping elements with a larger z-index cover those with a smaller one.

Add position:relative to the .card class.

window.onload = function()
{
    var cards = document.querySelectorAll(".card");
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].style.margin = "0 5px 0 5px";
        cards[i].style.opacity = "1";
    }
    setTimeout(1000);
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].style.transition = ".4s";
    }
    for (let i = 0; i < cards.length; i++)
    {
        cards[i].onmouseover = function()
        {
            cards[i].style.zIndex = "9";
            cards[i].style.transform = "scale(1.1)";
        }
        cards[i].onmouseout = function()
        {
            cards[i].style.zIndex = "-1";
            cards[i].style.transform = "scale(1)";
        }
    }
}
image { width:200px; } 
.card
{
    background: rgb(70, 70, 70);
    width: 200px;
    padding-bottom: 10px;
    float: left;
    margin: 100px 5px 0 5px;
    opacity: 0;
    box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
    transition: 1s;
    z-index: -1;
    position:relative; /* z-index only works on positioned elements */
}
.card:hover
{
    box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
}
.card > img
{
    width: 300px;
}
.card-title
{
    margin-top: 5px;
    font-family: 'Roboto', sans-serif;
    font-weight: 900;
}
.card-text
{
    margin-top: 5px;
    font-family: 'Roboto', sans-serif;
    font-weight: 400;
}
<div class="card">
                <img src="https://flipsy.com/blog/images/OldGameConsoles99.jpg">
                <div class="card-title">
                    Consoles
                </div>
                <div class="card-text">
                    some random text some random text some random text some random text some random text some random text some random text some random 
                </div>
            </div>
<div class="card">
                <img src="https://flipsy.com/blog/images/OldGameConsoles99.jpg">
                <div class="card-title">
                    Consoles
                </div>
                <div class="card-text">
                    some random text some random text some random text some random text some random text some random text some random text some random 
                </div>
            </div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71