-
Notifications
You must be signed in to change notification settings - Fork 654
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Добавляет доку про роль
timer
(#4786)
* Добавляет демку * Обновляет текст * Дописывает текст * Добавляет начертание * Улучшает демку * Улучшает текст * Вносит уточнения * Удаляет лишнее * Улучшает текст * Уточняет детали * Выделяет термин * Улучшает текст, дополняет его * Убирает ковычки из `<title>` * Переписывает Как понять * Исправляет очепятку * Улучшает демку * Удаляет лишний пробел * Делает мелкие уточнения * Удаляет комментарий * Объединяет параграфы * Добавляет видео с субтитрами
- Loading branch information
1 parent
7a35f29
commit 9139dc8
Showing
4 changed files
with
291 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
<!DOCTYPE html> | ||
<html lang="ru"> | ||
<head> | ||
<title>Пример с простым таймером — timer — Дока</title> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link rel="preconnect" href="https://fonts.googleapis.com"> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"> | ||
<style> | ||
*, *::before, *::after { | ||
margin: 0; | ||
padding: 0; | ||
box-sizing: border-box; | ||
} | ||
|
||
html { | ||
color-scheme: dark; | ||
font-size: 16px; | ||
} | ||
|
||
body { | ||
min-height: 100vh; | ||
padding: 50px; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
background-color: #18191C; | ||
font-family: "Roboto", sans-serif; | ||
} | ||
|
||
p { | ||
margin: 7px 0; | ||
font-size: 1rem; | ||
line-height: 1.4; | ||
} | ||
|
||
h1 { | ||
margin-bottom: 17px; | ||
font-weight: 500; | ||
font-size: 1.625rem; | ||
} | ||
|
||
.button { | ||
display: block; | ||
min-width: 210px; | ||
border: 2px solid transparent; | ||
border-radius: 6px; | ||
padding: 9px 15px; | ||
color: #000000; | ||
font-size: 1.125rem; | ||
font-weight: 300; | ||
font-family: inherit; | ||
transition: background-color 0.2s linear; | ||
} | ||
|
||
.button-aqua { | ||
background-color: #10F3AF; | ||
} | ||
|
||
.button-pink { | ||
background-color: #F498AD; | ||
} | ||
|
||
.button:hover { | ||
background-color: #FFFFFF; | ||
cursor: pointer; | ||
transition: background-color 0.2s linear; | ||
} | ||
|
||
.button:focus-visible { | ||
border: 2px solid #FFFFFF; | ||
outline: none; | ||
} | ||
|
||
.button:focus { | ||
border: 2px solid #FFFFFF; | ||
outline: none; | ||
} | ||
|
||
.timer, .timer-controls { | ||
display: flex; | ||
} | ||
|
||
.timer { | ||
gap: 130px; | ||
} | ||
|
||
.timer-controls { | ||
align-items: center; | ||
flex-wrap: wrap; | ||
margin-top: 30px; | ||
gap: 20px; | ||
} | ||
|
||
.timer__item { | ||
position: relative; | ||
font-size: 6.25rem; | ||
line-height: 1; | ||
} | ||
|
||
.timer__item--min::after, | ||
.timer__item--sec::after { | ||
bottom: 11px; | ||
padding-left: 20px; | ||
font-size: 1.375rem; | ||
} | ||
|
||
.timer__item--min::after { | ||
content: "минут"; | ||
position: absolute; | ||
} | ||
|
||
.timer__item--sec::after { | ||
content: "секунд"; | ||
position: absolute; | ||
} | ||
|
||
.timer-message { | ||
height: 22px; | ||
margin-top: 10px; | ||
} | ||
|
||
@media (max-width: 768px) { | ||
body { | ||
padding: 30px; | ||
} | ||
|
||
.timer { | ||
gap: 60px; | ||
} | ||
|
||
.timer__item--min::after, | ||
.timer__item--sec::after { | ||
left: 0; | ||
bottom: -20px; | ||
padding-left: 0; | ||
} | ||
|
||
.timer-message { | ||
margin-top: 50px; | ||
} | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div> | ||
<h1>Оставшееся время</h1> | ||
<div role="timer" class="timer" id="timer" aria-atomic="true"> | ||
<span class="timer__item timer__item--min" id="min">02</span> | ||
<span class="timer__item timer__item--sec" id="sec">00</span> | ||
</div> | ||
<div class="timer-message" id="message" aria-live="polite"></div> | ||
|
||
<div class="timer-controls"> | ||
<button class="button button-aqua" id="start-button"> | ||
Старт | ||
</button> | ||
<button class="button button-pink" id="pause-button"> | ||
Пауза | ||
</button> | ||
</div> | ||
</div> | ||
|
||
<script> | ||
const startButton = document.getElementById('start-button') | ||
const pauseButton = document.getElementById('pause-button') | ||
const timer = document.getElementById('timer') | ||
const minute = document.getElementById('min') | ||
const seconds = document.getElementById('sec') | ||
const message = document.getElementById('message') | ||
|
||
let interval | ||
let totalSeconds = 120 | ||
|
||
function setAriaLive() { | ||
timer.setAttribute('aria-live', 'polite') | ||
setTimeout(() => { | ||
timer.removeAttribute('aria-live') | ||
}, 100) | ||
} | ||
|
||
startButton.addEventListener('click', () => { | ||
startTimer() | ||
}) | ||
|
||
pauseButton.addEventListener('click', () => { | ||
pauseTimer() | ||
}) | ||
|
||
function pauseTimer() { | ||
clearInterval(interval) | ||
} | ||
|
||
function startTimer() { | ||
message.textContent = '' | ||
|
||
interval = setInterval(() => { | ||
--totalSeconds | ||
let currentMinutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0') | ||
let currentSeconds = String(totalSeconds % 60).padStart(2, '0') | ||
|
||
minute.textContent = currentMinutes | ||
seconds.textContent = currentSeconds | ||
|
||
if (totalSeconds === 119 || totalSeconds === 60 || totalSeconds === 10) { | ||
setAriaLive() | ||
} | ||
|
||
if (totalSeconds === 0) { | ||
clearInterval(interval) | ||
message.textContent = 'Время вышло!' | ||
totalSeconds = 120 | ||
minute.textContent = '02' | ||
seconds.textContent = '00' | ||
} | ||
}, 1000) | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,81 @@ | ||
--- | ||
title: "`timer`" | ||
description: "Роль для области со счётчиком." | ||
description: "Отсчитываем время доступно." | ||
authors: | ||
- doka-dog | ||
- tatianafokina | ||
contributors: | ||
- skorobaeus | ||
keywords: | ||
- доступность | ||
- a11y | ||
- ARIA | ||
- ARIA-атрибут | ||
- доступный таймер | ||
- доступный секундомер | ||
- live region | ||
- живая область | ||
- интерактивная область | ||
related: | ||
- a11y/role-status | ||
- a11y/role-alert | ||
- a11y/aria-live | ||
tags: | ||
- doka | ||
- placeholder | ||
--- | ||
|
||
## Кратко | ||
|
||
[Роль изменяющихся областей](/a11y/aria-roles/#roli-izmenyayushchihsya-oblastey). Делает часть страницы live region или «живой» областью. `timer` нужна для областей со счётчиками, которые отсчитывают время в обычном или обратном порядке. | ||
[Роль изменяющихся областей](/a11y/aria-roles/#roli-izmenyayushchihsya-oblastey) из [WAI-ARIA](/a11y/aria-intro/#specifikaciya). Делает часть страницы изменяющейся или «живой» областью. `timer` пригодится для областей, где идёт отсчёт времени в обычном или обратном порядке. | ||
|
||
## Пример | ||
|
||
```html | ||
<div id="clock" role="timer" aria-live="polite"> | ||
<span id="clock-hours"></span> | ||
<span id="clock-mins"></span> | ||
<div role="timer"> | ||
<span id="timer-hours">00</span> | ||
<span id="timer-mins">00</span> | ||
</div> | ||
``` | ||
|
||
## Как пишется | ||
|
||
Добавьте к тегу атрибут `role="timer"`. Роль можно использовать для всех тегов. | ||
Добавьте к элементу атрибут `role="timer"`. Роль можно использовать для всех тегов и [ARIA-ролей](/a11y/aria-roles/). | ||
|
||
У `timer` по умолчанию есть свойство [`aria-live="off"`](/a11y/aria-live/). | ||
Внутри контейнера с ролью таймера не обязательно использовать [`<time>`](/html/time/) и указывать время в машиночитаемом формате. Это могут быть обычные цифры и текст. | ||
|
||
[Скринридер](/a11y/screenreaders/) объявит об изменениях в области с `timer` после завершения пользователями действий со страницей и другой информации. | ||
По умолчанию у `timer` есть свойство [`aria-live="off"`](/a11y/aria-live/). Так что [скринридеры](/a11y/screenreaders/) не расскажут об изменениях до того, как пользователь сделает на фокус на области с этой ролью. | ||
|
||
Чтобы скринридер объявлял об изменениях через определённый интервал времени, используйте [JavaScript](/js/). Для этого переключайте значение `aria-live` c `off` на `polite` через нужный промежуток времени. Например, каждые 60 минут. | ||
Чтобы изменить поведение роли, используйте `aria-live` со значением `polite` и [JavaScript](/js/). Переключайте значение c `polite` на `off` или удаляйте весь атрибут через нужные интервалы времени. Например, каждые 60 минут. Так объявления не будут навязчивыми. В большинстве случаев лучше не изменять поведение `timer`. Например, постоянно рассказывать о том, сколько часов, минут и секунд осталось до Чёрной пятницы, — не самая лучшая идея. Пользователям скринридеров будет мучительно это слушать 😫 Другое дело — отсчёт времени до конца теста или на выполнение банковской операции. В этом случае пользователям важно знать, сколько у них осталось времени. | ||
|
||
## Как понять | ||
Атрибут [`aria-atomic="true"`](/a11y/aria-busy/) поможет улучшить таймер. Благодаря ему вспомогательные технологии расскажут про всё содержимое таймера, а не только про изменившиеся часы, секунды или минуты. Например, таймер отсчитывает две минуты в обратном направлении. Когда остаётся 59 секунд, без `aria-atomic` скринридер расскажет только о минутах: «Ноль минут». Так что пользователи могут подумать, что время вышло, хотя у них осталась ещё пара секунд. Чтобы объявления не были назойливыми, устанавливайте интервалы между объявлениями. Это удобно делать [функцией `setInterval()`](/js/setinterval/). Так можно добавлять и удалять `aria-live="true"` через нужные промежутки времени. | ||
|
||
В примере элементу, в котором отсчитывается время, заданы `role="timer"` и `aria-atomic="true"`. После того, как время вышло, появляется сообщение «Время вышло!». `aria-live` удаляется и добавляется через секунду после начала отсчёта, потом через минуту и затем за 10 секунд до завершения. | ||
|
||
Подсказки про то, минуты это или секунды, добавлены с помощью псевдоэлемента [`::after`](/css/after/) и [`content`](/css/content/). Скринридеры всегда зачитывают текст из этого CSS-свойства. | ||
|
||
«Живая» область — это область страницы, в которой что-то постоянно обновляется из-за внешних событий. Например, появляется уведомление или ошибка, когда пользователь сделал что-то неправильно. Так пользователи скринридеров могут узнать об изменениях автоматически, без перехода к этой части страницы. | ||
```html | ||
<h2>Оставшееся время</h2> | ||
<div | ||
role="timer" | ||
id="timer" | ||
aria-atomic="true" | ||
> | ||
<span id="min">02</span> | ||
<span id="sec">00</span> | ||
</div> | ||
<div id="message" aria-live="polite"></div> | ||
``` | ||
|
||
<iframe title="Таймер с ролью timer" src="demos/basic-timer/" height="500"></iframe> | ||
|
||
<video controls width="640"> | ||
<source src="video/role-timer.mp4" type="video/mp4"> | ||
<track | ||
label="Russian" | ||
kind="subtitles" | ||
srclang="ru" | ||
src="video/closed-captions.vtt" | ||
> | ||
</video> | ||
Элементам с `role="timer"` можно задавать подписи. Для видимой подойдёт атрибут [`aria-labelledby`](/a11y/aria-labelledby/), а для невидимой — [`aria-label`](/a11y/aria-label/). Только помните, что хоть на практике и можно добавлять подписи ко всем элементам, спецификация не рекомендует подписывать [`<div>`](/html/div/), [`<span>`](/html/span/) и другие неинтерактивные элементы. | ||
|
||
## Как понять | ||
|
||
Роль `timer` часто используют для таймеров. | ||
_Изменяющаяся область_ — это область страницы, в которой содержимое обновляется из-за внешних событий или действий пользователей. Благодаря изменяющимся областям вспомогательные технологии узнают об обновлениях на странице и автоматически рассказывают о них пользователям. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
WEBVTT | ||
00:00:00.001 --> 00:00:01.134 | ||
(NVDA) | ||
Старт, кнопка. | ||
|
||
00:00:02.253 --> 00:00:07.404 | ||
Ноль-один минут, | ||
пятьдесят девять секунд. | ||
|
||
00:00:12.833 --> 00:00:15.021 | ||
Ноль-один минут, | ||
ноль-ноль секунд. | ||
|
||
00:00:20.004 --> 00:00:22.214 | ||
Ноль-ноль минут, | ||
десять секунд. | ||
|
||
00:00:30.047 --> 00:00:31.370 | ||
Время вышло! |
Binary file not shown.