拖放-和-拖放组件供盲人使用? 你在开玩笑吗

是什么使Trello,Gmail,Aviasales和Google Keep融合在一起? 它们每个都有Drag-&-Drop组件,可以用鼠标拖动它们。 这些组件的使用使网站真正方便,因为在现实生活中我们经常使用这种模式。 对于我们来说,移动事物是很自然的,因此在网络上,我们希望将屏幕周围的元素从一个位置移动到另一个位置,例如黑板上的贴纸或冰箱上的磁铁。 对待办事项列表进行排序,组织仪表板,下载文件-如果不拖放页面上的元素,我们简直无法想象所有这些事件。



但是有细微差别。 在开发此类组件时,我们认为用户实际上可以看到屏幕和元素,可以用鼠标抓住并拖动它们,通常是这样,但我们却忽略了视力障碍的用户群体。 我们创建的组件无法被根本看不到的大批人使用。 如何使拖放组件也可访问?

Sergey Krieger是SinnerSchrader的前端开发人员。 除了前端开发之外,他还对Web可访问性主题非常感兴趣,并讨论了一些增加它的方法。 在剪辑之下-一个有关为那些看不见屏幕并使用其他设备与浏览器进行交互的用户创建拖放组件的故事。


滑杆


让我们从Aviasales屏幕上的一个简单屏幕开始。 输入出发点,到达点,屏幕上会出现可供选择的航班列表。 航班可以有很多,可以按价格,时间和其他参数进行过滤。 滑块用于过滤Aviasales网站上的结果。 它们看起来很棒,使用方便。



我们的任务是想象我们是该网站的开发者。 让我们尝试重新创建这些滑块,并查看它们在不同情况下的工作方式。

本机滑块


首先要考虑的是本机元素是否可以用于我们的功能? 如果有这样的机会,我们就这样走,因为原生元素会节省很多时间。

让我们举一个简单的例子:滑块沿着轨道移动,并且滑块的值改变。 向右移动滑块-屏幕颜色从白色变为亮粉红色(如果变回,则从红色变为)-再次变为白色。



滑块的工作原理很简单-滑块沿着轨道滑动,并且滑块返回一些值。

没有人会在生产中使用这种滑块。 没有设计师允许他使用,因为他看上去很虚弱。 作为开发人员,我们可以解决此问题。 每个浏览器都有许多带前缀的CSS属性,您可以在其中样式化滑块的各个元素并对其进行优化。

: : -webkit-slider-runnable-track : : -webkit-sHder-thumb : : -moz-range-track : : -moz-range-thumb : : -ns-track :-ms-thumb : : -ms-fill-lower : : -ms-fill-upper 

您可以手动使用属性,但这不是一件容易的事。 属性在不同的浏览器中工作,并且测试将花费大量时间。

但是,有一个特殊的工具可以解决该问题-Daniel Stern网站 。 您手动设置滑块的样式,复制CSS代码,一切正常。 现在,本机滑块是类型为rangeinput HTML元素,但仍可以像以前一样工作-通过移动滑块。

滑块测试


为了彻底解决问题-我们进行了测试。 此外,我们将不仅测试滑块,还测试三个参数中的其他元素。

  • 鼠标 。 用鼠标测试组件的操作正是我们一直要做的。
  • 琴键 除鼠标外,我们还为视力障碍者调整了滑块。 这些用户看不到屏幕,而是使用键盘与计算机和浏览器进行交互
  • 屏幕阅读器 -一种读取屏幕上信息的特殊设备。

注意:在下文中,结合视频记录的阅读和观看测试会更加方便-这更加明显。 经过测试的视频片段将从正确的时刻开始。


鼠标 。 我们紧贴滑块,向左右拖动。 如果一切都变了-太好了。

琴键 使用Tab键转到滑块,然后使用箭头沿着轨道移动它。

屏幕阅读器 。 这里比较复杂。 想象一下,我们看不到屏幕-关闭屏幕上的灯,然后打开屏幕阅读器。 他说:

-VoiceOver已在Chrome中打开

