[英]Smooth scroll anchor links WITHOUT jQuery
Is it possible to use smooth scroll to anchor links but without jQuery
?是否可以使用平滑滚动来锚定链接但没有
jQuery
? I am creating a new site and I don't want to use jQuery
.我正在创建一个新站点,我不想使用
jQuery
。
Extending this answer: https://stackoverflow.com/a/8918062/3851798扩展这个答案: https : //stackoverflow.com/a/8918062/3851798
After defining your function of scrollTo, you can pass the element you want to scrollTo in the function.定义好你的scrollTo 函数后,你可以在函数中传递你想要scrollTo 的元素。
function scrollTo(element, to, duration) {
if (duration <= 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) return;
scrollTo(element, to, duration - 10);
}, 10);
}
If you have a div with an id="footer"如果你有一个 id="footer" 的 div
<div id="footer" class="categories">…</div>
In the script that you run to scroll you can run this,在您运行滚动的脚本中,您可以运行它,
elmnt = document.getElementById("footer");
scrollTo(document.body, elmnt.offsetTop, 600);
And there you have it.你有它。 Smooth scrolling without jQuery.
没有 jQuery 的平滑滚动。 You can actually play around with that code on your browser's console and fine tune it to your liking.
您实际上可以在浏览器的控制台上使用该代码并根据自己的喜好对其进行微调。
Using the function from here: JavaScript animation and modifying it to modify a property (not only a style's property), you can try something like this:使用此处的函数: JavaScript animation并修改它以修改属性(不仅仅是样式的属性),您可以尝试以下操作:
DEMO: http://jsfiddle.net/7TAa2/1/演示: http : //jsfiddle.net/7TAa2/1/
Just saying...就是说...
function animate(elem, style, unit, from, to, time, prop) { if (!elem) { return; } var start = new Date().getTime(), timer = setInterval(function() { var step = Math.min(1, (new Date().getTime() - start) / time); if (prop) { elem[style] = (from + step * (to - from)) + unit; } else { elem.style[style] = (from + step * (to - from)) + unit; } if (step === 1) { clearInterval(timer); } }, 25); if (prop) { elem[style] = from + unit; } else { elem.style[style] = from + unit; } } window.onload = function() { var target = document.getElementById("div5"); animate(document.scrollingElement || document.documentElement, "scrollTop", "", 0, target.offsetTop, 2000, true); };
div { height: 50px; }
<div id="div1">asdf1</div> <div id="div2">asdf2</div> <div id="div3">asdf3</div> <div id="div4">asdf4</div> <div id="div5">asdf5</div> <div id="div6">asdf6</div> <div id="div7">asdf7</div> <div id="div8">asdf8</div> <div id="div9">asdf9</div> <div id="div10">asdf10</div> <div id="div10">asdf11</div> <div id="div10">asdf12</div> <div id="div10">asdf13</div> <div id="div10">asdf14</div> <div id="div10">asdf15</div> <div id="div10">asdf16</div> <div id="div10">asdf17</div> <div id="div10">asdf18</div> <div id="div10">asdf19</div> <div id="div10">asdf20</div>
Actually, there is more lightweight and simple way to do that: https://codepen.io/ugg0t/pen/mqBBBY实际上,有更轻量级和简单的方法来做到这一点: https : //codepen.io/ugg0t/pen/mqBBBY
function scrollTo(element) { window.scroll({ behavior: 'smooth', left: 0, top: element.offsetTop }); } document.getElementById("button").addEventListener('click', () => { scrollTo(document.getElementById("8")); });
div { width: 100%; height: 200px; background-color: black; } div:nth-child(odd) { background-color: white; } button { position: absolute; left: 10px; top: 10px; }
<div id="1"></div> <div id="2"></div> <div id="3"></div> <div id="4"></div> <div id="5"></div> <div id="6"></div> <div id="7"></div> <div id="8"></div> <div id="9"></div> <div id="10"></div> <button id="button">Button</button>
Use this:用这个:
let element = document.getElementById("box");
element.scrollIntoView();
element.scrollIntoView(false);
element.scrollIntoView({block: "end"});
element.scrollIntoView({behavior: "instant", block: "end", inline: "nearest"});
DEMO : https://jsfiddle.net/anderpo/x8ucc5ak/1/演示: https : //jsfiddle.net/anderpo/x8ucc5ak/1/
CSS3 transitions with a :target
selector can give a nice result without any JS hacking.带有
:target
选择器的 CSS3 转换可以在没有任何 JS hack 的情况下提供不错的结果。 I was just contemplating whether to imlement this but without Jquery it does get a bit messy.我只是在考虑是否要实现这一点,但没有 Jquery,它确实有点混乱。 See this question for details.
有关详细信息,请参阅此问题。
Smooth Scroll behavior with polyfill...使用 polyfill 平滑滚动行为...
Example:例子:
document.querySelectorAll('a[href^="#"]').addEventListener("click", function(event) {
event.preventDefault();
document.querySelector(this.getAttribute("href")).scrollIntoView({ behavior: "smooth" });
});
Repository: https://github.com/iamdustan/smoothscroll存储库: https : //github.com/iamdustan/smoothscroll
Vanilla js variant using requestAnimationFrame
with easings and all browsers supported:使用带有缓动和所有浏览器的
requestAnimationFrame
Vanilla js 变体:
const requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame;
function scrollTo(to) {
const start = window.scrollY || window.pageYOffset
const time = Date.now()
const duration = Math.abs(start - to) / 3;
(function step() {
var dx = Math.min(1, (Date.now() - time) / duration)
var pos = start + (to - start) * easeOutQuart(dx)
window.scrollTo(0, pos)
if (dx < 1) {
requestAnimationFrame(step)
}
})()
}
Try this code here:在这里试试这个代码:
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
This is a pretty old question, but I think it's important to say that nowadays smooth scrolling is supported in CSS, so there's no need for any scripts:这是一个很老的问题,但我认为重要的是现在 CSS 支持平滑滚动,因此不需要任何脚本:
html {
scroll-behavior: smooth;
}
This property still has no support for Safari or IE/Edge as of 2019, so for a full crossbrowser support, you'll still have to use a script.截至 2019 年,此属性仍然不支持 Safari 或 IE/Edge,因此要获得完整的跨浏览器支持,您仍然必须使用脚本。
纯轻量级的JavaScript库: 在github上顺畅滚动
My favorite scroll-to library currently is Zenscroll because of the wide range of features and small size (currently only 3.17kb).我目前最喜欢的滚动到库是Zenscroll,因为它具有广泛的功能和小尺寸(目前只有 3.17kb)。
In the future it may make more sense to use the native scrollIntoView
functionality, but since it'd have to be polyfilled in most production sites today due to the lack of IE support, I recommend using Zenscroll instead in all cases.将来,使用原生
scrollIntoView
功能可能更有意义,但是由于缺乏 IE 支持,现在大多数生产站点都必须对它进行 polyfill,因此我建议在所有情况下都使用 Zenscroll。
I know this is an old question but wanted to put forward an answer that has simpler ways of doing it in modern days.我知道这是一个老问题,但想提出一个在现代有更简单方法的答案。 As of today, almost all the major browsers are compatible with
scroll-behavior
including Safari with its latest release.截至今天,几乎所有主流浏览器都与
scroll-behavior
兼容,包括最新版本的 Safari。 Still, you might want to employ fallback methods or just use the javascript approach described in method 2 for compatibility in older browsers.不过,您可能希望使用回退方法或仅使用方法 2 中描述的 javascript 方法,以便在旧浏览器中兼容。
You can just do this with你可以这样做
<a href="#target" id="scroll-trigger">Click</a>
.
.
.
<h2 id="target">Target</h2>
and CSS和 CSS
html {
scroll-behavior: smooth
}
Or if you have a unique case that needs javascript, go on elaborate with this method.或者,如果您有一个需要 javascript、go 的独特案例,请使用此方法进行详细说明。
const scrollTrigger = document.getElementById('scroll-trigger');
const target = document.getElementById('target');
scrollTrigger.addEventListener('click', function (e) {
window.scroll({
top: target.offsetTop,
left:0,
behavior: 'smooth' });
}, false)
It's upgraded version from @Ian这是@Ian 的升级版
// Animated scroll with pure JS
// duration constant in ms
const animationDuration = 600;
// scrollable layout
const layout = document.querySelector('main');
const fps = 12; // in ms per scroll step, less value - smoother animation
function scrollAnimate(elem, style, unit, from, to, time, prop) {
if (!elem) {
return;
}
var start = new Date().getTime(),
timer = setInterval(function () {
var step = Math.min(1, (new Date().getTime() - start) / time);
var value = (from + step * (to - from)) + unit;
if (prop) {
elem[style] = value;
} else {
elem.style[style] = value;
}
if (step === 1) {
clearInterval(timer);
}
}, fps);
if (prop) {
elem[style] = from + unit;
} else {
elem.style[style] = from + unit;
}
}
function scrollTo(hash) {
const target = document.getElementById(hash);
const from = window.location.hash.substring(1) || 'start';
const offsetFrom = document.getElementById(from).offsetTop;
const offsetTo = target.offsetTop;
scrollAnimate(layout,
"scrollTop", "", offsetFrom, offsetTo, animationDuration, true);
setTimeout(function () {
window.location.hash = hash;
}, animationDuration+25)
};
// add scroll when click on menu items
var menu_items = document.querySelectorAll('a.mdl-navigation__link');
menu_items.forEach(function (elem) {
elem.addEventListener("click",
function (e) {
e.preventDefault();
scrollTo(elem.getAttribute('href').substring(1));
});
});
// scroll when open link with anchor
window.onload = function () {
if (window.location.hash) {
var target = document.getElementById(window.location.hash.substring(1));
scrollAnimate(layout, "scrollTop", "", 0, target.offsetTop, animationDuration, true);
}
}
For anyone in 2019, first, you add an event listener对于 2019 年的任何人,首先,您添加一个事件侦听器
document.getElementById('id').addEventListener('click', () => scrollTo())
then you target the element and go smoothly to it然后你瞄准这个元素并顺利地找到它
function scrollTo() {
let target = document.getElementById('target');
target.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest"
})
}
Based on MDN docs for scroll options we can use the following code:基于MDN 文档的滚动选项,我们可以使用以下代码:
element.scrollTo({
top: 100,
left: 100,
behavior: 'smooth'
});
In fact, the behavior
key can accept smooth
and auto
variables.事实上,
behavior
键可以接受smooth
和auto
变量。 first for smooth motion and second for a single jump.首先是平滑运动,其次是单次跳跃。
Here is a simple solution in pure JavaScript .这是纯 JavaScript 的一个简单解决方案。 It takes advantage of CSS property scroll-behavior: smooth
它利用了 CSS 属性scroll-behavior: smooth
function scroll_to(id) {
document.documentElement.style.scrollBehavior = 'smooth'
element = document.createElement('a');
element.setAttribute('href', id)
element.click();
}
Usage :用法:
Say we have 10 divs:假设我们有 10 个 div:
<div id='df7ds89' class='my_div'>ONE</div>
<div id='sdofo8f' class='my_div'>TWO</div>
<div id='34kj434' class='my_div'>THREE</div>
<div id='gbgfh98' class='my_div'>FOUR</div>
<div id='df89sdd' class='my_div'>FIVE</div>
<div id='34l3j3r' class='my_div'>SIX</div>
<div id='56j5453' class='my_div'>SEVEN</div>
<div id='75j6h4r' class='my_div'>EIGHT</div>
<div id='657kh54' class='my_div'>NINE</div>
<div id='43kjhjh' class='my_div'>TEN</div>
We can scroll to the ID of choice :我们可以滚动到选择的 ID :
scroll_to('#657kh54')
You simply call this function on your click event (eg click button then scroll to div #9).您只需在单击事件上调用此函数(例如单击按钮然后滚动到 div #9)。
Result :结果:
Of course it looks much smoother in real life.当然,它在现实生活中看起来要流畅得多。
Unfortunately, IE and Safari don't support scrollBehavior = 'smooth' as of 2019不幸的是,截至2019 年,IE 和 Safari 不支持 scrollBehavior = 'smooth'
For a more comprehensive list of methods for smooth scrolling, see my answer here .对于用于平滑滚动的方法更全面的列表,请参阅我的答案在这里。
To scroll to a certain position in an exact amount of time, window.requestAnimationFrame
can be put to use, calculating the appropriate current position each time.要在精确的时间内滚动到某个位置,可以使用
window.requestAnimationFrame
,每次计算适当的当前位置。 setTimeout
can be used to a similar effect when requestAnimationFrame
is not supported.当不支持
requestAnimationFrame
时,可以使用setTimeout
达到类似的效果。
/*
@param pos: the y-position to scroll to (in pixels)
@param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
Demo:演示:
function scrollToSmoothly(pos, time) { var currentPos = window.pageYOffset; var start = null; if(time == null) time = 500; pos = +pos, time = +time; window.requestAnimationFrame(function step(currentTime) { start = !start ? currentTime : start; var progress = currentTime - start; if (currentPos < pos) { window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos); } else { window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time)); } if (progress < time) { window.requestAnimationFrame(step); } else { window.scrollTo(0, pos); } }); } document.getElementById("toElement").addEventListener('click', function(e) { var elem = document.querySelector("div"); scrollToSmoothly(elem.offsetTop); }); document.getElementById("toTop").addEventListener('click', function(e){ scrollToSmoothly(0, 700); });
<button id="toElement">Scroll To Element</button> <div style="margin: 1000px 0px; text-align: center;">Div element <button id="toTop">Scroll back to top</button> </div>
For more complex cases, the SmoothScroll.js library can be used, which handles smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.对于更复杂的情况,可以使用SmoothScroll.js 库,它处理垂直和水平平滑滚动、在其他容器元素内部滚动、不同的缓动行为、从当前位置相对滚动等等。
document.getElementById("toElement").addEventListener('click', function(e) { smoothScroll({toElement: document.querySelector('div'), duration: 500}); }); document.getElementById("toTop").addEventListener('click', function(e){ smoothScroll({yPos: 0, duration: 700}); });
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll@1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script> <button id="toElement">Scroll To Element</button> <div style="margin: 1000px 0px; text-align: center;">Div element <button id="toTop">Scroll back to top</button> </div>
Alternatively, you can pass an options object to window.scroll
which scrolls to a specific x and y position and window.scrollBy
which scrolls a certain amount from the current position:或者,您可以将选项对象传递给
window.scroll
,它滚动到特定的 x 和 y 位置,以及window.scrollBy
从当前位置滚动一定量:
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
Demo:演示:
<button onClick="scrollToDiv()">Scroll To Element</button> <div style="margin: 500px 0px;">Div</div> <script> function scrollToDiv(){ var elem = document.querySelector("div"); window.scroll({ top: elem.offsetTop, left: 0, behavior: 'smooth' }); } </script>
Modern browsers support the scroll-behavior
CSS property , which can be used to make scrolling in the document smooth (without the need for JavaScript).现代浏览器支持
scroll-behavior
CSS 属性,可用于使文档中的滚动平滑(无需 JavaScript)。 Anchor tags can be used for this by giving the anchor tag a href
of #
plus the id
of the element to scroll to).锚标签可用于此目的,方法是为锚标签提供
#
的href
加上要滚动到的元素的id
)。 You can also set the scroll-behavior
property for a specific container like a div
to make its contents scroll smoothly.您还可以为特定容器(如
div
设置scroll-behavior
属性,以使其内容平滑滚动。
html, body{ scroll-behavior: smooth; }
<a href="#elem">Scroll To Element</a> <div id="elem" style="margin: 500px 0px;">Div</div>
Without jQuery没有jQuery
const links = document.querySelectorAll('header nav ul a') for (const link of links) { link.onclick = function clickHandler(e) { e.preventDefault() const href = this.getAttribute('href') document.querySelector(href).scrollIntoView({ behavior: 'smooth' }) } }
body { background-color: black; height:7000px } header { margin-top: 1.3rem; margin-bottom: 25rem; display: flex; justify-content: center; align-items: center; } nav ul { display: flex; } nav ul li { all: unset; margin: 2rem; cursor: pointer; } nav ul li a { all: unset; font: bold 1.8rem robto; color: white; letter-spacing: 1px; cursor: pointer; padding-top: 3rem; padding-bottom: 2rem; } #team, #contact, #about { background-color: #e2df0d; width: 100%; height: 35rem; display: flex; justify-content: center; align-items: center; color: black; font: bold 4rem roboto; letter-spacing: 6.2px; margin-top: 70rem; }
<header> <!-- NavBar --> <nav> <ul> <li><a href="#team">Team</a></li> <li><a href="#contact">Contact</a></li> <li><a href="#about">About</a></li> </ul> </nav> </header> <!-- ----------- Team ----------------------- --> <div id="team"> <h2>Team</h2> </div> <!-- ----------- Contact ----------------------- --> <div id="contact"> <h2>Contact</h2> </div> <!-- ----------- About ----------------------- --> <div id="about"> <h2>About</h2> </div>
Or with just CSS , but it's not supported in all browsers yet或仅使用CSS ,但尚不支持所有浏览器
html {scroll-behavior: smooth}
If you want to set all of your deep links #
to scroll smoothly you can do this:如果您想将所有深层链接设置为平滑滚动
#
您可以这样做:
const allLinks = document.querySelectorAll('a[href^="#"]')
allLinks.forEach(link => {
const
targetSelector = link.getAttribute('href'),
target = document.querySelector(targetSelector)
if (target) {
link.addEventListener('click', function(e) {
e.preventDefault()
const top = target.offsetTop // consider decreasing your main nav's height from this number
window.scroll({
behavior: 'smooth',
left: 0,
top: top
});
})
}
})
An example code to consider also your main nav's height (this code goes where top
const is declared):一个示例代码也要考虑您的主导航的高度(此代码位于声明
top
const 的位置):
const
mainHeader = document.querySelector('header#masthead'), //change to your correct main nav selector
mainHeaderHeight = mainHeader.offsetHeight,
// now calculate top like this:
top = target.offsetTop - mainHeaderHeight
Here is the most elegant and concise solution.这是最优雅和简洁的解决方案。
Links:
链接:
<a href="#elementIDtoScrollTo"></a>
CSS:
CSS:
html {
scroll-behavior: smooth;
}
Remember to add a unique id="elementIDtoScrollTo"
to each HTML element.请记住为每个 HTML 元素添加一个唯一的
id="elementIDtoScrollTo"
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.