我有一个滚动的div,我想有一个事件,当我点击它,它将迫使这个div滚动查看里面的一个元素。 我这样写它的JavasSript:

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

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

我想这样说: MyContainerDiv.getElementById(杆).scrollIntoView(真正的);


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

divElem.scrollTop = 0;

更新:

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

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

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

你需要获得你想要滚动到视图中的元素的顶部偏移量,相对于它的父元素(滚动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,以便您希望看到的元素恰好位于顶部(如果不可能,则尽可能向下滚动,使其可见)。


代码应该是:

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;

等等....


用户动画滚动

下面是一个如何在没有JQuery的情况下以编程方式横向滚动<div>的示例。要垂直滚动,可以将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。


自动动画滚动

此外,这里还有用于将<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);
    }
}

如果你正在使用jQuery,你可以使用以下命令滚动动画:

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

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


只有在需要的时候,你才能使用scrollIfNeeded函数将一个元素滚动到div的视图中:

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>


这是一个简单的纯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);

or

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

or

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

这就是我最终得到的

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

另一个使用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");
    }
});

方法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 { 宽度:80%; 边框:2px虚线; 身高:180 px; overflow-y:滚动; scroll-behavior:光滑;/* <——*/ } # boxChild { Margin: 600px 0 300px; 宽度:40像素; 高度:40像素; 背景:绿色; } <a href='#boxChild'>滚动到元素</a> < div class =“盒子”> < div id =“boxChild”> < / div > < / div >


有两个事实:

1) safari不支持scrollIntoView组件。

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

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

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

浏览器会自动滚动到一个获得焦点的元素,所以你也可以做它来包装你需要滚动到的元素<a>…</a>然后当你需要滚动时将焦点设置在a上


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

就是这样!


And here's a working snippet for the doubtful - 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>

更新:正如你在评论中看到的,IE11似乎不支持Element.scrollTo()。所以如果你不关心IE11(你真的不应该,微软将在2022年6月退休IE11),请在你所有的项目中使用它。注意,支持Edge!所以你并没有真正离开你的Edge/Windows用户;)

参考


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

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

这与我在一个带滚动的div中工作,这应该与你一起工作,以防你将鼠标指向这个元素,然后试图向下或向上滚动。如果它手动工作,它也应该工作


我们可以在不使用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;
}

我们可以很容易地重写这个方法,以参数的形式传递父和子


其他答案都不能解决我的问题。

我摆弄了scrollIntoView参数,并设法找到了一个解决方案。将inline设置为开始并将block设置为最近的位置,以防止父元素(或整个页面)滚动:

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

我需要滚动页面上的动态加载元素,所以我的解决方案有点复杂。

这将适用于静态元素,这些静态元素不是惰性加载数据,也不是动态加载数据。

const smoothScrollElement = async (selector: string, scrollBy = 12, prevCurrPos = 0) => {
    const wait = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout));
    const el = document.querySelector(selector) as HTMLElement;
    let positionToScrollTo = el.scrollHeight;
    let currentPosition = Math.floor(el.scrollTop) || 0;
    let pageYOffset = (el.clientHeight + currentPosition);
    if (positionToScrollTo == pageYOffset) {
        await wait(1000);
    }
    if ((prevCurrPos > 0 && currentPosition <= prevCurrPos) !== true) {
        setTimeout(async () => {
            el.scrollBy(0, scrollBy);
            await smoothScrollElement(selector, scrollBy, currentPosition);
        }, scrollBy);
    }
};