如何滚动到div中的元素?


170

我有一个滚动条div,当我单击它时我想要一个链接,它将迫使它div滚动以查看其中的元素。我这样写它的JavasSript:

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

但这会在滚动页面的同时滚动所有页面div。如何解决?

我想这样说

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

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

Answers:


340

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

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

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

现在,我们告诉div使用scrollTop以下命令滚动到该位置:

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

如果您使用原型JS框架,则将执行以下操作:

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

再次,这将滚动div,以便您希望看到的元素恰好在顶部(或者,如果不可能的话,请尽可能向下滚动以使其可见)。


9
这真的很有帮助!如果要多次设置滚动,则需要偏移当前滚动位置。这是我在jQuery中的处理方式:$('#scrolling_div')。scrollTop($('#scrolling_div')。scrollTop()+ $('#element_within_div')。position()。top);
2014年

3
注意,请求myElement.offsetTop将触发重排(布局颠簸),这可能是性能瓶颈
Kestutis

27
请记住要使用css设置滚动父级:position: relative否则,您将像我刚才那样花很多时间进行调试。
saveario

2
我必须将overflow-y属性设置scroll为父元素(scrolling_div),否则它将无法正常工作。该overflow属性的默认css值为auto,即使它也使手动滚动成为可能,但js代码将不起作用(即使使用{psition: relative}.. 也无法使用)
Evgenia Manolova

2
在2017年仍然有效。附加信息:.offsetTop可能返回0。然后,您应引用父元素,然后重试。我这样做了标记h4,然后divarticle标签,只article为我工作。
Fenio

66

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

divElem.scrollTop = 0;

更新

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

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

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

3
我要滚动视图,以查看它是否未以某个特定值滚动
Amr Elgarhy 09年

39

方法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

请注意,浏览器支持不适用于此浏览器

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 滚动行为

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


1
需要注意的是滚动的行为不支持IE / EDGE / Safari浏览器
sheats

1
@sheats-它确切地说是我在MDN文档链接中使用大字体放置的。即使它不适用于那些浏览器,也不意味着您不应该使用它。没有“规则”,所有浏览器上的所有内容都必须相同。如果现代的浏览器可以做魔术,那就让他们做魔术。
vsync

这篇文章是关于滚动整个文档而不是滚动元素。

@ DoMiNeLa10-这是一个假设。OP可能提供了一个任意示例来说明他/她的问题。此外,OP并不是主要关注的问题,而是来自搜索引擎的人们在寻找有益的解决方案,最有可能专门回答OP的需求无济于事,并且此网站的目的是创建可以为许多人提供帮助的可靠答案尽可能。我的答案同时提供
vsync

12

要将元素滚动到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>


1
这真的很有帮助。我挣扎了一下,因为我错过了这个位置:容器上的相对位置。那很关键!
brohr

11

代码应为:

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;

等等....


1
第二行var chElem = document.getElementById('element_within_div');和第三行是否应该实际读取var topPos = divElem.offsetTop;
jayp

7

如果使用的是jQuery,则可以使用以下内容滚动动画:

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

动画是可选的:您还可以采用上面计算出的scrollTop值,并将其直接放在容器的scrollTop属性中。


5

本机JS,跨浏览器,平滑滚动(2020年更新)

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

// 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'});

而已!


这是可疑的工作片段-

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>

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

参考


1
scrollTo()可能在所有主流浏览器中都支持Window对象,但IE或Edge中不支持该元素。
Tim Down

根据caniuse的介绍,它在IE11和Edge中受支持。尚未在这些浏览器上进行过亲自测试,但似乎受支持。
Niket Pathak

1
window.scrollTo不是Element.scrollTo。例如,在Edge中尝试此操作,然后检查控制台:codepen.io/timdown/pen/abzVEMB
Tim Down

你是对的。不支持IE11。但是似乎支持Edge v76 (参考)及更高版本
Niket Pathak

2

有两个事实:

1)Safari不支持组件scrollIntoView。

2)JS框架jQuery可以完成以下工作:

parent = 'some parent div has css position==="fixed"' || 'html, body';

$(parent).animate({scrollTop: $(child).offset().top}, duration)

1

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

/**
 * 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);

1

使用jQuery和动画的另一个示例。

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

0

用户动画滚动

这是一个在不使用JQuery的情况下如何以编程方式<div>水平滚动水平的示例。要垂直滚动,你将取代JavaScript的写入与 scrollLeftscrollTop,来代替。

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


自动动画滚动

另外,这里还有用于<div>向左和向右完全滚动的功能。我们在这里所做的唯一更改是,在进行递归调用以再次滚动之前,请检查滚动的完整扩展是否已被利用。

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

0

这终于为我服务

/** 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);
}

0

浏览器会自动滚动到获得焦点的元素,因此您也可以使用它来包装需要滚动到的元素,<a>...</a>然后在需要滚动时将焦点放在该元素上a


0

选择元素后,只需将scrollIntoView功能与以下选项一起使用:

const option = {
  top: 0, // number,
  left: 0, // number,
  behavior: 'auto', // auto or smooth 
    // - auto for one jump motion and smooth for animated motion -
};

因此,这篇文章的答案是:

const el = document.getElementById('id-name');
el.scrollIntoView({
  top: 0,
  left: 0,
  behavior: 'auto',
});

0

给定您需要滚动的div元素,请尝试这段代码

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

这在带有滚动的div内与我一起使用,如果您将鼠标指向该元素然后尝试向下或向上滚动,则此方法应该与您一起使用。如果手动工作,它也应该工作

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.