Home > front end >  Is there a way to use flexbox with items that are relative and absolute
Is there a way to use flexbox with items that are relative and absolute

Time:09-07

I am trying to make a two rows of 3 pokeballs each that will open and reveal the pokemon inside when you click on it. I've managed to make the animation work to my liking for now. However when I tried to extend that to 6 pokeballs on two rows, I've encountered some problems.

My rows are on top of each other instead of one on each row. I've used a flexbox in my main container to use flex-direction: column and the rows use flex-direction: row.

It's my first time trying to make a front-end that isn't just the very basic elements and I'm not sure if I understand why it's happening. I believe the fact that the pokeball pieces are using position: absolute and the box containing them are using position: relative are causing the issue, but I need them to align my images on top of one another.

Any guidance or guide that covers that type of problem would be appreciated. I have found some great ressources on flexboxes but seemed to offer me any guidance on resolving the issue(I might have misunderstood something though)

Thank you!

const pokeballBottoms = document.querySelectorAll(".pkb-bottom");
const pokeballTops = document.querySelectorAll(".pkb-top");
const pokemons = document.querySelectorAll(".pokemon");
console.log(pokeballTops, pokeballBottoms, pokemons)

for (const pokeballBottomsKey in pokeballBottoms) {
    pokeballBottoms[pokeballBottomsKey].addEventListener("click", evt => {
        let pkb = evt.currentTarget;
        //Remove the close animation classes
        pkb.classList.remove("animatePokeballBottomClose")
        pokemons[pokeballBottomsKey].classList.remove("animatePokeballPokemonClose")
        //Add the open animation classes
        pkb.classList.add("animatePokeballBottomOpen");
        pokemons[pokeballBottomsKey].classList.add("animatePokeballPokemonOpen");
        setTimeout(function () {
            //Remove the open animation classes
            pkb.classList.remove("animatePokeballBottomOpen");
            pokemons[pokeballBottomsKey].classList.remove("animatePokeballPokemonOpen");
            //Add the close animation classes
            pkb.classList.add("animatePokeballBottomClose");
            pokemons[pokeballBottomsKey].classList.add("animatePokeballPokemonClose");
        }, 10000);
    })
}
.main-container {
    display: flex;
    flex-direction: column;
    max-width: 1000px;
}

.container-row {
    display: flex;
    flex-direction: row;
    justify-content: space-evenly;
    width: 100%;
}

.row-items {
    position: relative;
    width: 25%;
}

@keyframes pokeballBottomOpen {
    0% {margin-top: 39%}
    100% {margin-top: 76%}
}

@keyframes pokeballBottomClose {
    0% {margin-top: 76%}
    100% {margin-top: 39%}
}

@keyframes pokeballPokemonOpen {
    0% {margin-top: 0%}
    100% {margin-top: 20%}
}

@keyframes pokeballPokemonClose {
    0% {margin-top: 20%}
    100% {margin-top: 0%}
}

.animatePokeballBottomClose {
    animation: pokeballBottomClose;
    animation-duration: 3s;
    animation-timing-function: ease-out;
    animation-fill-mode: forwards;
}


.animatePokeballBottomOpen {
    animation: pokeballBottomOpen;
    animation-duration: 3s;
    animation-timing-function: ease-out;
    animation-fill-mode: forwards;
}

.animatePokeballPokemonOpen {
    animation: pokeballPokemonOpen;
    animation-duration: 3s;
    animation-timing-function: ease-out;
    animation-fill-mode: forwards;
}

.animatePokeballPokemonClose {
    animation: pokeballPokemonClose;
    animation-duration: 3s;
    animation-timing-function: ease-out;
    animation-fill-mode: forwards;
}

.poke-col {
    position: relative;
}

.pkb-top {
    width: 100%;
    position: absolute;
    z-index: 1;
}

.pkb-bottom {
    width: 100%;
    margin-top: 39%;
    position: absolute;
    z-index: 2;
}

