仅在用户点击时设置元素的焦点

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 属性。