skip to Main Content

I have a bunch of pictures within a showcase and Whenever any picture is pressed
I would like it to scroll to the horizontal center

I tried .scrollIntoView() but the problem was that the entire page was scrolling with it instead of just the showcase
I’ve managed to use scrollTo() but it doesn’t seem to perfectly align the image to the center:

enter image description here

Can someone please tell me why this is happening? I even took margin and width into calculation
(I’m open to changing my approach if it achieves the ultimate goal)

const showcase=document.querySelector(".showcase")
const move_img=(by)=>{

  const img=showcase.querySelector("img")
  const style=window.getComputedStyle(img);
  showcase.scrollTo({
    top: 0,
    left: (parseInt(style.width) + parseInt(style.marginLeft)) * (by - 1 ),
    behavior: "smooth",
  });
  
  /* 
    showcase.children[index].scrollIntoView({
            behavior: 'smooth',
            block: 'nearest',
            inline: 'center'
        });
    */

}

Array.from(showcase.children).forEach((child, index) => {

  child.onclick=()=>{move_img(index, true)}
});
:root{
  --main_pic_width:30rem;
  --showcase_height:5rem;
  --showcase_division:3;
  --showcase_gap:1rem;
}

.showcase{
  width:calc( var(--main_pic_width) + var(--showcase_gap));
  height:var(--showcase_height);
  background:gray;
  white-space:nowrap;
  overflow-y:hidden;
  overflow-x:auto;
  -ms-overflow-style: none;  /* Internet Explorer 10+ */
  scrollbar-width: none;  /* Firefox */
  }
.showcase::-webkit-scrollbar { 
    display: none;  /* Safari and Chrome */
}

.showcase img{
  width:calc( var(--main_pic_width)/var(--showcase_division) - var(--showcase_gap));
  background-color:black;
  margin-left:var(--showcase_gap);
  object-fit: contain;
}
<div class="showcase">
  <img src="https://www.w3schools.com/css/img_forest.jpg" />
  <img src="https://www.w3schools.com/css/img_5terre.jpg"/>
  <img src="https://www.w3schools.com/css/img_mountains.jpg"/>
  <img src="https://www.w3schools.com/css/img_lights.jpg"/>
  <img src="https://www.w3schools.com/css/img_5terre.jpg"/>
  <img src="https://www.w3schools.com/css/img_forest.jpg"/>
  <img src="https://www.w3schools.com/css/img_mountains.jpg"/>
</div>

2

Answers


  1. Chosen as BEST ANSWER

    @Unmitigated's answer works but for some reason it didn't work in production perhaps some margin or padding I missed?

    regardless I found the solution:

    const showcase=document.querySelector(".showcase")
    const move_img=(by)=>{
    
      const img=showcase.querySelector("img")
      const style=window.getComputedStyle(img);
      showcase.scrollTo({
        top: 0,
        left: (parseInt(style.width) + parseInt(style.marginLeft) + parseInt(style.marginRight)) * (by - 1 ),
        behavior: "smooth",
      });
    }
    
    Array.from(showcase.children).forEach((child, index) => {
    
      child.onclick=()=>{move_img(index, true)}
    });
    :root{
      --main_pic_width:30rem;
      --showcase_height:5rem;
      --showcase_division:3;
      --showcase_gap:1rem;
    }
    
    
    
    .showcase{
      
      width:var(--main_pic_width);
      height:var(--showcase_height);
      background:gray;
      white-space:nowrap;
      overflow-y:hidden;
      overflow-x:auto;
      -ms-overflow-style: none;  /* Internet Explorer 10+ */
      scrollbar-width: none;  /* Firefox */
      }
    .showcase::-webkit-scrollbar { 
        display: none;  /* Safari and Chrome */
    }
    
    .showcase img{
      height: 100%;
        width: calc( (var(--main_pic_width) - var(--showcase_gap) * var(--showcase_division) * 2) / var(--showcase_division));
      margin: 0 var(--showcase_gap);
      object-fit: contain;
      box-sizing: border-box;
    }
    <div class="showcase">
    <img src="https://www.w3schools.com/css/img_forest.jpg" /><img src="https://www.w3schools.com/css/img_5terre.jpg"/><img src="https://www.w3schools.com/css/img_mountains.jpg"/><img src="https://www.w3schools.com/css/img_lights.jpg"/><img src="https://www.w3schools.com/css/img_5terre.jpg"/><img src="https://www.w3schools.com/css/img_forest.jpg"/><img src="https://www.w3schools.com/css/img_mountains.jpg"/> -->
    </div>

    Also the reason all the <img> tags are in a single line is because adding a newline creates a space in between 2 images which messes up the calculation


  2. You can calculate the position to scroll to using offsetLeft and offsetWidth.

    const showcase = document.querySelector(".showcase");
    showcase.addEventListener('click', e => {
      if (e.target.matches('img')) 
        showcase.scroll({left: e.target.offsetLeft - (showcase.offsetWidth - e.target.offsetWidth) / 2, behavior: 'smooth'});
    });
    :root{
      --main_pic_width:30rem;
      --showcase_height:5rem;
      --showcase_division:3;
      --showcase_gap:1rem;
    }
    
    .showcase{
      width:calc( var(--main_pic_width) + var(--showcase_gap));
      height:var(--showcase_height);
      background:gray;
      white-space:nowrap;
      overflow-y:hidden;
      overflow-x:auto;
      -ms-overflow-style: none;  /* Internet Explorer 10+ */
      scrollbar-width: none;  /* Firefox */
      }
    .showcase::-webkit-scrollbar { 
        display: none;  /* Safari and Chrome */
    }
    
    .showcase img{
      width:calc( var(--main_pic_width)/var(--showcase_division) - var(--showcase_gap));
      background-color:black;
      margin-left:var(--showcase_gap);
      object-fit: contain;
    }
    <div class="showcase">
      <img src="https://www.w3schools.com/css/img_forest.jpg" />
      <img src="https://www.w3schools.com/css/img_5terre.jpg"/>
      <img src="https://www.w3schools.com/css/img_mountains.jpg"/>
      <img src="https://www.w3schools.com/css/img_lights.jpg"/>
      <img src="https://www.w3schools.com/css/img_5terre.jpg"/>
      <img src="https://www.w3schools.com/css/img_forest.jpg"/>
      <img src="https://www.w3schools.com/css/img_mountains.jpg"/>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search