How To Slide in div with full width
Asked Answered
W

5

6

I want to slide in a div on a mobile device with a couple of boxes without the box element being sliced off during the slide-in animation, how can I achieve this with CSS? I have the below code and Jsfiddle link: https://jsfiddle.net/dealwap/prwdm724/. The issue happens only on mobile devices.

HTML:

    .box {
      flex: 0 0 80px;
      height: 80px;
      background-color: red;
      margin: 10px;
      left: 10px;
    }

    .container{
      z-index: 10;
      width: 100%;
      position: relative;
      display: flex;
      justify-content: flex-start;
      margin: auto;
      overflow: auto;
      -ms-overflow-style: none;
      scrollbar-width: none;
      animation: 2s ease-in-out 0s 1 slideInFromLeft;
    }


    @keyframes slideInFromLeft {
      0% {
        transform: translateX(-100%);
      }
      100% {
        transform: translateX(0);
      }
    }
   <div class="container">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
   </div>
Wingspan answered 24/3, 2022 at 0:29 Comment(2)
Are you referring to this last box on the far right? i.sstatic.net/zhywa.pngPiper
Yes, the last boxes on the right, I need to prevent it from being sliced off during slide in while maintaining the overflow: auto so the user can slide to see more boxes.Wingspan
F
10

Pragmatically: 1.) flex-wrap:nowrap; 2.) transform: translateX(-200%);

    .box {
      flex: 0 0 80px;
      height: 80px;
      background-color: red;
      margin: 10px;
      left: 10px;
    }

    .container{
      z-index: 10;
      width: 100%;
      position: relative;
      display: flex;
      justify-content: flex-start;
      flex-wrap:nowrap;
      margin: auto;      
      -ms-overflow-style: none;
      animation: 2s ease-in-out 0s 1 slideInFromLeft;
    }

    @keyframes slideInFromLeft {
      0% {
        transform: translateX(-200%);
      }
      100% {
        transform: translateX(0);
      }
    }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

   <div class="container">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
   </div>

  </body>
</html>
Figurehead answered 10/4, 2022 at 8:18 Comment(0)
L
2
.container{
  flex-wrap:wrap; 
}

If i understood your question right this fix the problem.

    .box {
      flex: 0 0 80px;
      height: 80px;
      background-color: red;
      margin: 10px;
      left: 10px;
    }

    .container{
      z-index: 10;
      width: 100%;
      position: relative;
      display: flex;
      justify-content: flex-start;
      flex-wrap:wrap;
      margin: auto;
      overflow: auto;
      -ms-overflow-style: none;
      animation: 2s ease-in-out 0s 1 slideInFromLeft;
    }


    @keyframes slideInFromLeft {
      0% {
        transform: translateX(-100%);
      }
      100% {
        transform: translateX(0);
      }
    }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

   <div class="container">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
   </div>

  </body>
</html>
Leede answered 24/3, 2022 at 3:19 Comment(1)
Thanks for your answer, I need the overflow to be there so the user can slide to see more boxes. This wrap will prevent that from happening.Wingspan
H
2

In this case you need to provide width to .box elements. Providing flex-basis alone is not enough.

CSS only:

body {
  overflow: hidden;
}

.box {
  flex: 0 0 80px;
  height: 80px;
  background-color: rgb(255, 130, 130);
  margin: 10px;
  left: 10px;
  width: 80px;
}

.container {
  font-size: 3rem;
  color: purple;
  width: fit-content;
  z-index: 10;
  position: relative;
  display: flex;
  justify-content: flex-start;
  margin: auto;
  overflow: auto;
  -ms-overflow-style: none;
  scrollbar-width: none;
  transform: translateX(-100%);
  animation: 2s ease-in-out 0s 1 slideInFromLeft normal forwards;
}

@keyframes slideInFromLeft {
  0% {
    transform: translateX(-100%);
  }
  99.99% {
    width: fit-content;
  }
  100% {
    width: 100%;
    transform: translateX(0);
  }
}
<div id='slideMe' class="container">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>

Using JavaScript:
Using Animations API this is easy to achieve.

const slideIn = new KeyframeEffect(slideMe, 
                             { transform: 'translateX(0%)' }, 
                             { fill: 'forwards', duration: 4000 });

const anim = new Animation(slideIn);
anim.onfinish = e => slideMe.style.width = '100%';

btn.onclick = (e) => {
  anim.play();
  e.target.style.visibility = 'hidden';
}
.box {
  flex: 0 0 80px;
  height: 80px;
  background-color: rgb(255, 130, 130);
  margin: 10px;
  left: 10px;

  width: 80px;
}