使用Tab键,转到滑块。

-零 程式化的滑块应用程序。

屏幕阅读器的语音信息:值,滑块名称和其他相关信息,也可能很有用。 我们开始移动滑块:

-一,二,三,四,五。

如果我们听到倒计时,一切正常。 打开灯并检查结果。 测试结束。

似乎我们什么也没做,只是简单地设置了滑块。 我们在可访问性方面的工作是什么? 事实是,没有工作-我们使用了本机元素。

如果您的应用程序能够使用本机元素:滑块,按钮,复选框,请随时使用它们并节省时间。 这些元素已经支持键盘和屏幕阅读器。

自定义滑块


假设本机滑块不是我们的选择。 让我们看一下Aviasales代码,看看这里不是我们刚刚测试过的滑块。



这不是类型rangeinput ,而是设计师设计所需的一组div样式。 似乎没有区别,一切正常。

我们将对此进行检查,并通过手动创建滑块来使任务复杂化。 沿轨道移动滑块的关键是绝对定位:

 position: absolute 

我们绝对将滑块相对于轨道定位,并根据其位置计算滑块的值。

为了确定使用鼠标捕获元素的时刻,我们使用mousedown事件。 要跟踪事件的运动mousemovemouseup会告诉我们我们释放了滑块。 对于触摸屏,我们还将使用许多事件: touchstarttouchmovetouchend

似乎一切都很简单。 滑块的外观与上一个示例相同,但是在代码中,它不是滑块,而是一组样式化div ,而JavaScript将负责移动它。 使用鼠标时,这是很难察觉的,但是键盘上却有细微差别。 为了使键盘能够抓住这样的滑块,我们为它提供了一个属性,使其具有tabindex属性的焦点,并使用JavaScript来跟踪箭头的单击。

测试自定义滑块



使用屏幕阅读器会更难。 关闭灯,打开屏幕阅读器,然后尝试更改该值。 屏幕阅读器会说出这些动作,如果他说出奇怪的话,例如“小组”,我们认为。

屏幕阅读器读取没有任何语义角色的div或其他元素时,“ Groups”即为屏幕阅读器发出的声音。 任何不涉及滑块的词都表示尚未实现可访问性。 为了使滑块可用,我们使用ARIA属性:

 <div class="thumb" tabindex="0"    role="slider"    aria-labl=""    aria-valuenow="5"    aria-valuemin="0"    aria-valuenax="10" ></div> 

我们需要告诉屏幕阅读器我们通常的样式元素是滑块。 我们将通过role使用值slider来执行此操作。 然后使用aria-labl为滑块指定名称。 我们设置滑块的当前值,滑块的最小值和最大值。 使用这五个ARIA属性,我们将对滑块进行动画处理,并使屏幕阅读器说出我们需要的内容。

使用标记,JavaScript和ARIA元素,我们使所有用户都可以使用自定义滑块。

排序


实现拖放组件的另一种方法是排序。 通常,网站上都有很好排序的项目列表。



上方是Google Keep网站的屏幕截图-该服务可让您创建待办事项列表,待办事项表。 待办事项表具有名称,元素列表,标记每个元素,将其删除以及添加新元素的能力。 我们的任务是重新创建此功能。

这是待办事项列表小部件的样子。



它具有:

  • 名称-待办事项清单;
  • 要素:与狗同行,与医生约诊,可以注明或删除;
  • 添加新元素的能力-添加任务。

当我们添加新项目(例如“做晚餐”)时,它会放在列表的末尾。 这是一种逻辑行为-我们在最后添加了该项。 但是,让我们假设这些列表具有某种优先级。 例如,在工作一天之后,晚餐比带狗散步更重要。 我们想将其移到开头-优先级元素应该在列表的顶部。 如何解决这个问题?

即使根本不考虑辅助功能,也该如何移动元素? 我们已经知道一种方法-使用绝对定位。 另一种方法是将draggable属性添加到元素。 如果true任何元素将此属性添加为true ,则该属性变为可拖动。 您可以用鼠标抓住它并将其拖动到屏幕上的其他位置。

