【问题标题】:How to scroll to an element inside a div?如何滚动到div内的元素?
【发布时间】:2010-10-12 18:01:48
【问题描述】:

我有一个滚动的div,当我点击它时我想要一个事件,它会强制这个div 滚动以查看里面的元素。 我这样写它的JavasSript:

document.getElementById(chr).scrollIntoView(true);

但这会在滚动div 本身的同时滚动整个页面。 如何解决?

我想这样说: MyContainerDiv.getElementById(chr).scrollIntoView(true);

【问题讨论】:

  • Scrolltop 并不总是返回可用值。我倾向于在$(document).ready({}) 函数中使用SetTimeout,并将focus() 设置为要滚动到的元素。为我工作

标签: javascript html scroll


【解决方案1】:

其他答案都没有解决我的问题。

我玩弄了scrollIntoView 参数并设法找到了解决方案。将inline 设置为start 并将block 设置为nearest 可防止父元素(或整个页面)滚动:

document.getElementById(chr).scrollIntoView({
   behavior: 'smooth',
   block: 'nearest',
   inline: 'start'
});

【讨论】:

    【解决方案2】:

    我们可以在不使用 JQuery 和其他库的情况下解决这个问题。

    我为此编写了以下代码:

    你有类似的结构 ->

    <div class="parent">
      <div class="child-one">
    
      </div>
      <div class="child-two">
    
      </div>
    </div>
    

    JS:

    scrollToElement() {
      var parentElement = document.querySelector('.parent');
      var childElement = document.querySelector('.child-two');
    
      parentElement.scrollTop = childElement.offsetTop - parentElement.offsetTop;
    }
    

    我们可以很容易地重写这个方法来传递父和子作为参数

    【讨论】:

    • 这个答案对我很有帮助!正是我想要的!
    【解决方案3】:

    原生 JS、跨浏览器、平滑滚动(2020 年更新)

    设置ScrollTop 确实给出了预期的结果,但滚动非常突然。使用jquery 平滑滚动不是一种选择。因此,这是一种支持所有主要浏览器的完成工作的本机方式。参考——caniuse

    // get the "Div" inside which you wish to scroll (i.e. the container element)
    const El = document.getElementById('xyz');
    
    // Lets say you wish to scroll by 100px, 
    El.scrollTo({top: 100, behavior: 'smooth'});
    
    // If you wish to scroll until the end of the container
    El.scrollTo({top: El.scrollHeight, behavior: 'smooth'});
    

    就是这样!


    这是一个适用于可疑人员的工作 sn-p -

    document.getElementById('btn').addEventListener('click', e => {
      e.preventDefault();
      // smooth scroll
      document.getElementById('container').scrollTo({top: 175, behavior: 'smooth'});
    });
    /* just some styling for you to ignore */
    .scrollContainer {
      overflow-y: auto;
      max-height: 100px;
      position: relative;
      border: 1px solid red;
      width: 120px;
    }
    
    body {
      padding: 10px;
    }
    
    .box {
      margin: 5px;
      background-color: yellow;
      height: 25px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    #goose {
      background-color: lime;
    }
    <!-- Dummy html to be ignored -->
    <div id="container" class="scrollContainer">
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div id="goose" class="box">goose</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
      <div class="box">duck</div>
    </div>
    
    <button id="btn">goose</button>

    更新:正如您在 cmets 中所看到的,IE11 似乎不支持 Element.scrollTo()。因此,如果您不关心 IE11(您真的不应该),请随意在您的所有项目中使用它。请注意,存在对 Edge 的支持!所以你并没有真正让你的 Edge/Windows 用户落后;)

    Reference

    【讨论】:

    • scrollTo() 可能在所有主要浏览器中都支持Window 对象,但在 IE 或 Edge 中不支持元素。
    • 根据caniuse,IE11和Edge都支持。没有在这些浏览器上亲自测试过,但似乎支持。
    • 那是window.scrollTo,而不是Element.scrollTo。例如,在 Edge 中试试这个,然后检查控制台:codepen.io/timdown/pen/abzVEMB
    • 你是对的。不支持 IE11。但是 Edge v76 (ref) 及更高版本似乎受支持
    【解决方案4】:

    假设你有一个需要在里面滚动的 div 元素,试试这段代码

    document.querySelector('div').scroll(x,y)

    这适用于我在带有滚动的 div 中,如果您将鼠标指向该元素然后尝试向下或向上滚动,这应该适用于您。如果它手动工作,它也应该工作

    【讨论】:

    【解决方案5】:

    方法 1 - 平滑滚动到元素内的元素

    var box = document.querySelector('.box'),
        targetElm = document.querySelector('.boxChild'); // <-- Scroll to here within ".box"
    
    document.querySelector('button').addEventListener('click', function(){
       scrollToElm( box, targetElm , 600 );   
    });
    
    
    /////////////
    
    function scrollToElm(container, elm, duration){
      var pos = getRelativePos(elm);
      scrollTo( container, pos.top , 2);  // duration in seconds
    }
    
    function getRelativePos(elm){
      var pPos = elm.parentNode.getBoundingClientRect(), // parent pos
          cPos = elm.getBoundingClientRect(), // target pos
          pos = {};
    
      pos.top    = cPos.top    - pPos.top + elm.parentNode.scrollTop,
      pos.right  = cPos.right  - pPos.right,
      pos.bottom = cPos.bottom - pPos.bottom,
      pos.left   = cPos.left   - pPos.left;
    
      return pos;
    }
        
    function scrollTo(element, to, duration, onDone) {
        var start = element.scrollTop,
            change = to - start,
            startTime = performance.now(),
            val, now, elapsed, t;
    
        function animateScroll(){
            now = performance.now();
            elapsed = (now - startTime)/1000;
            t = (elapsed/duration);
    
            element.scrollTop = start + change * easeInOutQuad(t);
    
            if( t < 1 )
                window.requestAnimationFrame(animateScroll);
            else
                onDone && onDone();
        };
    
        animateScroll();
    }
    
    function easeInOutQuad(t){ return t<.5 ? 2*t*t : -1+(4-2*t)*t };
    .box{ width:80%; border:2px dashed; height:180px; overflow:auto; }
    .boxChild{ 
      margin:600px 0 300px; 
      width: 40px;
      height:40px;
      background:green;
    }
    <button>Scroll to element</button>
    <div class='box'>
      <div class='boxChild'></div>
    </div>

    方法 2 - 使用Element.scrollIntoView:

    注意browser support 不适合这个

    var targetElm = document.querySelector('.boxChild'),  // reference to scroll target
        button = document.querySelector('button');        // button that triggers the scroll
      
    // bind "click" event to a button 
    button.addEventListener('click', function(){
       targetElm.scrollIntoView()
    })
    .box {
      width: 80%;
      border: 2px dashed;
      height: 180px;
      overflow: auto;
      scroll-behavior: smooth; /* <-- for smooth scroll */
    }
    
    .boxChild {
      margin: 600px 0 300px;
      width: 40px;
      height: 40px;
      background: green;
    }
    <button>Scroll to element</button>
    <div class='box'>
      <div class='boxChild'></div>
    </div>

    方法 3 - 使用 CSS scroll-behavior:

    .box {
      width: 80%;
      border: 2px dashed;
      height: 180px;
      overflow-y: scroll;
      scroll-behavior: smooth; /* <--- */
    }
    
    #boxChild {
      margin: 600px 0 300px;
      width: 40px;
      height: 40px;
      background: green;
    }
    <a href='#boxChild'>Scroll to element</a>
    <div class='box'>
      <div id='boxChild'></div>
    </div>

    【讨论】:

    • 请注意,IE/Edge/Safari 不支持滚动行为
    • @sheats - 它在 MDN 文档链接中准确地说明了我以大字体放置的内容。即使它不适用于这些浏览器,也不意味着您不应该使用它。没有“规则”,一切都必须在所有浏览器上表现相同。如果现代浏览器可以变魔术,那就让它们变魔术吧。
    • 这篇文章是关于滚动整个文档而不是滚动元素。
    • @DoMiNeLa10 - 这是一个假设。 OP 可能提供了一个任意示例来说明他/她的问题。此外,OP 不是主要关注点,而是来自搜索引擎的人们正在寻找一个健康的解决方案,并且很可能专门针对 OP 需求的回答对他们没有帮助,本网站的目的是创建 solid 可以帮助尽可能多的答案。 我的回答同时提供了
    【解决方案6】:

    浏览器会自动滚动到获得焦点的元素,因此您也可以将需要滚动到的元素包装到 &lt;a&gt;...&lt;/a&gt; 中,然后当您需要滚动时,只需将焦点设置在该 @987654322 上@

    【讨论】:

      【解决方案7】:

      有两个事实:

      1) safari 不支持组件 scrollIntoView。

      2) JS 框架 jQuery 可以做这样的工作:

      parent = 'some parent div has css position==="fixed"' || 'html, body';
      
      $(parent).animate({scrollTop: $(child).offset().top}, duration)
      

      【讨论】:

        【解决方案8】:

        另一个使用 jQuery 和 animate 的例子。

        var container = $('#container');
        var element = $('#element');
        
        container.animate({
            scrollTop: container.scrollTop = container.scrollTop() + element.offset().top - container.offset().top
        }, {
            duration: 1000,
            specialEasing: {
                width: 'linear',
                height: 'easeOutBounce'
            },
            complete: function (e) {
                console.log("animation completed");
            }
        });
        

        【讨论】:

          【解决方案9】:

          这就是最终为我服务的东西

          /** Set parent scroll to show element
           * @param element {object} The HTML object to show
           * @param parent {object} The HTML object where the element is shown  */
          var scrollToView = function(element, parent) {
              //Algorithm: Accumulate the height of the previous elements and add half the height of the parent
              var offsetAccumulator = 0;
              parent = $(parent);
              parent.children().each(function() {
                  if(this == element) {
                      return false; //brake each loop
                  }
                  offsetAccumulator += $(this).innerHeight();
              });
              parent.scrollTop(offsetAccumulator - parent.innerHeight()/2);
          }
          

          【讨论】:

            【解决方案10】:

            这是一个简单的纯 JavaScript 解决方案,适用于目标数字(scrollTop 的值)、目标 DOM 元素或一些特殊的字符串情况:

            /**
             * target - target to scroll to (DOM element, scrollTop Number, 'top', or 'bottom'
             * containerEl - DOM element for the container with scrollbars
             */
            var scrollToTarget = function(target, containerEl) {
                // Moved up here for readability:
                var isElement = target && target.nodeType === 1,
                    isNumber = Object.prototype.toString.call(target) === '[object Number]';
            
                if (isElement) {
                    containerEl.scrollTop = target.offsetTop;
                } else if (isNumber) {
                    containerEl.scrollTop = target;
                } else if (target === 'bottom') {
                    containerEl.scrollTop = containerEl.scrollHeight - containerEl.offsetHeight;
                } else if (target === 'top') {
                    containerEl.scrollTop = 0;
                }
            };
            

            以下是一些用法示例:

            // Scroll to the top
            var scrollableDiv = document.getElementById('scrollable_div');
            scrollToTarget('top', scrollableDiv);
            

            // Scroll to 200px from the top
            var scrollableDiv = document.getElementById('scrollable_div');
            scrollToTarget(200, scrollableDiv);
            

            // Scroll to targetElement
            var scrollableDiv = document.getElementById('scrollable_div');
            var targetElement= document.getElementById('target_element');
            scrollToTarget(targetElement, scrollableDiv);
            

            【讨论】:

              【解决方案11】:

              要将元素滚动到 div 的视图中,仅在需要时,您可以使用此 scrollIfNeeded 函数:

              function scrollIfNeeded(element, container) {
                if (element.offsetTop < container.scrollTop) {
                  container.scrollTop = element.offsetTop;
                } else {
                  const offsetBottom = element.offsetTop + element.offsetHeight;
                  const scrollBottom = container.scrollTop + container.offsetHeight;
                  if (offsetBottom > scrollBottom) {
                    container.scrollTop = offsetBottom - container.offsetHeight;
                  }
                }
              }
              
              document.getElementById('btn').addEventListener('click', ev => {
                ev.preventDefault();
                scrollIfNeeded(document.getElementById('goose'), document.getElementById('container'));
              });
              .scrollContainer {
                overflow-y: auto;
                max-height: 100px;
                position: relative;
                border: 1px solid red;
                width: 120px;
              }
              
              body {
                padding: 10px;
              }
              
              .box {
                margin: 5px;
                background-color: yellow;
                height: 25px;
                display: flex;
                align-items: center;
                justify-content: center;
              }
              
              #goose {
                background-color: lime;
              }
              <div id="container" class="scrollContainer">
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div id="goose" class="box">goose</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
                <div class="box">duck</div>
              </div>
              
              <button id="btn">scroll to goose</button>

              【讨论】:

              • 这真的很有帮助。我有点挣扎,因为我错过了位置:容器上的相对位置。这很关键!
              • 这样可以节省我编写函数的时间。
              【解决方案12】:

              如果您使用的是 jQuery,您可以使用以下方式滚动动画:

              $(MyContainerDiv).animate({scrollTop: $(MyContainerDiv).scrollTop() + ($('element_within_div').offset().top - $(MyContainerDiv).offset().top)});
              

              动画是可选的:你也可以把上面计算的scrollTop值直接放到容器的scrollTop属性中。

              【讨论】:

                【解决方案13】:

                代码应该是:

                var divElem = document.getElementById('scrolling_div');
                var chElem = document.getElementById('element_within_div');
                var topPos = divElem.offsetTop;
                divElem.scrollTop = topPos - chElem.offsetTop;
                

                您想滚动子元素顶部位置和 div 顶部位置之间的差异。

                使用以下方法访问子元素:

                var divElem = document.getElementById('scrolling_div'); 
                var numChildren = divElem.childNodes.length;
                

                等等……

                【讨论】:

                • 第二行不应该是var chElem = document.getElementById('element_within_div');,第三行是var topPos = divElem.offsetTop;吗?
                【解决方案14】:

                用户动画滚动

                这是一个如何以编程方式水平滚动&lt;div&gt; 的示例,没有 JQuery。要垂直滚动,您可以将 JavaScript 对 scrollLeft 的写入替换为 scrollTop

                JSFiddle

                https://jsfiddle.net/fNPvf/38536/

                HTML

                <!-- Left Button. -->
                <div style="float:left;">
                    <!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
                    <input type="button" value="«" style="height: 100px;" onmousedown="scroll('scroller',3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
                </div>
                <!-- Contents to scroll. -->
                <div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
                    <!-- <3 -->
                    <img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
                </div>
                <!-- Right Button. -->
                <div style="float:left;">
                    <!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
                    <input type="button" value="»" style="height: 100px;" onmousedown="scroll('scroller',-3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
                </div>
                

                JavaScript

                // Declare the Shared Timer.
                var TIMER_SCROLL;
                /** 
                Scroll function. 
                @param id  Unique id of element to scroll.
                @param d   Amount of pixels to scroll per sleep.
                @param del Size of the sleep (ms).*/
                function scroll(id, d, del){
                    // Scroll the element.
                    document.getElementById(id).scrollLeft += d;
                    // Perform a delay before recursing this function again.
                    TIMER_SCROLL = setTimeout("scroll('"+id+"',"+d+", "+del+");", del);
                 }
                

                归功于Dux


                自动动画滚动

                此外,这里还有将&lt;div&gt; 完全向左和向右滚动的函数。我们在这里唯一改变的是,在再次递归调用滚动之前,我们会检查滚动的完整扩展是否已被利用。

                JSFiddle

                https://jsfiddle.net/0nLc2fhh/1/

                HTML

                <!-- Left Button. -->
                <div style="float:left;">
                    <!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
                    <input type="button" value="«" style="height: 100px;" onclick="scrollFullyLeft('scroller',3, 10);"/>
                </div>
                <!-- Contents to scroll. -->
                <div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
                  <!-- <3 -->
                  <img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
                </div>
                <!-- Right Button. -->
                <div style="float:left;">
                    <!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
                    <input type="button" value="»" style="height: 100px;" onclick="scrollFullyRight('scroller',3, 10);"/>
                </div>
                

                JavaScript

                // Declare the Shared Timer.
                var TIMER_SCROLL;
                /** 
                Scroll fully left function; completely scrolls  a <div> to the left, as far as it will go.
                @param id  Unique id of element to scroll.
                @param d   Amount of pixels to scroll per sleep.
                @param del Size of the sleep (ms).*/
                function scrollFullyLeft(id, d, del){
                    // Fetch the element.
                    var el = document.getElementById(id);
                    // Scroll the element.
                    el.scrollLeft += d;
                    // Have we not finished scrolling yet?
                    if(el.scrollLeft < (el.scrollWidth - el.clientWidth)) {
                        TIMER_SCROLL = setTimeout("scrollFullyLeft('"+id+"',"+d+", "+del+");", del);
                    }
                }
                
                /** 
                Scroll fully right function; completely scrolls  a <div> to the right, as far as it will go.
                @param id  Unique id of element to scroll.
                @param d   Amount of pixels to scroll per sleep.
                @param del Size of the sleep (ms).*/
                function scrollFullyRight(id, d, del){
                    // Fetch the element.
                    var el = document.getElementById(id);
                    // Scroll the element.
                    el.scrollLeft -= d;
                    // Have we not finished scrolling yet?
                    if(el.scrollLeft > 0) {
                        TIMER_SCROLL = setTimeout("scrollFullyRight('"+id+"',"+d+", "+del+");", del);
                    }
                }
                

                【讨论】:

                  【解决方案15】:

                  您必须在要滚动到的 DIV 中找到元素的位置,然后设置 scrollTop 属性。

                  divElem.scrollTop = 0;
                  

                  更新

                  向上或向下移动的示例代码

                    function move_up() {
                      document.getElementById('divElem').scrollTop += 10;
                    }
                  
                    function move_down() {
                      document.getElementById('divElem').scrollTop -= 10;
                    }
                  

                  【讨论】:

                  • 我想滚动它查看,看它不滚动某个值
                  【解决方案16】:

                  您需要获取要滚动到视图中的元素的顶部偏移量,相对于其父级(滚动的 div 容器):

                  var myElement = document.getElementById('element_within_div');
                  var topPos = myElement.offsetTop;
                  

                  变量 topPos 现在设置为滚动 div 的顶部与您希望可见的元素之间的距离(以像素为单位)。

                  现在我们使用scrollTop 告诉 div 滚动到该位置:

                  document.getElementById('scrolling_div').scrollTop = topPos;
                  

                  如果你使用原型 JS 框架,你会做同样的事情:

                  var posArray = $('element_within_div').positionedOffset();
                  $('scrolling_div').scrollTop = posArray[1];
                  

                  同样,这将滚动 div,以便您希望看到的元素正好位于顶部(或者如果这不可能,则尽可能向下滚动以使其可见)。

                  【讨论】:

                  • 这真的很有帮助!如果要多次设置滚动,则需要偏移当前滚动位置。以下是我在 jQuery 中的做法: $('#scrolling_div').scrollTop($('#scrolling_div').scrollTop() + $('#element_within_div').position().top);
                  • 请注意,请求 myElement.offsetTop 将触发回流(布局抖动),这可能是 performance bottleneck
                  • 记得用css设置滚动父级:position: relative否则你会像我刚才那样花很多时间调试。
                  • 我必须将父元素 (scrolling_div) 的 overflow-y 属性设置为 scroll,否则它不起作用。 overflow 属性的默认 css 值为 auto,即使它也可以手动滚动,js 代码也不起作用(即使使用 {psition: relative}..)
                  • 在 2017 年仍然有效。附加信息:.offsetTop 可能返回 0。然后您应该引用父元素并重试。我为标签h4然后div然后article标签做了那个,只有article为我工作。
                  猜你喜欢
                  • 2019-12-25
                  • 1970-01-01
                  • 2015-03-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-11-12
                  相关资源
                  最近更新 更多