仅在用户点击时设置元素的焦点
Setting an element's focus only if user has tabbed to it
我正在尝试使我网站上的一些可折叠手风琴容器易于访问,但我 运行 遇到了问题。
手风琴由页面上的 link 元素控制 - 这样,只有键盘的用户可以通过 Tab 键切换到它们并进行访问。我 运行 遇到的第一个问题是,如果用户切换到 link 中的一个,页面不会总是向上滚动以显示他们切换到哪个。我使用以下代码解决了设置焦点的问题,该代码将 link 滚动到视口的顶部:
$(".accordion .accordion-item .accordion-heading a").focus(
function()
{
$('html:not(:animated), body:not(:animated)').animate({
scrollTop: $(this).offset().top
}, 250);
}
);
我现在遇到的问题是,当鼠标用户点击link时,它跳转到页面顶部并且不打开容器,除非鼠标用户点击link 再次。
有没有一种方法可以将上面的焦点代码设置为仅在 link 被切换到时触发?或者,是否有更好的方法来处理焦点问题,使其适用于纯键盘用户和鼠标用户?
谢谢!
首先快速道歉,现在看到您的手风琴构建正确,如果手风琴是在页面加载时使用 javascript 构建并回退,那么带有页内锚点的 links 实际上更可取只是页面内锚 link 和它们之间的内容的列表。
我是那个习惯于看到 <a href="#">
手风琴开场和奇怪的手风琴实现的人,我草率地得出结论,把它从 <buttons>
改回来!
解决您的问题
可能不是您正在寻找的答案,但请完全删除 .focus()
功能。
它会产生奇怪的行为,如果我打开了一个手风琴项目,然后我用 Alt + Tab 快速滚动确实可以如果您的 Tab 键比滚动速度快,它会跳来跳去,令人困惑。
可访问性的黄金法则之一是仅在需要时调整页面上的滚动位置(即 return to top
按钮或使用页内锚点)。
在示例和您的网站上,一旦我禁用了 'scroll to top on focus',该网站的行为实际上符合预期。
我理解你为什么这样做,因为偶尔会出现一个 link 被聚焦的页面,但是当你再次点击或向下滚动时,这会自行补救(你的网站是合乎逻辑的,所以如果我点击并我的焦点不可见我知道它不在页面上。)
当项目刚好在视线之外时,这种情况往往会发生(项目未滚动到视图中)一两个像素,这很常见并且具有讽刺意味的是现在属于 'expected' 行为(另一个规则,遵循设计组件和页面时可接受的和预期的行为)。
如果你真的想修复它
在您的 focus
函数中,不要只在项目获得焦点时滚动到页面顶部,而是检查它是否离开页面。
下面是我发现(未测试)的示例函数,您可以使用它来检查项目是否在视口中,如果是则不执行任何操作,如果不是则执行滚动功能.
var isInViewport = function (elem) {
var bounding = elem.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
大致如此(又一次没有测试是否传递了正确的项目,这只是给你一个想法)。
$(".accordion .accordion-item .accordion-heading a").focus(
function()
{
if(isInViewport(this) === false){
//item is not in the viewport so scroll it into view
$('html:not(:animated), body:not(:animated)').animate({
scrollTop: $(this).offset().top //I would perhaps add a couple of hundred pixels here to make the item appear in a more natural area.
}, 250); //remove the animation as a further accessibility improvement, animations can be off putting to people with motion or anxiety disorders.
}
}
);
这解决了您的问题,因为鼠标用户永远无法单击页面外的项目,因此他们永远不会触发导致焦点问题的滚动事件。
您可以更改事件设置:代替 focus() 事件,您将执行 click() 事件:当您单击 link 时,您将向上滚动。这将同时解决键盘导航和鼠标点击的问题;而且在可访问性方面也更是如此。
$(".accordion .accordion-item .accordion-heading a").click(
function(e)
{
e.preventDefault();
$('html:not(:animated), body:not(:animated)').animate({
scrollTop: $(this).offset().top
}, 250);
}
);
不要忘记通过添加 role=button 属性将 link 设置更改为按钮。
并添加 aria-expanded 属性。
我正在尝试使我网站上的一些可折叠手风琴容器易于访问,但我 运行 遇到了问题。
手风琴由页面上的 link 元素控制 - 这样,只有键盘的用户可以通过 Tab 键切换到它们并进行访问。我 运行 遇到的第一个问题是,如果用户切换到 link 中的一个,页面不会总是向上滚动以显示他们切换到哪个。我使用以下代码解决了设置焦点的问题,该代码将 link 滚动到视口的顶部:
$(".accordion .accordion-item .accordion-heading a").focus(
function()
{
$('html:not(:animated), body:not(:animated)').animate({
scrollTop: $(this).offset().top
}, 250);
}
);
我现在遇到的问题是,当鼠标用户点击link时,它跳转到页面顶部并且不打开容器,除非鼠标用户点击link 再次。
有没有一种方法可以将上面的焦点代码设置为仅在 link 被切换到时触发?或者,是否有更好的方法来处理焦点问题,使其适用于纯键盘用户和鼠标用户?
谢谢!
首先快速道歉,现在看到您的手风琴构建正确,如果手风琴是在页面加载时使用 javascript 构建并回退,那么带有页内锚点的 links 实际上更可取只是页面内锚 link 和它们之间的内容的列表。
我是那个习惯于看到 <a href="#">
手风琴开场和奇怪的手风琴实现的人,我草率地得出结论,把它从 <buttons>
改回来!
解决您的问题
可能不是您正在寻找的答案,但请完全删除 .focus()
功能。
它会产生奇怪的行为,如果我打开了一个手风琴项目,然后我用 Alt + Tab 快速滚动确实可以如果您的 Tab 键比滚动速度快,它会跳来跳去,令人困惑。
可访问性的黄金法则之一是仅在需要时调整页面上的滚动位置(即 return to top
按钮或使用页内锚点)。
在示例和您的网站上,一旦我禁用了 'scroll to top on focus',该网站的行为实际上符合预期。
我理解你为什么这样做,因为偶尔会出现一个 link 被聚焦的页面,但是当你再次点击或向下滚动时,这会自行补救(你的网站是合乎逻辑的,所以如果我点击并我的焦点不可见我知道它不在页面上。)
当项目刚好在视线之外时,这种情况往往会发生(项目未滚动到视图中)一两个像素,这很常见并且具有讽刺意味的是现在属于 'expected' 行为(另一个规则,遵循设计组件和页面时可接受的和预期的行为)。
如果你真的想修复它
在您的 focus
函数中,不要只在项目获得焦点时滚动到页面顶部,而是检查它是否离开页面。
下面是我发现(未测试)的示例函数,您可以使用它来检查项目是否在视口中,如果是则不执行任何操作,如果不是则执行滚动功能.
var isInViewport = function (elem) {
var bounding = elem.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
大致如此(又一次没有测试是否传递了正确的项目,这只是给你一个想法)。
$(".accordion .accordion-item .accordion-heading a").focus(
function()
{
if(isInViewport(this) === false){
//item is not in the viewport so scroll it into view
$('html:not(:animated), body:not(:animated)').animate({
scrollTop: $(this).offset().top //I would perhaps add a couple of hundred pixels here to make the item appear in a more natural area.
}, 250); //remove the animation as a further accessibility improvement, animations can be off putting to people with motion or anxiety disorders.
}
}
);
这解决了您的问题,因为鼠标用户永远无法单击页面外的项目,因此他们永远不会触发导致焦点问题的滚动事件。
您可以更改事件设置:代替 focus() 事件,您将执行 click() 事件:当您单击 link 时,您将向上滚动。这将同时解决键盘导航和鼠标点击的问题;而且在可访问性方面也更是如此。
$(".accordion .accordion-item .accordion-heading a").click(
function(e)
{
e.preventDefault();
$('html:not(:animated), body:not(:animated)').animate({
scrollTop: $(this).offset().top
}, 250);
}
);
不要忘记通过添加 role=button 属性将 link 设置更改为按钮。 并添加 aria-expanded 属性。