平滑滚动 (视口内从原始链接到目标锚点的动画位置变化)可以是添加到站点的很好的交互细节,从而给用户带来优美的体验。 如果您不相信我,请查看CSS-Tricks上有多少人对“ 平滑滚动”代码段做出了回应。
![平稳滚动与突然跳跃](https://i-blog.csdnimg.cn/blog_migrate/d017cd97d96751ea2943e4f2fa1bb586.gif)
无论您如何实现该功能,都应解决一些可访问性问题:焦点管理和动画。
重点管理
重要的是要确保仅使用键盘即可访问所有内容 ,因为某些用户100%依赖键盘进行导航。 因此,当键盘用户浏览内容并点击使用平滑滚动的链接时,他们应该能够使用它来导航到目标锚元素。
换句话说,当您跟随链接时,键盘焦点也应跟随该链接,并且能够访问目标之后的下一个元素。 这是指向页面锚点的链接的示例,该页面锚点由于未使用JavaScript而得以保持焦点:
![保持焦点的示例](https://i-blog.csdnimg.cn/blog_migrate/36f2c6b72d24a4e8d4dc49f20b7ab184.gif)
亲自尝试:使用Tab键浏览此演示 。 请注意,Safari / WebKit有一个关于键盘焦点的突出错误 。
原始jQuery示例
让我们看一下原始帖子中的jQuery示例:
$(function() {
$('a[href*="#"]:not([href="#"])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
这是在W3C的页面上实现的:
![在W3C网站上流畅滚动](https://i-blog.csdnimg.cn/blog_migrate/3d70d1c22cff0b944aa0f7d27c540fa1.gif)
:focus
于内容,但这不会改变焦点
在这里,我们看到“跳至内容”链接没有将重点放在导航到的内容上。 因此,如果我们使用此示例,则使用键盘会使人们的导航情况更糟,因为用户希望导航到目标内容,但事实并非如此,因为焦点不会更新以反映更改。
使用Tab键浏览此演示文稿 ,自己尝试一下。
什么地方出了错?
为什么不起作用? 我们使用JavaScript来接管正常的浏览器链接行为(请注意,URL永远不会使用/#target进行更新),这意味着我们需要使用JavaScript来设置焦点。 在jQuery中将是$(target).focus();
。
为了使它能够处理非焦点目标元素(section,div,span,h1-6等),我们必须在它们上设置tabindex="-1"
才能使$(target).focus();
。 我们可以将tabindex="-1"
直接添加到html标记中的不可聚焦目标元素上,也可以使用JavaScript添加它,如下所示。
$(function() {
$('a[href*="#"]:not([href="#"])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top
}, 1000);
target.focus(); // Setting focus
if (target.is(":focus")){ // Checking if the target was focused
return false;
} else {
target.attr('tabindex','-1'); // Adding tabindex for elements not focusable
target.focus(); // Setting focus
};
return false;
}
}
});
});
使用Tab键浏览此演示文稿 ,自己尝试一下。 不要忘记您的:focus样式!
![将功能集中在W3C网站上的滚动上](https://i-blog.csdnimg.cn/blog_migrate/d83f1dbbb9d9e18fd7d6cb91fe00fe1a.gif)
更好的方法?
一般来说,如果我们在不劫持正常浏览器导航行为的情况下处理此功能,则可能对用户更好。 例如,如果您单击链接,则可以使用浏览器的后退按钮返回。 另外,您可以为当前URL添加书签(或复制和粘贴),浏览器将从您单击的最后一个链接转到该特定目标。
// URL updates and the element focus is maintained
// originally found via in Update 3 on http://www.learningjquery.com/2007/10/improved-animated-scrolling-script-for-same-page-links
// filter handling for a /dir/ OR /indexordefault.page
function filterPath(string) {
return string
.replace(/^\//, '')
.replace(/(index|default).[a-zA-Z]{3,4}$/, '')
.replace(/\/$/, '');
}
var locationPath = filterPath(location.pathname);
$('a[href*="#"]').each(function () {
var thisPath = filterPath(this.pathname) || locationPath;
var hash = this.hash;
if ($("#" + hash.replace(/#/, '')).length) {
if (locationPath == thisPath && (location.hostname == this.hostname || !this.hostname) && this.hash.replace(/#/, '')) {
var $target = $(hash), target = this.hash;
if (target) {
$(this).click(function (event) {
event.preventDefault();
$('html, body').animate({scrollTop: $target.offset().top}, 1000, function () {
location.hash = target;
$target.focus();
if ($target.is(":focus")){ //checking if the target was focused
return false;
}else{
$target.attr('tabindex','-1'); //Adding tabindex for elements not focusable
$target.focus(); //Setting focus
};
});
});
}
}
}
});
![专注于W3C网站](https://i-blog.csdnimg.cn/blog_migrate/d4313ea5e9111631f9cd3c0d8917be8f.gif)
在此,URL随单击的每个锚点更新。 使用Tab键浏览本演示 ,自己尝试一下。
本机示例
让我们看看CSS-Tricks post中的本机浏览器示例。 (还有一个polyfill 。)
document.querySelector('#target-of-thing-clicked-on').scrollIntoView({
behavior: 'smooth'
});
不幸的是,使用此方法时,我们遇到了与jQuery方法相同的问题,在该方法中页面在视口中滚动,但没有更新键盘焦点。 因此,如果我们要走这条路,我们仍然必须设置.focus()
并确保不可聚焦的目标元素收到tabindex="-1"
。
此处的另一个考虑因素是滚动停止时缺少回调函数。 这可能是问题,也可能不是问题。 您可以在滚动时同时移动焦点,而不是在结束时移动焦点,这可能有些奇怪,也可能没有。 无论如何,会有工作要做!
动作和辅助功能
实际上,某些人可能会因屏幕上的快速移动而感到不适 。 我建议您使用慢速的动作,因为如果用户要跳过很多内容 ,如果动作太快,可能会导致眩晕。
同样,为用户提供一种关闭动画的方法也不是坏主意。 幸运的是,Safari 10.1引入了减少运动媒体查询 ,该查询为开发人员提供了一种包含动画的方法,该方法可以在浏览器级别禁用。
/* JavaScript MediaQueryList Interface */
var motionQuery = window.matchMedia('(prefers-reduced-motion)');
if (motionQuery.matches) {
/* reduce motion */
}
motionQuery.addListener( handleReduceMotionChanged );
不幸的是,尚无其他浏览器实现此功能。 因此,在支持范围扩展到一个浏览器之前,我们可以通过界面为用户提供一个选项,以启用/禁用可能引起用户问题的动画。
<label>
<input type="checkbox" id="animation" name="animation" checked="checked">
Enable Animation
</label>
$(this).click(function(event) {
if ($('#animation').prop('checked')) {
event.preventDefault();
$('html, body').animate({scrollTop: $target.offset().top}, 1000, function() {
location.hash = target;
$target.focus();
if ($target.is(":focus")) {
return !1;
} else {
$target.attr('tabindex', '-1');
$target.focus()
}
})
}
});
通过此演示自己尝试一下。