但并非所有元素都需要draggable属性。 不需要图像和链接-默认情况下将它们拖放。

仅当我们要取消此功能时,我们才将false设置为draggable

资料传输


屏幕上有两个元素。 左图是默认情况下暗含draggable属性的图片。 右边是带有虚线的元素。 我们的任务是将图片拖到虚线框内,我称之为“拖放区”。



抓住图片并将其拖到拖放区。 这种熟悉的功能:我们可以在拖动区域中输入图片,放开时退出-图片在里面。 我们希望在待办事项列表中具有相同的功能。



但是在查看待办事项列表如何使用这项技术之前,我们将弄清楚当将一个项目从一个地方拖到另一个地方时会发生什么。 这些元素中的每一个都发生事件列表。

拖动的项目上有三个事件。

Dragstart ,当我们开始拖动元素的过程时发生一次。 这是一个重要事件,我们稍后将查找原因。

每数百毫秒定期发生一次拖动 。 取决于浏览器,该值会更改,但是该事件很频繁。 使用此属性,您可以跟踪要拖动的元素在屏幕上的位置。

Dragend-当我们用鼠标释放物品时触发。

在接受其他元素的元素上,将引发四个事件。

Dragenter-当我们将一个项目拖到另一个项目中时发出警报。

Dragover-当我们开始将其移入内部时说。

Dragleave-当我们一个元素移到另一个元素的边界之外而没有释放鼠标时。

当我们在接收元素内释放鼠标时, 掉落是最重要的事件。

所有这四个事件只是元素移动的先决条件-它们本身什么也不做。 使用它们,您可以决定元素的移动。 我们这样做:

 draggable.addEventListener("dragstart", e => { e.dataTransfer.setData("text/plain", e.target.id); }); dropZone.addEventListener("drop", e => { const id = e.dataTransfer.getData("text/plain"); const el = document.getElementById(id); }); 

我们可以将数据手动添加到在拖动元素的开头触发的事件中。 使用dataTransfer.setData方法,我们添加了要拖动的项目的选择器。 在我们的例子中,这是id

最后,当在接收元素上触发Drop事件时,我们使用dataTransfer.getData方法获取此数据。 事实证明,我们将拥有我们要移动id元素的id 。 接下来,使用普通的JavaScript,在页面上选择此元素并将其移动到任何地方。 我们用手移动。 为了使其成为可能,我们在拖放元素上使用事件。

我们可以将任何元素拖到任何其他元素上。 只需在页面上拖动元素并将其指向其他元素即可。 移动并不意味着一个要素如果没有计划就应该接受另一要素。 因此,浏览器以这种方式工作:默认情况下,没有元素可以接受其他元素。

