是否可以使用平滑滚动来锚定链接但没有 jQuery
?我正在创建一个新站点,但我不想使用jQuery
.
17 回答
扩展这个答案:https ://stackoverflow.com/a/8918062/3851798
定义你的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);
}
如果你有一个 id="footer" 的 div
<div id="footer" class="categories">…</div>
在您运行滚动的脚本中,您可以运行它,
elmnt = document.getElementById("footer");
scrollTo(document.body, elmnt.offsetTop, 600);
你有它。没有 jQuery 的平滑滚动。您实际上可以在浏览器的控制台上使用该代码并根据自己的喜好对其进行微调。
使用此处的函数:JavaScript 动画并对其进行修改以修改属性(不仅是样式的属性),您可以尝试以下操作:
演示:http: //jsfiddle.net/7TAa2/1/
只是说...
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>
实际上,有更轻量级和简单的方法可以做到这一点: 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>
用这个:
let element = document.getElementById("box");
element.scrollIntoView();
element.scrollIntoView(false);
element.scrollIntoView({block: "end"});
element.scrollIntoView({behavior: "instant", block: "end", inline: "nearest"});
带有:target
选择器的 CSS3 过渡可以在没有任何 JS 黑客攻击的情况下提供很好的结果。我只是在考虑是否要实现这一点,但如果没有 Jquery,它确实会有点混乱。有关详细信息,请参阅此问题。
这是一个很老的问题,但我认为现在 CSS 支持平滑滚动很重要,因此不需要任何脚本:
html {
scroll-behavior: smooth;
}
截至 2019 年,此属性仍然不支持 Safari 或 IE/Edge,因此要获得完整的跨浏览器支持,您仍然必须使用脚本。
Vanilla js 变体使用requestAnimationFrame
缓动和支持的所有浏览器:
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)
}
})()
}
支持任何缓动!
在这里试试这个代码:
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
使用 polyfill 平滑滚动行为...
例子:
document.querySelectorAll('a[href^="#"]').addEventListener("click", function(event) {
event.preventDefault();
document.querySelector(this.getAttribute("href")).scrollIntoView({ behavior: "smooth" });
});
我目前最喜欢的滚动到库是Zenscroll,因为它功能广泛且体积小(目前只有 3.17kb)。
将来使用本机功能可能更有意义scrollIntoView
,但由于缺乏 IE 支持,现在大多数生产站点都必须对它进行 polyfill,我建议在所有情况下都使用 Zenscroll。
基于滚动选项的MDN 文档,我们可以使用以下代码:
element.scrollTo({
top: 100,
left: 100,
behavior: 'smooth'
});
事实上,behavior
key 可以接受smooth
和auto
变量。第一个用于平滑运动,第二个用于单跳。</p>
这是@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);
}
}
对于 2019 年的任何人,首先,您添加一个事件侦听器
document.getElementById('id').addEventListener('click', () => scrollTo())
然后你以元素为目标并顺利进行
function scrollTo() {
let target = document.getElementById('target');
target.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest"
})
}
有关平滑滚动的更全面的方法列表,请参阅我的答案here。
要在准确的时间内滚动到某个位置,window.requestAnimationFrame
可以使用,每次计算出合适的当前位置。不支持setTimeout
时可以使用类似的效果。requestAnimationFrame
/*
@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);
}
});
}
演示:
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>
对于更复杂的情况,可以使用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>
或者,您可以传递一个选项对象,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'
});
演示:
<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>
现代浏览器支持scroll-behavior
CSS 属性,该属性可用于使文档中的滚动平滑(无需 JavaScript)。锚标签可以通过给锚标签 ahref
加上要滚动#
到id
的元素来使用)。您还可以为scroll-behavior
特定容器设置属性,如 adiv
以使其内容平滑滚动。
html, body{
scroll-behavior: smooth;
}
<a href="#elem">Scroll To Element</a>
<div id="elem" style="margin: 500px 0px;">Div</div>
如果您想将所有深层链接设置#
为平滑滚动,您可以这样做:
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
});
})
}
})
一个示例代码也可以考虑您的主导航的高度(此代码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
这是纯 JavaScript的简单解决方案。它利用了 CSS 属性scroll-behavior: smooth
function scroll_to(id) {
document.documentElement.style.scrollBehavior = 'smooth'
element = document.createElement('a');
element.setAttribute('href', id)
element.click();
}
用法:
假设我们有 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>
我们可以滚动到选择的 ID:
scroll_to('#657kh54')
您只需在单击事件上调用此函数(例如单击按钮然后滚动到 div #9)。
结果:
当然,它在现实生活中看起来要流畅得多。
不幸的是,截至2019 年,IE 和 Safari 不支持 scrollBehavior = 'smooth'
没有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>
或仅使用CSS,但尚不支持所有浏览器
html {scroll-behavior: smooth}