如何将一个元素滚动到水平中心?

huangapple go评论73阅读模式
英文:

How to scroll an element into horizontal center?

问题

我有一堆图片放在一个展示窗口里,每当按下任何一张图片时,我希望它滚动到水平中心。

我尝试了.scrollIntoView(),但问题是整个页面也随之滚动,而不仅仅是展示窗口。
我已经使用scrollTo()成功了,但似乎不能完美地将图像对齐到中心:

如何将一个元素滚动到水平中心?

请问有人可以告诉我为什么会发生这种情况吗?我甚至考虑了边距和宽度
(如果能实现最终目标,我愿意改变我的方法)

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",
  });
}

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;
  scrollbar-width: none;
}

.showcase::-webkit-scrollbar {
  display: none;
}

.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>

<details>
<summary>英文:</summary>

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&#39;ve managed to use `scrollTo()` but it doesn&#39;t seem to perfectly align the image to the center:

[![enter image description here][1]][1]

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

&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;

&lt;!-- language: lang-js --&gt;

    const showcase=document.querySelector(&quot;.showcase&quot;)
    const move_img=(by)=&gt;{

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

    }

    Array.from(showcase.children).forEach((child, index) =&gt; {

      child.onclick=()=&gt;{move_img(index, true)}
    });



&lt;!-- language: lang-css --&gt;

    :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;
    }


&lt;!-- language: lang-html --&gt;

    &lt;div class=&quot;showcase&quot;&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_forest.jpg&quot; /&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_5terre.jpg&quot;/&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_mountains.jpg&quot;/&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_lights.jpg&quot;/&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_5terre.jpg&quot;/&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_forest.jpg&quot;/&gt;
      &lt;img src=&quot;https://www.w3schools.com/css/img_mountains.jpg&quot;/&gt;
    &lt;/div&gt;



&lt;!-- end snippet --&gt;


  [1]: https://i.stack.imgur.com/QcHpD.png

</details>


# 答案1
**得分**: 2

你可以使用 `offsetLeft` 和 `offsetWidth` 来计算要滚动到的位置。

```javascript
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>
英文:

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

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const showcase = document.querySelector(&quot;.showcase&quot;);
showcase.addEventListener(&#39;click&#39;, e =&gt; {
  if (e.target.matches(&#39;img&#39;)) 
    showcase.scroll({left: e.target.offsetLeft - (showcase.offsetWidth - e.target.offsetWidth) / 2, behavior: &#39;smooth&#39;});
});

<!-- language: lang-css -->

: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;
}

<!-- language: lang-html -->

&lt;div class=&quot;showcase&quot;&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_forest.jpg&quot; /&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_5terre.jpg&quot;/&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_mountains.jpg&quot;/&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_lights.jpg&quot;/&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_5terre.jpg&quot;/&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_forest.jpg&quot;/&gt;
  &lt;img src=&quot;https://www.w3schools.com/css/img_mountains.jpg&quot;/&gt;
&lt;/div&gt;

<!-- end snippet -->

答案2

得分: 0

@Unmitigated的答案有效,但由于某种原因,在生产环境中未能正常工作,也许是我忽略了一些边距或填充?

不管怎样,我找到了解决方案:

<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>
: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;
}
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);
  };
});

此外,所有<img>标签都在同一行中的原因是,添加换行会在2个图像之间创建空格,从而破坏了计算。

英文:

@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:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const showcase=document.querySelector(&quot;.showcase&quot;)
const move_img=(by)=&gt;{

  const img=showcase.querySelector(&quot;img&quot;)
  const style=window.getComputedStyle(img);
  showcase.scrollTo({
    top: 0,
    left: (parseInt(style.width) + parseInt(style.marginLeft) + parseInt(style.marginRight)) * (by - 1 ),
    behavior: &quot;smooth&quot;,
  });
}

Array.from(showcase.children).forEach((child, index) =&gt; {

  child.onclick=()=&gt;{move_img(index, true)}
});

<!-- language: lang-css -->

: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;
}

<!-- language: lang-html -->

&lt;div class=&quot;showcase&quot;&gt;
&lt;img src=&quot;https://www.w3schools.com/css/img_forest.jpg&quot; /&gt;&lt;img src=&quot;https://www.w3schools.com/css/img_5terre.jpg&quot;/&gt;&lt;img src=&quot;https://www.w3schools.com/css/img_mountains.jpg&quot;/&gt;&lt;img src=&quot;https://www.w3schools.com/css/img_lights.jpg&quot;/&gt;&lt;img src=&quot;https://www.w3schools.com/css/img_5terre.jpg&quot;/&gt;&lt;img src=&quot;https://www.w3schools.com/css/img_forest.jpg&quot;/&gt;&lt;img src=&quot;https://www.w3schools.com/css/img_mountains.jpg&quot;/&gt; --&gt;
&lt;/div&gt;

<!-- end snippet -->

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

huangapple
  • 本文由 发表于 2023年7月11日 03:03:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76656615.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定