我有一个滚动的 div
,当我点击它时我想要一个事件,它会强制此 div
滚动以查看里面的元素。我这样写它的JavasSript:
document.getElementById(chr).scrollIntoView(true);
但这会在滚动 div
本身时滚动整个页面。如何解决?
我想这样说:MyContainerDiv.getElementById(chr).scrollIntoView(true);
$(document).ready({})
函数中使用 SetTimeout
并将 focus()
设置为您要滚动到的元素。为我工作
您需要获取要滚动到视图中的元素相对于其父级(滚动 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 以使您希望看到的元素正好位于顶部(或者如果这不可能,则尽可能向下滚动以使其可见)。
您必须在要滚动到的 DIV 中找到元素的位置,然后设置 scrollTop 属性。
divElem.scrollTop = 0;
更新:
上移或下移的示例代码
function move_up() {
document.getElementById('divElem').scrollTop += 10;
}
function move_down() {
document.getElementById('divElem').scrollTop -= 10;
}
方法 1 - 平滑滚动到元素内的元素
var box = document.querySelector('.box'), targetElm = document.querySelector('.boxChild'); // <-- 在“.box”中滚动到此处 document.querySelector('button').addEventListener('click', function(){ scrollToElm( box, targetElm , 600 ); }); //////////// function scrollToElm(container, elm, duration){ var pos = getRelativePos(elm); scrollTo( 容器, pos.top , 2); // 持续时间以秒为单位 } function getRelativePos(elm){ var pPos = elm.parentNode.getBoundingClientRect(), // 父 pos cPos = elm.getBoundingClientRect(), // 目标 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.左;返回位置; } function scrollTo(element, to, duration, onDone) { var start = element.scrollTop, change = to - start, startTime = performance.now(), val, now, elapsed, t;函数 animateScroll(){ 现在 = performance.now();经过=(现在-开始时间)/ 1000; t =(经过/持续时间); element.scrollTop = start + change * easeInOutQuad(t); if(t < 1) window.requestAnimationFrame(animateScroll);否则 onDone && onDone(); };动画滚动(); } 函数 easeInOutQuad(t){ 返回 t<.5 ? 2*t*t : -1+(4-2*t)*t }; .box{ 宽度:80%;边框:2px 虚线;高度:180px;溢出:自动; } .boxChild{ 边距:600px 0 300px;宽度:40px;高度:40px;背景:绿色; }
方法 2 - 使用 Element.scrollIntoView:
请注意,浏览器支持不是很好
var targetElm = document.querySelector('.boxChild'), // 引用滚动目标 button = document.querySelector('button'); // 触发滚动的按钮 // 将“click”事件绑定到按钮 button.addEventListener('click', function(){ targetElm.scrollIntoView() }) .box { width: 80%;边框:2px 虚线;高度:180px;溢出:自动;滚动行为:平滑; /* <-- 平滑滚动 */ } .boxChild { margin: 600px 0 300px;宽度:40px;高度:40px;背景:绿色; }
方法 3 - 使用 CSS 滚动行为:
.box { 宽度:80%;边框:2px 虚线;高度:180px;溢出-y:滚动;滚动行为:平滑; /* <--- */ } #boxChild { 边距:600px 0 300px;宽度:40px;高度:40px;背景:绿色; } 滚动到元素
原生 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'});
而已!
这是一个给怀疑者的工作片段 -
document.getElementById('btn').addEventListener('click', e => { e.preventDefault(); // 平滑滚动 document.getElementById('container').scrollTo({top: 175, behavior: 'smooth' }); }); /* 只是一些你可以忽略的样式 */ .scrollContainer { overflow-y: auto;最大高度:100px;位置:相对;边框:1px 纯红色;宽度:120px; } 身体 { 填充:10px; } .box { 边距:5px;背景颜色:黄色;高度:25px;显示:弯曲;对齐项目:居中;证明内容:中心; } #goose { 背景颜色:石灰; }
更新:正如您在评论中看到的那样,IE11 似乎不支持 Element.scrollTo()
。因此,如果您不关心 IE11(您真的不应该,Microsoft 将于 2022 年 6 月停用 IE11),请随时在您的所有项目中使用它。请注意,存在对 Edge 的支持!所以你并没有真正把你的 Edge/Windows 用户抛在后面;)
要将元素滚动到 div 的视图中,只有在需要时,您才可以使用此 scrollIfNeeded
函数:
函数 scrollIfNeeded(element, container) { if (element.offsetTop < container.scrollTop) { container.scrollTop = element.offsetTop; } else { const offsetBottom = element.offsetTop + element.offsetHeight;常量 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 { 溢出-y:自动;最大高度:100px;位置:相对;边框:1px 纯红色;宽度:120px; } 身体 { 填充:10px; } .box { 边距:5px;背景颜色:黄色;高度:25px;显示:弯曲;对齐项目:居中;证明内容:中心; } #goose { 背景颜色:石灰; }
代码应该是:
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');
而第 3 行不应该读取 var topPos = divElem.offsetTop;
吗?
如果您使用的是 jQuery,则可以使用以下内容滚动动画:
$(MyContainerDiv).animate({scrollTop: $(MyContainerDiv).scrollTop() + ($('element_within_div').offset().top - $(MyContainerDiv).offset().top)});
动画是可选的:您也可以将上面计算的 scrollTop 值直接放在容器的 scrollTop 属性中。
我们可以在不使用 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;
}
我们可以很容易地重写这个方法来传递父母和孩子作为参数
另一个使用 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");
}
});
有两个事实:
1) safari 不支持组件 scrollIntoView。
2)JS框架jQuery可以做这样的工作:
parent = 'some parent div has css position==="fixed"' || 'html, body';
$(parent).animate({scrollTop: $(child).offset().top}, duration)
这是一个简单的纯 JavaScript 解决方案,适用于目标 Number(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);
其他答案都没有解决我的问题。
我玩弄了 scrollIntoView 个参数并设法找到了解决方案。将 inline
设置为 start
并将 block
设置为 nearest
可防止父元素(或整个页面)滚动:
document.getElementById(chr).scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'start'
});
假设你有一个需要在里面滚动的 div 元素,试试这段代码
document.querySelector('div').scroll(x,y)
这适用于我在带有滚动的 div 中,如果您将鼠标指向此元素然后尝试向下或向上滚动,这应该适用于您。如果它手动工作,它也应该工作
用户动画滚动
下面是一个如何以编程方式水平滚动 <div>
的示例,没有 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。
自动动画滚动
此外,这里还有将 <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);
}
}
这就是最终为我服务的东西
/** 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);
}
浏览器会自动滚动到获得焦点的元素,因此您还可以将需要滚动到的元素包装到 <a>...</a>
中,然后当您需要滚动时,只需将焦点设置在该 a
上
不定期副业成功案例分享
myElement.offsetTop
将触发可能是 performance bottleneck 的重排(布局抖动)position: relative
设置滚动父级,否则您将像我刚才那样花费大量时间进行调试。scrolling_div
) 的overflow-y
属性设置为scroll
,否则它不起作用。overflow
属性的默认 css 值为auto
,即使它也使手动滚动成为可能,js 代码也不起作用(即使使用{psition: relative}
..)h4
然后div
然后article
标签做了这个,只有article
对我有用。