.pokemon {
    width: 100%;
    padding: 10%;
    position: absolute;
    z-index: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=500px, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/index.css">
    <title>Title</title>
</head>
<body>
    <div >
        <div >
            <div >
                <img  src="https://i.imgur.com/F9DFytU.png">
                <img  src="https://i.imgur.com/jri9n2c.png">
                <img  src="https://i.imgur.com/xgnvGcf.png">
            </div>
            <div >
                <img  src="https://i.imgur.com/F9DFytU.png">
                <img  src="https://i.imgur.com/jri9n2c.png">
                <img  src="https://i.imgur.com/xgnvGcf.png">
            </div>
            <div >
                <img  src="https://i.imgur.com/F9DFytU.png">
                <img  src="https://i.imgur.com/jri9n2c.png">
                <img  src="https://i.imgur.com/xgnvGcf.png">
            </div>
        </div>
        <div >
            <div >
                <img  src="https://i.imgur.com/F9DFytU.png">
                <img  src="https://i.imgur.com/jri9n2c.png">
                <img  src="https://i.imgur.com/xgnvGcf.png">
            </div>
            <div >
                <img  src="https://i.imgur.com/F9DFytU.png">
                <img  src="https://i.imgur.com/jri9n2c.png">
                <img  src="https://i.imgur.com/xgnvGcf.png">
            </div>
            <div >
                <img  src="https://i.imgur.com/F9DFytU.png">
                <img  src="https://i.imgur.com/jri9n2c.png">
                <img  src="https://i.imgur.com/xgnvGcf.png">
            </div>
        </div>
    </div>
</body>
<footer>
</footer>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/index.js"></script>
</html>

CodePudding user response:

The positioning causes the parent to be of zero height. You can overcome this by setting a min-height on .container-row. I used min-height: 32vw; (32% of the viewport width) in the snippet:

const pokeballBottoms = document.querySelectorAll(".pkb-bottom");
const pokeballTops = document.querySelectorAll(".pkb-top");
const pokemons = document.querySelectorAll(".pokemon");
console.log(pokeballTops, pokeballBottoms, pokemons)

for (const pokeballBottomsKey in pokeballBottoms) {
  pokeballBottoms[pokeballBottomsKey].addEventListener("click", evt => {
    let pkb = evt.currentTarget;
    //Remove the close animation classes
    pkb.classList.remove("animatePokeballBottomClose")
    pokemons[pokeballBottomsKey].classList.remove("animatePokeballPokemonClose")
    //Add the open animation classes
    pkb.classList.add("animatePokeballBottomOpen");
    pokemons[pokeballBottomsKey].classList.add("animatePokeballPokemonOpen");
    setTimeout(function() {
      //Remove the open animation classes
      pkb.classList.remove("animatePokeballBottomOpen");
      pokemons[pokeballBottomsKey].classList.remove("animatePokeballPokemonOpen");
      //Add the close animation classes
      pkb.classList.add("animatePokeballBottomClose");
      pokemons[pokeballBottomsKey].classList.add("animatePokeballPokemonClose");
    }, 10000);
  })
}
.main-container {
  display: flex;
  flex-direction: column;
  max-width: 1000px;
}

.container-row {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  width: 100%;
  min-height: 32vw;
}

.row-items {
  position: relative;
  width: 25%;
}

@keyframes pokeballBottomOpen {
  0% {
    margin-top: 39%
  }
  100% {
    margin-top: 76%
  }
}

@keyframes pokeballBottomClose {
  0% {
    margin-top: 76%
  }
  100% {
    margin-top: 39%
  }
}

@keyframes pokeballPokemonOpen {
  0% {
    margin-top: 0%
  }
  100% {
    margin-top: 20%
  }
}

@keyframes pokeballPokemonClose {
  0% {
    margin-top: 20%
  }
  100% {
    margin-top: 0%
  }
}

.animatePokeballBottomClose {
  animation: pokeballBottomClose;
  animation-duration: 3s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
}

.animatePokeballBottomOpen {
  animation: pokeballBottomOpen;
  animation-duration: 3s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
}

.animatePokeballPokemonOpen {
  animation: pokeballPokemonOpen;
  animation-duration: 3s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
}

.animatePokeballPokemonClose {
  animation: pokeballPokemonClose;
  animation-duration: 3s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
}

.poke-col {
  position: relative;
}

.pkb-top {
  width: 100%;
  position: absolute;
  z-index: 1;
}

.pkb-bottom {
  width: 100%;
  margin-top: 39%;
  position: absolute;
  z-index: 2;
}

.pokemon {
  width: 100%;
  padding: 10%;
  position: absolute;
  z-index: 0;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=500px, initial-scale=1">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="css/index.css">
  <title>Title</title>
</head>

<body>
  <div >
    <div >
      <div >
        <img  src="https://i.imgur.com/F9DFytU.png">
        <img  src="https://i.imgur.com/jri9n2c.png">
        <img  src="https://i.imgur.com/xgnvGcf.png">
      </div>
      <div >
        <img  src="https://i.imgur.com/F9DFytU.png">
        <img  src="https://i.imgur.com/jri9n2c.png">
        <img  src="https://i.imgur.com/xgnvGcf.png">
      </div>
      <div >
        <img  src="https://i.imgur.com/F9DFytU.png">
        <img  src="https://i.imgur.com/jri9n2c.png">
        <img  src="https://i.imgur.com/xgnvGcf.png">
      </div>
    </div>
    <div >
      <div >
        <img  src="https://i.imgur.com/F9DFytU.png">
        <img  src="https://i.imgur.com/jri9n2c.png">
        <img  src="https://i.imgur.com/xgnvGcf.png">
      </div>
      <div >
        <img  src="https://i.imgur.com/F9DFytU.png">
        <img  src="https://i.imgur.com/jri9n2c.png">
        <img  src="https://i.imgur.com/xgnvGcf.png">
      </div>
      <div >
        <img  src="https://i.imgur.com/F9DFytU.png">
        <img  src="https://i.imgur.com/jri9n2c.png">
        <img  src="https://i.imgur.com/xgnvGcf.png">
      </div>
    </div>
  </div>
</body>
<footer>
</footer>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/index.js"></script>

</html>

CodePudding user response:

I believe the fact that the pokeball pieces are using position: absolute and the box containing them are using position: relative are causing the issue,

It's the abspos pokeball pieces that are causing the issue. The relpos container is fine. abspos elements don't have any space allocated for them. relpos elements do.

but I need them to align my images on top of one another.

I don't think you do. You can make the images relpos (position:relative) and mess with margin to get the images to line up. Then you don't have to set any definite height like the other answer suggests. I tried margin-top:-10% on the bottom image instead of 39% and that seemed right. You'd need to then also adjust the margin percentages in your animations.

You do still need relpos on the images to get the z-indexes to work. But I think you don't need it on the containers anymore, just the images.

tl;dr use negative margins on relpos images instead of using abspos images.

  • Related