如果要教元素接受其他元素,则需要在dragenterdragover上使用e.preventDefault()方法取消此值,这会在dropZone元素上dropZone

 dropZone.addEventListener("dragenter", e => { e.preventDefault(); }); dropZone.addEventListener("dragover«, e => { e.preventDefault(); }); 

我在不同的浏览器中测试了这种组合。 例如,只有dragenter才能在Chrome中工作,因此将dragenterdragover用于跨浏览器解决方案。

让我们看看这在待办事项清单上如何运作。



我们的任务是将熟悉的待办事项列表中的最后一项拖到第一个位置。 将鼠标悬停在一个元素上,一个具有6个垂直点的元素将显示在左侧。 在UX世界中,这意味着您可以拖动它。



我们将鼠标悬停在它上面,如果它发生变化,则表明该元素已准备好移动。 用鼠标向上拉,会出现一个粉红色指示器,指示您可以在哪里移动该项目。 其余技术是将对象放置在所需位置。



现在,我们将教键盘,然后教屏幕阅读器正确处理我们刚做的事情。

琴键


使用键盘,一切都不会那么复杂。 使用键盘,我们使用与鼠标相同的模式:找到要移动,选择,移动然后释放的元素,并将其放到适当的位置。

按Tab键,第一个元素的左侧会出现一个熟悉的6点图标,表示可以拖放。 默认情况下,它是隐藏的,并且它的出现意味着它已经聚焦。 这是您可以与此元素进行交互的信号。

我们通过按“ Enter”键将第一个元素“烹饪晚餐”引入“选择模式”。 该项目目前正在接受其他选项。 向上和向下箭头可以将其移动到其他位置。 按下向下箭头,该项将移动一个位置,再次移至另一位置。 因此,我们手动移动组件。 这不是浏览器中的默认设置-我们使用JavaScript手动编写。



当我们要从元素中删除选择时,请按“ Esc”或任何其他键-元素丢失选择并保留在正确的位置。

屏幕阅读器


键盘上的所有内容都很清晰。 我们几乎解决了这个问题。 仍然需要教屏幕阅读器发出动作。 所需要做的只是添加说明,以便屏幕阅读器知道正在发生的事情:它在哪里以及要做什么。

为了控制屏幕阅读器所说的内容,我们将使用实时区域技术。 这是一组可以添加到元素的属性。 根据属性,屏幕阅读器会发音不同的短语。

 <div class="live-region visually-hidden"    aria-live="polite"    role="status" ></div> 


 const liveRegion = document.querySelector(".live-region«); liveRegion.textContent = ' '; 

我将aria-live属性的值为polite常规的空div ,并将rolestatus设置为status 。 对于屏幕阅读器,这是一个监听元素的信号。 当您希望屏幕阅读器说些什么时,请使用JavaScript更新内容,然后屏幕阅读器会说出该内容。

让我们看看它是如何工作的。


我们的任务是将第一个元素移到最后一个位置。 关闭屏幕上的灯,打开屏幕阅读器。

-VoiceOver已在Chrome中打开。

我们开始移动该物品。 首先,寻找我们的小部件-在标题中移动。 屏幕阅读器声音:

-二级标题。 待办事项清单。

找到了 我们继续单击Tab键。

-对象列表3.按“ Enter”键选择元素“与狗同行”。 组。

首先,屏幕阅读器会读出列表中元素的数量,以便用户了解列表中有多少个元素。 然后他说出一条指令-选择项目的操作:“按Enter键和该组件的名称。很明显,该做什么-按下Enter键。

-选择元素“与狗同行”。 使用向上和向下键移动。 使用Esc键取消选择。

我讲的是关于这些说明的信息:当您选择一个元素时,屏幕阅读器会提供我们想到的说明。 我们更新屏幕阅读器,并朗读放置在实时区域元素中的文本。 按照说明进行操作很简单-使用向上/向下和Esc键取消选择。 下移一个位置。

-元素“与狗同行”移动到位置2。

再来一次

-将元素“与狗同行”移到位置3。

该项目在列表的末尾。 打开灯,检查元素是否真的在最后位置。

按“ Esc”取消选择。

-取消“带狗散步”项目。

借助想象力,标记,JavaScript和ARIA属性,我们提供了一个小部件,对于有视力问题的用户来说是很难的。

搬家


让我们以Trello为例来看一下页面中元素的移动。 这是一个任务跟踪器,带有用于指示任务状态的列。 将任务从一列拖放到另一列对应于任务状态的更改。



模拟Trello的简化版本以弄清楚如何使该组件可用。 在我的版本中,有三列:“我会做”,“我会做”,“完成”。



任务可以从一个地方拖到另一个地方:用鼠标抓住组件,将其拖到下一列,然后释放它-它就在那里。

琴键


使用鼠标,一切都很简单;我们熟悉上一个示例中的truedraggable属性。 使用键盘,可以选择相同的选项-使用箭头将任务从一列移到另一列。 但是,如果列是5或8,则从第一个移动到最后一个将需要在右键5或8次上单击5或8次,这很不方便,并且会使得使用该组件变得困难。

否则我们将做。 按Tab键,焦点移到第一个元素。 再次按该键,将出现一个隐藏的新元素,直到焦点移入其中。



三个垂直点表示该项目将具有一个菜单。 图标可能不同。 使用select元素时,浏览器的默认行为是单击“空格”,然后出现一个菜单。

我们将使用JavaScript解决问题,但让用户有机会选择他们要移动此任务的列。



我们移至最后一列,按Enter键,一切正常-元素移至所需位置。

屏幕阅读器


添加有关屏幕阅读器的说明。 使用常规select元素具有很大的优势,因为默认情况下它是可用的。 让我们看看我们能做什么。


关闭屏幕上的灯,打开屏幕阅读器。

-VoiceOver已在Chrome中打开。

我们转到第一个元素。 屏幕阅读器会显示列表中有多少个对象。 我们使用了语义元素以及元素的名称。 按Tab键。

-“制作”:分组选择“踢足球”按钮的折叠弹出按钮。

屏幕阅读器可以发音奇怪的单词。 他称列名称为“ Make”,而屏幕阅读器的“最小化弹出窗口”则表示我们将使用菜单-对于屏幕阅读器的用户,这将是清晰的。“ Minimized”,“ pop-up”和“ button”将被发音。在不同的屏幕阅读器中有所不同,但我们不必为此担心,因为屏幕阅读器用户已熟悉此行为。

我们的任务是从列表中选择所需的列。

-不为零,请执行。 选择列展开的弹出按钮。 您当前在屏幕上的位置...“正在执行”。 “完成” ...项目“踢足球”已移至“完成”列。

这是我们手动添加的文本,用于通知用户我们已经这样做了。 这就是我们的任务委员会的工作方式。

上载档案


还可以在网站上找到文件上传功能,例如,将文件附加到电子邮件。 因此,在我的示例中,电子邮件是Gmail。



屏幕上有一个带有虚线的元素。 我们将在这里拖动文件。



为此,请打开文件所在的资源管理器,然后用鼠标将文件拖到虚线区域。 拖放后,项目将更改状态,释放文件,然后开始下载。 下载结束时,我们将通知用户所有内容均已成功下载。

琴键


使用键盘,一切都可以轻松解决。 有一个类型为file的语义input元素。 如果使用它,则单击此项目时,“浏览器”对话框将自动打开,您可以在其中从OS中选择文件。 窗口样式可以设置为任何样式,具体取决于设计人员的需求。



单击该项目,将打开一个对话框。 由于我们使用了本机input元素,因此您也可以使用Tab键移动到该元素,按空格键,将打开一个对话框。 使用Enter键选择元素,所有操作均以相同的方式进行。

一切都可以通过鼠标和键盘使用。 对于屏幕阅读器,您可以执行默认情况下本机元素未提供的操作。

屏幕阅读器


“选择”元素将起作用,我们仍然可以使用操作系统打开一个对话框。 但是,当加载开始时,我们可以做一件非常有趣的事情来更新用户的屏幕阅读器有关下载状态的信息。


打开屏幕阅读器。使用键盘,转到该项目以从OS中选择文件。

-选择按钮应用程序。

使用屏幕阅读器按按钮。

-按选择按钮。对话的开始... image image.png。3月31日... 0%... 16%已下载... 73%已下载... 100%已加载。image.png文件已成功上传。

发生什么事了 打开对话框后,我们选择了文件。我们不需要在这里做任何事情,因为屏幕阅读器与操作系统有关,与浏览器无关。像所有其他应用程序一样,文件系统可以很好地处理。

, screen reader . — 10%, 20%...100%. , , , .

Live region, . screen reader, , ARIA Live, screen reader . .

总结


. — . , , screen reader. , , .

HTML + JavaScript + ARIA . Drag-&-Drop , JavaScript ARIA. , .

« » . , « »: , , , , .

. : , , .


, W3.org — . .

, , inclusive-components.design . . , , , , , .

. , , « ». — . .

. , — Medium . , . , . , , . . , .

. FrontendConf ++ . FrontendConf 2019 Leonie Watson — , W3C W3C -. Leonie screen reader. , , , , .

FrontendConf , . , .

Source: https://habr.com/ru/post/zh-CN468541/


All Articles