.container {
  font-size: 3rem;
  color: purple;
  width: fit-content;

  z-index: 10;
  position: relative;
  display: flex;
  justify-content: flex-start;
  margin: auto;
  overflow: auto;
  -ms-overflow-style: none;
  scrollbar-width: none;
  transform: translateX(-100%);
}
<button id='btn'>Show</button>
<div id='slideMe' class="container">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>
Harpist answered 8/4, 2022 at 5:28 Comment(3)
I appreciate the response, I want an approach that doesn't require JS, KeyframeEffect is not supported by every browsers.Wingspan
@Wingspan you had javascript tag on your question... I've added CSS only solution to the answer.Harpist
great workournd "99.99% { width: fit-content; }" it is an out of the box thought on cssDoctrine
S
0

you need to calculate full width of .container and then change translateX , to goes left as much as it's width to hide from viewport. and with add animation to silde it right.
now for calculate the full width , you can use calce() function. i set widths of .boxs in a variable (--box-width). and set in calc function

calc( (box-width + side margins) * (- box number) )
add a minus sign for goes to left

calc( (var(--box-width) + 20px) * -10)

body{
   --box-width: 80px;
}
.container {
  z-index: 10;
  width: 100%; 
  position: relative;
  display: flex;
  justify-content: flex-start;
  margin: auto;
  animation: 2s ease-in-out 0s 1  slideInFromLeft;
}

.box {
  flex: 0 0 var(--box-width);
  height: 80px;
  background-color: red;
  margin: 10px;
}

@keyframes slideInFromLeft {
  0% {
  transform: translatex(calc( (var(--box-width) + 20px) * -10));
  }
  100% {
    transform: translateX(0);
  }
}
  <div class="container">
      <div class="box">1</div>
      <div class="box">2</div>
      <div class="box">3</div>
      <div class="box">4</div>
      <div class="box">5</div>
      <div class="box">6</div>
      <div class="box">7</div>
      <div class="box">8</div>
      <div class="box">9</div>
      <div class="box">10</div>
   </div>

and that work better without knowing the number of box element, with a little pure js 😁.

const container = document.querySelector('.container')
window.addEventListener('load', () => {
  childNumber = container.childElementCount
  container.style.setProperty('--childNumber', childNumber)
  container.classList.add('animated')
})
body{
   --box-width: 80px;
}
.container { 
  --childNumber : 0;
  display: flex;
  visibility: hidden;
  z-index: 10; 
  width: 100%; 
  position: relative;
  justify-content: flex-start;
  margin: auto;
}
.container.animated{
 visibility: visible;
  animation: 2s ease-in-out 0s 1  slideInFromLeft;
}

.box {
  flex: 0 0 var(--box-width);
  height: 80px;
  background-color: red;
  margin: 10px;
} 
@keyframes slideInFromLeft {
  0% {
  transform: translatex(calc( (var(--box-width) + 20px) * var(--childNumber) * -1));
  }
  100% {
    transform: translateX(0);
  }
} 
<div class="container">
      <div class="box">1</div>
      <div class="box">2</div>
      <div class="box">3</div>
      <div class="box">4</div>
      <div class="box">5</div>
      <div class="box">6</div>
      <div class="box">7</div>
      <div class="box">8</div>
      <div class="box">9</div>
      <div class="box">10</div>
   </div>
Scutter answered 10/4, 2022 at 7:56 Comment(1)
Thanks for your response, this didn't solve the problem. I need an approach that doesn't require me to know the number of boxes.Wingspan
E
0

    .box {
      flex: 0 0 80px;
      height: 80px;
      background-color: red;
      left: 10px;
    }

    .container{
      z-index: 10;
      width: 100%;
      position: relative;
      display: flex;
      justify-content: flex-start;
      margin: auto;
      overflow: auto;
      -ms-overflow-style: none;
      animation: 2s ease-in-out 0s 1 slideInFromLeft;
    }


    @keyframes slideInFromLeft {
      0% {
        transform: translateX(-100%);
      }
      100% {
        transform: translateX(0);
      }
    }

If you dont want it sliced off then margin is NOT needed but if you really want it there then just set it to auto

    .box {
      flex: 0 0 80px;
      height: 80px;
      margin: auto;
      background-color: red;
      left: 10px;
    }

    .container{
      z-index: 10;
      width: 100%;
      position: relative;
      display: flex;
      justify-content: flex-start;
      margin: auto;
      overflow: auto;
      -ms-overflow-style: none;
      animation: 2s ease-in-out 0s 1 slideInFromLeft;
    }


    @keyframes slideInFromLeft {
      0% {
        transform: translateX(-100%);
      }
      100% {
        transform: translateX(0);
      }
    }
but to be honest with you I dont really know what you need if you just dont want it going offscreen just add flex-wrap:wrap; to container
Eyed answered 11/4, 2022 at 3:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.