From 104b82b20e75271476e6d3243a4b75574e6db036 Mon Sep 17 00:00:00 2001 From: "Patrick H. Lauke" Date: Fri, 22 Nov 2024 18:05:19 +0000 Subject: [PATCH 01/14] Change "NEW" marker to use W3C blue background (#4145) Instead of the original red - see https://github.com/w3c/wcag/pull/1481#issuecomment-2447584448 --- guidelines/guidelines.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guidelines/guidelines.css b/guidelines/guidelines.css index e7ca78324b..889a6ab499 100644 --- a/guidelines/guidelines.css +++ b/guidelines/guidelines.css @@ -5,7 +5,7 @@ .change { display: inline; color: #fff; - background: #B50000; + background: #005A9C; border-radius: 0.25em; padding: 0.25em 0.4em; margin: 0 0.25em 0 0; From aa4315333622dbc61571e7d9fc52a804d4f74e96 Mon Sep 17 00:00:00 2001 From: "Patrick H. Lauke" Date: Fri, 22 Nov 2024 18:49:19 +0000 Subject: [PATCH 02/14] Add explanation of what "automatic" means in 2.2.2 and 1.4.2, cross-reference (#4012) Closes https://github.com/w3c/wcag/issues/2863 This is an alternative to https://github.com/w3c/wcag/pull/2906 which more directly addresses the definition, as well as providing further explanation/cross-linking for overlapping SCs: * removes the mention of "audio" from the intent for 2.2.2 Pause, Stop, Hide, which is clearly aimed at visual content only * adds a basic explanation of what's meant by "starts automatically" to 2.2.2 * adds relevant cross-references/overlaps to other SCs to 2.2.2 * adds a basic explanation of what's meant by "plays automatically" to 1.4.2 Audio Control * adds a further clarification to 2.3.3 Animation from Interactions --------- Co-authored-by: Alastair Campbell Co-authored-by: Mike Gower --- understanding/20/audio-control.html | 71 +------- understanding/20/pause-stop-hide.html | 164 +++++------------- .../21/animation-from-interactions.html | 54 +++--- 3 files changed, 75 insertions(+), 214 deletions(-) diff --git a/understanding/20/audio-control.html b/understanding/20/audio-control.html index 5ebd2fc3b4..0009d2697e 100644 --- a/understanding/20/audio-control.html +++ b/understanding/20/audio-control.html @@ -1,157 +1,104 @@ - + Understanding Audio Control

Understanding Audio Control

- +

In brief

Goal
A page that plays music or sounds doesn't disrupt people.
What to do
If you play audio content automatically, let people turn it down or off.
-
Why it's important
Sound distracts some people, and also interferes with screen readers.
+
Why it's important
Sound distracts some people, and also interferes with screen readers.
- +

Intent of Audio Control

- -

Individuals who use screen reading software can find it hard to hear the speech output if there is other audio playing at the same time. This difficulty is exacerbated when the screen reader's speech output is software based (as most are today) and is controlled via the same volume control as the sound. Therefore, it is important that the user - be able to turn off the background sound. + be able to turn off the background sound.

Having control of the volume includes being able to reduce its volume to zero. Muting the system volume is not "pausing or stopping" the autoplay audio. Both the "pause or stop" and control of audio volume need to be independent of the overall system volume.

-
-

Playing audio automatically when landing on a page may affect a screen reader user's ability to find the mechanism to stop it because they navigate by listening and automatically started sounds might interfere with that navigation. Therefore, we discourage the practice of automatically starting sounds (especially if they last more than 3 seconds), - and encourage that the sound be + and encourage that the sound be started by an action initiated by the user after they reach the page, rather than requiring - that the sound be + that the sound be stopped by an action of the user after they land on the page.

-
- -

See also - 1.4.7: Low or No Background Audio. -

- - +

See also 1.4.7 Low or No Background Audio.

+

In the context of this Success Criterion, "plays automatically" broadly refers to audio that is not started/played as a direct result of a user's intentional activation. For example, not selecting a link or button.

Benefits of Audio Control

- -
    -
  • Individuals who use screen reading technologies can hear the screen reader without other sounds playing. This is especially important for those who are hard of hearing and for those whose screen readers use the system volume (so they cannot turn sound down and screen reader up).
  • -
  • This Success Criterion also benefits people who have difficulty focusing on visual content (including text) when audio is playing.
  • -
-
-

Examples of Audio Control

-
  • An audio file begins playing automatically when a page is opened. However, the audio can be stopped by the user by selecting a "silent" link at the top of the page.
-
-

Resources for Audio Control

- -
-

Techniques for Audio Control

- -

Sufficient Techniques for Audio Control

- - -
-

Additional Techniques (Advisory) for Audio Control

- -
-

Failures for Audio Control

- - -
-
- diff --git a/understanding/20/pause-stop-hide.html b/understanding/20/pause-stop-hide.html index e513facd7c..eebf9d6ead 100644 --- a/understanding/20/pause-stop-hide.html +++ b/understanding/20/pause-stop-hide.html @@ -1,107 +1,85 @@ - + Understanding Pause, Stop, Hide

Understanding Pause, Stop, Hide

- +

In brief

Goal
Fewer users are distracted by content that updates or moves.
What to do
Let users control content changes that occur in parallel with other content.
-
Why it's important
Some people with cognitive disabilities and attention deficits cannot concentrate with continual movement.
+
Why it's important
Some people with cognitive disabilities and attention deficits are distracted by continuous movement.
- +

Intent of Pause, Stop, Hide

- - +

The intent of this Success Criterion is to avoid distracting users during their interaction with a Web page.

- + +

In the context of this Success Criterion, "starts automatically" broadly refers to animations/updates + that are not the direct result of a user's intentional activation, for example, selecting a link or button.

+

"Moving, blinking and scrolling" refers to content in which the visible content conveys a sense of motion. Common examples include motion pictures, synchronized media presentations, animations, real-time games, and scrolling stock tickers. "Auto-updating" refers to content that updates or disappears based on a preset time interval. Common time-based - content includes audio, automatically updated weather information, news, stock price + content includes automatically updated weather information, news, stock price updates, and auto-advancing presentations and messages. The requirements for moving, blinking and scrolling content and for auto-updating content are the same except that:

- +
    - -
  • authors have the option of providing the user with a means to control the frequency - of updates when content is auto-updating and -
  • - -
  • there is no five second exception for auto-updating since it makes little sense to - auto-update for a few seconds and then stop -
  • - +
  • authors have the option of providing the user with a means to control the frequency of updates when content is auto-updating and
  • +
  • there is no five second exception for auto-updating since it makes little sense to auto-update for a few seconds and then stop
- +

Content that moves or auto-updates can be a barrier to anyone who has trouble reading stationary text quickly as well as anyone who has trouble tracking moving objects. It can also cause problems for screen readers.

- +

Moving content can also be a severe distraction for some people. Certain groups, particularly those with attention deficit disorders, find blinking content distracting, making it difficult for them to concentrate on other parts of the Web page. Five seconds was chosen because it is long enough to get a user's attention, but not so long that a user cannot wait out the distraction if necessary to use the page.

- +

Content that is paused can either resume in real-time or continue playing from the point in the presentation where the user left off.

- +
    -
  • -

    Pausing and resuming where the user left off is best for users who want to pause to read content and works best when the content is not associated with a real-time event or status.

    -
    - -

    See - 2.2.1: Timing Adjustable for additional requirements related to time-limits for reading. -

    - +

    See 2.2.1: Timing Adjustable for additional requirements related to time-limits for reading and interactions.

    -
  • -
  • -

    Pausing and jumping to current display (when pause is released) is better for information that is real-time or "status" in nature. For example, weather radar, a stock ticker, a traffic camera, or an auction timer, would present misleading information if a pause caused it to display old information when the content was restarted.

    -
    - -

    Hiding content would have the same result as pausing and jumping to current display - (when pause is released). -

    - +

    Hiding content would have the same result as pausing and jumping to current display (when pause is released).

    -
  • -
- +

For a mechanism to be considered "a mechanism for the user to pause," it must provide the user with a means to pause that does not tie up the user or the focus so that the page cannot be used. The word "pause" here is meant in the sense of a "pause @@ -110,58 +88,58 @@

Intent of Pause, Stop, Hide

moves the focus away) would not be considered a "mechanism for the user to pause" because it makes the page unusable in the process and would not meet this SC.

- -

It is important to note that the terms "blinking" and "flashing" can sometimes refer - to the same content. -

- + +
+

This Success Criterion is specifically concerned with moving, blinking, scrolling, and + auto-updating visual content. For audio content that starts automatically, refer to 1.4.2 Audio Control.

+

Moving, blinking, scrolling content that starts automatically because of a general user interaction (such as focusing/hovering over an element, + or scrolling the page), rather than as a result of an intentional activation (such as activating a button), + and which doesn't provide provide a way to Pause, Stop, or Hide, will fail this Criterion, and potentially + 2.3.3 Animation from Interaction.

+
+ +

It is important to note that the terms "blinking" and "flashing" can sometimes refer to the same content.

+
    -
  • "Blinking" refers to content that causes a distraction problem. Blinking can be allowed for a short time as long as it stops (or can be stopped)
  • -
  • "Flashing" refers to content that can trigger a seizure (if it is more than 3 per second and large and bright enough). This cannot be allowed even for a second or it could cause a seizure. And turning the flash off is also not an option since the seizure could occur faster than most users could turn it off.
  • -
  • Blinking usually does not occur at speeds of 3 per second or more, but it can. If blinking occurs faster than 3 per second, it would also be considered a flash.
  • -
- - + +
+

"Flashing" content that starts automatically will need to be evaluated against 2.3.2 Three Flashes + and 2.3.1 Three Flashes or Below Threshold. +

+
+

Benefits of Pause, Stop, Hide

- - +
    -
  • Providing content that stops blinking after five seconds or providing a mechanism for users to stop blinking content allows people with certain disabilities to interact with the Web page.
  • -
  • One use of content that blinks is to draw the visitor's attention to that content. Although this is an effective technique for all users with vision, it can be a problem for some users if it persists. For certain groups, including people with low literacy, reading and intellectual disabilities, and people with attention deficit disorders, content that blinks may make it difficult or even impossible to interact with the - rest of the Web page. - + rest of the Web page.
  • -
-
-

Examples of Pause, Stop, Hide

-
An essential animation can be paused without affecting the activity
A Web site helps users understand 'how things work' through animations that demonstrate @@ -195,127 +173,69 @@

Examples of Pause, Stop, Hide

for all users and because it is not presented in parallel with other content, no mechanism to pause, stop or hide it needs to be provided.
-
-

Resources for Pause, Stop, Hide

- -
-

Techniques for Pause, Stop, Hide

- -

Sufficient Techniques for Pause, Stop, Hide

- - -
-

Additional Techniques (Advisory) for Pause, Stop, Hide

-
-

Failures for Pause, Stop, Hide

- - -
-
- diff --git a/understanding/21/animation-from-interactions.html b/understanding/21/animation-from-interactions.html index d5b51b9378..9cd3d1710e 100644 --- a/understanding/21/animation-from-interactions.html +++ b/understanding/21/animation-from-interactions.html @@ -15,20 +15,20 @@

In brief

What to do
Support user preferences for motion, and eliminate unnecessary motion effects.
Why it's important
People can get sick from motion effects.
- - - + + +

Intent

The intent of this Success Criterion is to allow users to prevent animation from being displayed on Web pages. Some users experience distraction or nausea from animated content. For example, if scrolling a page causes elements to move (other than the essential movement associated with scrolling) it can trigger vestibular disorders. Vestibular (inner ear) disorder reactions include dizziness, nausea and headaches. Another animation that is often non-essential is parallax scrolling. Parallax scrolling occurs when backgrounds move at a different rate to foregrounds. Animation that is essential to the functionality or information of a web page is allowed by this Success Criterion.

-

"Animation from interactions" applies when a user’s interaction initiates non-essential animation. In contrast, 2.2.2 Pause, Stop, Hide applies when the web page initiates animation.

+

"Animation from interactions" applies when a user’s interaction initiates non-essential animation. In contrast, 2.2.2 Pause, Stop, Hide applies when the web page initiates animation "automatically" that is not in response to an intentional user activation. There may be situations where a particular animation may fail both Success Criteria.

The impact of animation on people with vestibular disorders can be quite severe. Triggered reactions include nausea, migraine headaches, and potentially needing bed rest to recover.

How can a website reduce the chances of triggering a vestibular disorder? Choose any one of the following solutions. Avoid using unnecessary animation. Provide a control for users to turn off non-essential animations from user interaction. Take advantage of the reduce motion feature in the user agent or operating system.

- +

What about movement caused by a user scrolling a page? Moving new content into the viewport is essential for scrolling. The user controls the essential scrolling movement so it is allowed. Only add non-essential animation to the scrolling interaction in a responsible way. Always give users the ability to turn off unnecessary movement.

@@ -44,35 +44,29 @@

Benefits

Examples

-
    -
  • Parallax scrolling with option to turn off unnecessary motion globally: -
      -
    • A site includes extra animations when the user scrolls. Decorative elements move in and out of view horizontally when the essential page content is scrolled vertically. A control at the top of each page allows the user to turn off unnecessary animations. The ability to turn off non-essential animations is a site-wide setting.
    • -
    -
  • -
  • Transitions that support the reduce motion preference: -
      -
    • A site includes a non-essential transition when loading new content. The transition is a page-flipping animation that respects the reduce-motion CSS media query. When the user enables the reduce motion preference, the page-flipping animation is turned off.
    • -
    -
  • -
  • Essential animation: -
      -
    • A web application provides a feature to author animated sequences. As part of this tool the author needs to preview the animation.
    • -
    -
  • -
+
+
Parallax scrolling with option to turn off unnecessary motion globally
+
A site includes extra animations when the user scrolls. Decorative elements move in and out of view + horizontally when the essential page content is scrolled vertically. A control at the top of each page + allows the user to turn off unnecessary animations. The ability to turn off non-essential animations is a site-wide setting.
+
Transitions that support the reduce motion preference
+
A site includes a non-essential transition when loading new content. The transition is a page-flipping + animation that respects the reduce-motion CSS media query. When the user enables the reduce motion preference, + the page-flipping animation is turned off.
+
Essential animation
+
A web application provides a feature to author animated sequences. As part of this tool the author needs to preview the animation.
+

Resources

From 6ec98a3e4256b40a7ba6a20f01144753a010144b Mon Sep 17 00:00:00 2001 From: "Kenneth G. Franqueiro" Date: Wed, 27 Nov 2024 17:20:03 -0500 Subject: [PATCH 03/14] Update 11ty-publish workflow to use git-auto-commit-action (#4154) This update resolves spurious errors in the publish workflow in cases where a merge to `main` results in no changes to push to `gh-pages`. - [Example of the type of error this addresses](https://github.com/kfranqueiro/wcag/actions/runs/12036136821/job/33556666057) - [Example of the same type of run succeeding with this change](https://github.com/kfranqueiro/wcag/actions/runs/12036196134/job/33556861412) - [Example of a run completing with this change, operating as usual when there are changes to commit to `gh-pages`](https://github.com/kfranqueiro/wcag/actions/runs/12036639462/job/33558323786) --- .github/workflows/11ty-publish.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/11ty-publish.yaml b/.github/workflows/11ty-publish.yaml index fd2ec74e6b..198641fc31 100644 --- a/.github/workflows/11ty-publish.yaml +++ b/.github/workflows/11ty-publish.yaml @@ -36,10 +36,13 @@ jobs: curl https://labs.w3.org/spec-generator/?type=respec"&"url=https://raw.githack.com/$GITHUB_REPOSITORY/main/requirements/22/index.html -o _site/requirements/22/index.html -f --retry 3 curl https://labs.w3.org/spec-generator/?type=respec"&"url=https://raw.githack.com/$GITHUB_REPOSITORY/main/conformance-challenges/index.html -o _site/conformance-challenges/index.html -f --retry 3 - name: Push - working-directory: _site - run: | - git config user.email 87540780+w3cgruntbot@users.noreply.github.com - git config user.name w3cgruntbot - git add -A . - git commit -m ":robot: Deploy to GitHub Pages: $GITHUB_SHA from branch $GITHUB_REF" - git push origin gh-pages + uses: stefanzweifel/git-auto-commit-action@v5 + with: + repository: _site + branch: gh-pages + commit_user_name: w3cgruntbot + commit_user_email: 87540780+w3cgruntbot@users.noreply.github.com + commit_author: "w3cgruntbot <87540780+w3cgruntbot@users.noreply.github.com>" + commit_message: ":robot: Deploy to GitHub Pages: ${{ github.sha }} from branch ${{ github.ref }}" + skip_fetch: true + skip_checkout: true From 7aad7a702bd17bc23785f7bc8fba1278d6d6dc67 Mon Sep 17 00:00:00 2001 From: "Kenneth G. Franqueiro" Date: Thu, 28 Nov 2024 06:12:13 -0500 Subject: [PATCH 04/14] Pin definitions when building an older version (#4155) This is a follow-up to #4007, in which I had neglected to pin definitions for key terms to the published recommendation when building for 2.1. - Moves `termsMap` definition to the Eleventy config (where all other target-version-dependent assignments are made), to be passed into the `CustomLiquid` constructor - Updates `termsMap` references within `CustomLiquid` to use an instance variable set in the constructor - Updates `loadRemoteGuidelines` to account for pre-processed terms content - Also updates to account for #4124 - Skips entirety of custom `render` processing for pages not being output for 2.1 (to avoid irrelevant error messages as well as save time) --- 11ty/CustomLiquid.ts | 26 +++++++++++++++++--------- 11ty/guidelines.ts | 30 +++++++++++++++++------------- 11ty/types.ts | 2 +- eleventy.config.ts | 4 ++++ 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/11ty/CustomLiquid.ts b/11ty/CustomLiquid.ts index 1a302627c6..948a4847f3 100644 --- a/11ty/CustomLiquid.ts +++ b/11ty/CustomLiquid.ts @@ -1,5 +1,5 @@ import { Liquid, type Template } from "liquidjs"; -import type { RenderOptions } from "liquidjs/dist/liquid-options"; +import type { LiquidOptions, RenderOptions } from "liquidjs/dist/liquid-options"; import compact from "lodash-es/compact"; import uniq from "lodash-es/uniq"; @@ -10,7 +10,7 @@ import type { GlobalData } from "eleventy.config"; import { biblioPattern, getBiblio } from "./biblio"; import { flattenDom, load, type CheerioAnyNode } from "./cheerio"; import { generateId } from "./common"; -import { getAcknowledgementsForVersion, getTermsMap } from "./guidelines"; +import { getAcknowledgementsForVersion, type TermsMap } from "./guidelines"; import { resolveTechniqueIdFromHref, understandingToTechniqueLinkSelector } from "./techniques"; import { techniqueToUnderstandingLinkSelector } from "./understanding"; @@ -22,7 +22,6 @@ const techniquesPattern = /\btechniques\//; const understandingPattern = /\bunderstanding\//; const biblio = await getBiblio(); -const termsMap = await getTermsMap(); const termLinkSelector = "a:not([href])"; /** Generates {% include "foo.html" %} directives from 1 or more basenames */ @@ -72,6 +71,10 @@ function expandTechniqueLink($el: CheerioAnyNode) { const stripHtmlComments = (html: string) => html.replace(//g, ""); +interface CustomLiquidOptions extends LiquidOptions { + termsMap: TermsMap; +} + // Dev note: Eleventy doesn't expose typings for its template engines for us to neatly extend. // Fortunately, it passes both the content string and the file path through to Liquid#parse: // https://github.com/11ty/eleventy/blob/9c3a7619/src/Engines/Liquid.js#L253 @@ -84,6 +87,11 @@ const stripHtmlComments = (html: string) => html.replace(//g, "") * - generating/expanding sections with auto-generated content */ export class CustomLiquid extends Liquid { + termsMap: TermsMap; + constructor(options: CustomLiquidOptions) { + super(options); + this.termsMap = options.termsMap; + } public parse(html: string, filepath?: string) { // Filter out Liquid calls for computed data and includes themselves if (filepath && !filepath.includes("_includes/") && isHtmlFileContent(html)) { @@ -300,7 +308,7 @@ export class CustomLiquid extends Liquid { public async render(templates: Template[], scope: GlobalData, options?: RenderOptions) { // html contains markup after Liquid tags/includes have been processed const html = (await super.render(templates, scope, options)).toString(); - if (!isHtmlFileContent(html) || !scope) return html; + if (!isHtmlFileContent(html) || !scope || scope.page.url === false) return html; const $ = load(html); @@ -414,7 +422,7 @@ export class CustomLiquid extends Liquid { .toLowerCase() .trim() .replace(/\s*\n+\s*/, " "); - const term = termsMap[name]; + const term = this.termsMap[name]; if (!term) { console.warn(`${scope.page.inputPath}: Term not found: ${name}`); return; @@ -428,7 +436,7 @@ export class CustomLiquid extends Liquid { const $el = $(el); const termName = extractTermName($el); $el - .attr("href", `${scope.guidelinesUrl}#${termName ? termsMap[termName].trId : ""}`) + .attr("href", `${scope.guidelinesUrl}#${termName ? this.termsMap[termName].trId : ""}`) .attr("target", "terms"); }); } else if (scope.isUnderstanding) { @@ -442,7 +450,7 @@ export class CustomLiquid extends Liquid { // since terms may reference other terms in their own definitions. // Each iteration may append to termNames. for (let i = 0; i < termNames.length; i++) { - const term = termsMap[termNames[i]]; + const term = this.termsMap[termNames[i]]; if (!term) continue; // This will already warn via extractTermNames const $definition = load(term.definition); @@ -459,7 +467,7 @@ export class CustomLiquid extends Liquid { return 0; }); for (const name of termNames) { - const term = termsMap[name]; // Already verified existence in the earlier loop + const term = this.termsMap[name]; // Already verified existence in the earlier loop $termsList.append( `
${term.name}
` + `
${term.definition}
` @@ -469,7 +477,7 @@ export class CustomLiquid extends Liquid { // Iterate over non-href links once more in now-expanded document to add hrefs $(termLinkSelector).each((_, el) => { const name = extractTermName($(el)); - el.attribs.href = `#${name ? termsMap[name].id : ""}`; + el.attribs.href = `#${name ? this.termsMap[name].id : ""}`; }); } else { // No terms: remove skeleton that was placed in #parse diff --git a/11ty/guidelines.ts b/11ty/guidelines.ts index cbdc084bcb..0dc8ace485 100644 --- a/11ty/guidelines.ts +++ b/11ty/guidelines.ts @@ -197,14 +197,17 @@ interface Term { /** id of dfn in TR, which matches original id in terms file */ trId: string; } +export type TermsMap = Record; /** * Resolves term definitions from guidelines/index.html organized for lookup by name; * comparable to the term elements in wcag.xml from the guidelines-xml Ant task. */ -export async function getTermsMap() { - const $ = await flattenDomFromFile("guidelines/index.html"); - const terms: Record = {}; +export async function getTermsMap(version?: WcagVersion) { + const $ = version + ? await loadRemoteGuidelines(version) + : await flattenDomFromFile("guidelines/index.html"); + const terms: TermsMap = {}; $("dfn").each((_, el) => { const $el = $(el); @@ -240,24 +243,25 @@ const loadRemoteGuidelines = async (version: WcagVersion) => { ); // Re-collapse definition links and notes, to be processed by this build system - $(".guideline a.internalDFN").removeAttr("class data-link-type id href title"); - $(".guideline [role='note'] .marker").remove(); - $(".guideline [role='note']").find("> div, > p").addClass("note").unwrap(); + $("a.internalDFN").removeAttr("class data-link-type id href title"); + $("[role='note'] .marker").remove(); + $("[role='note']").find("> div, > p").addClass("note").unwrap(); - // Bibliography references are not processed in Understanding SC boxes - $(".guideline cite:has(a.bibref:only-child)").each((_, el) => { + // Un-process bibliography references, to be processed by CustomLiquid + $("cite:has(a.bibref:only-child)").each((_, el) => { const $el = $(el); - const $parent = $el.parent(); - $el.remove(); - // Remove surrounding square brackets (which aren't in a dedicated element) - $parent.html($parent.html()!.replace(/ \[\]/g, "")); + $el.replaceWith(`[${$el.find("a.bibref").html()}]`); }); + // Remove generated IDs and markers from examples + $(".example[id]").removeAttr("id"); + $(".example .marker:has(.self-link)").remove(); + // Remove extra markup from headings so they can be parsed for names $("bdi").remove(); // Remove abbr elements which exist only in TR, not in informative docs - $("#acknowledgements li abbr").each((_, abbrEl) => { + $("#acknowledgements li abbr, #glossary abbr").each((_, abbrEl) => { $(abbrEl).replaceWith($(abbrEl).text()); }); diff --git a/11ty/types.ts b/11ty/types.ts index 9bdd86c9f1..ed89e25178 100644 --- a/11ty/types.ts +++ b/11ty/types.ts @@ -9,7 +9,7 @@ interface EleventyPage { outputPath: string; rawInput: string; templateSyntax: string; - url: string; + url: string | false; // (false when permalink is set to false for the page) } interface EleventyDirectories { diff --git a/eleventy.config.ts b/eleventy.config.ts index 4313c5f2fa..d579a657ff 100644 --- a/eleventy.config.ts +++ b/eleventy.config.ts @@ -14,6 +14,7 @@ import { getFlatGuidelines, getPrinciples, getPrinciplesForVersion, + getTermsMap, scSlugOverrides, type FlatGuidelinesMap, type Guideline, @@ -103,6 +104,8 @@ for (const [technology, list] of Object.entries(techniques)) { const understandingDocs = await getUnderstandingDocs(version); const understandingNav = await generateUnderstandingNavMap(principles, understandingDocs); +const termsMap = process.env.WCAG_VERSION ? await getTermsMap(version) : await getTermsMap(); + // Declare static global data up-front so we can build typings from it const globalData = { version, @@ -274,6 +277,7 @@ export default function (eleventyConfig: any) { root: ["_includes", "."], jsTruthy: true, strictFilters: true, + termsMap, }) ); From 079df5e52d7a2d16b3240c4398d489d53d0c777b Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 6 Dec 2024 15:54:29 +0000 Subject: [PATCH 05/14] Update for 2.2 publication Dec 2024 (#4163) --- guidelines/respec-config.js | 56 ++++++------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/guidelines/respec-config.js b/guidelines/respec-config.js index a6189081a5..75d1ff7d1d 100644 --- a/guidelines/respec-config.js +++ b/guidelines/respec-config.js @@ -8,10 +8,10 @@ var respecConfig = { permalinkHide: false, tocIntroductory: true, // specification status (e.g., WD, LC, NOTE, etc.). If in doubt use ED. - specStatus: "ED", + specStatus: "REC", //crEnd: "2012-04-30", //perEnd: "2013-07-23", - publishDate: "2023-10-05", + publishDate: "2024-12-12", diffTool: "http://www.aptest.com/standards/htmldiff/htmldiff.pl", // the specifications short name, as in https://www.w3.org/TR/short-name/ @@ -62,62 +62,22 @@ var respecConfig = { companyURI: "https://loc.gov/", w3cid: 90310 }, - { + { name: "Michael Cooper", url: 'https://www.w3.org/People/cooper', - //mailto: "cooper@w3.org", company: "W3C", companyURI: "https://www.w3.org", - w3cid: 34017 + w3cid: 34017, + retiredDate: "2023-07-31" }, { name: "Andrew Kirkpatrick", - //url: "http://www.adobe.com/", - mailto: "akirkpat@adobe.com", company: "Adobe", companyURI: "http://www.adobe.com/", - w3cid: 39770 + w3cid: 39770, + retiredDate: "2020-03-04" } - ], - /* - formerEditors: [ - { - name: "Ben Caldwell", - company: "Trace R&D Center, University of Wisconsin-Madison", - w3cid: 33602 - }, - { - name: "Loretta Guarino Reid", - company: "Google, Inc.", - w3cid: 35436 - }, - { - name: "Gregg Vanderheiden", - company: "Trace R&D Center, University of Wisconsin-Madison", - w3cid: 3442 - }, - { - name: "Wendy Chisholm", - company: "W3C", - w3cid: 4099 - }, - { - name: "John Slatin", - company: "Accessibility Institute, University of Texas at Austin", - w3cid: 35537 - }, - { - name: "Jason White", - company: "University of Melbourne", - w3cid: 74028 - }, - { - name: "Joshue O Connor", - company: "Invited Expert, InterAccess", - w3cid: 41218 - } - ], - */ + ], // authors, add as many as you like. // This is optional, uncomment if you have authors as well as editors. From fd311595df3639495869b46ad243d7fe398899e7 Mon Sep 17 00:00:00 2001 From: "Kenneth G. Franqueiro" Date: Fri, 6 Dec 2024 18:12:47 -0500 Subject: [PATCH 06/14] Tolerate specref API failures during local dev (#4167) Since #4124 was merged, all builds require an HTTP request to api.specref.org in order to resolve additional bibliographical references. This may cause issues in local dev in the case of being offline due to travel or internet hiccups, behind a proxy, etc. This commit adds a reusable function for cases where a HTTP failure during local dev is tolerable, and uses it for the bibrefs request. Running `npm build` will still result in an immediate failure and stack trace; this is intentional to ensure that nothing slips by during builds for PR previews, GitHub Pages, or w3.org. --- 11ty/biblio.ts | 14 +++++++++----- 11ty/common.ts | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/11ty/biblio.ts b/11ty/biblio.ts index 24a809fdb8..fcf5faca80 100644 --- a/11ty/biblio.ts +++ b/11ty/biblio.ts @@ -3,6 +3,8 @@ import { readFile } from "fs/promises"; import { glob } from "glob"; import uniq from "lodash-es/uniq"; +import { wrapAxiosRequest } from "./common"; + export const biblioPattern = /\[\[\??([\w-]+)\]\]/g; /** Compiles URLs from local biblio + specref for linking in Understanding documents. */ @@ -12,7 +14,7 @@ export async function getBiblio() { .replace(/^respecConfig\.localBiblio\s*=\s*/, "(") .replace("};", "})") ); - + const refs: string[] = []; for (const path of await glob(["guidelines/**/*.html", "understanding/*/*.html"])) { const content = await readFile(path, "utf8"); @@ -20,16 +22,18 @@ export async function getBiblio() { while ((match = biblioPattern.exec(content))) if (!localBiblio[match[1]]) refs.push(match[1]); } const uniqueRefs = uniq(refs); - - const response = await axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`); + + const response = await wrapAxiosRequest( + axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`) + ); const fullBiblio = { ...response.data, ...localBiblio, }; - + const resolvedRefs = Object.keys(fullBiblio); const unresolvedRefs = uniqueRefs.filter((ref) => !resolvedRefs.includes(ref)); if (unresolvedRefs.length) console.warn(`Unresolved biblio refs: ${unresolvedRefs.join(", ")}`); - + return fullBiblio; } diff --git a/11ty/common.ts b/11ty/common.ts index ade5d87f14..bda9ec4618 100644 --- a/11ty/common.ts +++ b/11ty/common.ts @@ -1,5 +1,7 @@ /** @fileoverview Common functions used by multiple parts of the build process */ +import { AxiosError, type AxiosResponse } from "axios"; + import type { Guideline, Principle, SuccessCriterion } from "./guidelines"; /** Generates an ID for heading permalinks. Equivalent to wcag:generate-id in base.xslt. */ @@ -28,3 +30,23 @@ export function wcagSort( } return 0; } + +/** + * Handles HTTP error responses from Axios requests in local dev; + * re-throws error during builds to fail loudly. + * This should only be used for non-critical requests that can tolerate null data + * without major side effects. + */ +export const wrapAxiosRequest = (promise: Promise>) => + promise.catch((error) => { + if (!(error instanceof AxiosError) || !error.response || !error.request) throw error; + const { response, request } = error; + console.warn( + `AxiosError: status ${response.status} received from ${ + request.protocol + "//" + request.host + }${request.path || ""}` + ); + + if (process.env.ELEVENTY_RUN_MODE === "build") throw error; + else return { data: null }; + }); From 23d8ce8cc708508b16d490947f534bbec96506d4 Mon Sep 17 00:00:00 2001 From: "Kenneth G. Franqueiro" Date: Mon, 9 Dec 2024 11:08:02 -0500 Subject: [PATCH 07/14] Make link to build system readme more prominent in the main readme (#4168) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 401e417ef5..66c59c52de 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,11 @@ Content for WCAG 2.1 and later is organized according to the file structure belo Where `{version}` is "20", content came from WCAG 2.0. "21" is used for content introduced in WCAG 2.1, "22" for WCAG 2.2, etc. +## Build System + +The Techniques and Understanding documents are processed through a build system based on Eleventy and Liquid for templating and Cheerio for transformations. +More details, including instructions for previewing the output locally, can be found in the [build process README](11ty/README.md). + ## Editing Draft Success Criteria [Success Criteria Managers](https://www.w3.org/WAI/GL/wiki/SC_Managers_Phase1) will prepare candidate success criteria, ready for inclusion in the guidelines document. To prepare success criteria, follow these steps: @@ -158,7 +163,7 @@ Once a technique branch and file is set up, populate the content and request rev ### Formatting Techniques -Techniques in the repository are plain HTML files with minimal formatting. For publication to the editors' draft and W3C location, techniques are formatted by a build process based on Eleventy for templating and Cheerio for transformations. More details, including instructions for previewing locally, can be found in the [build process README](11ty/README.md). +Techniques in the repository are plain HTML files with minimal formatting. For publication to the editors' draft and W3C location, techniques are formatted by the Eleventy build process described above in the [Build System section](#build-system). The generator compiles the techniques together as a suite with formatting and navigation. It enforces certain structures, such as ordering top-level sections described above and standardizing headings. It attempts to process cross reference links to make sure the URIs work upon publication. One of the most substantial roles is to populate the Applicability section with references to the guidelines or success criteria to which the technique relates. The information for this comes from the Understanding documents. Proper use of the technique template is important to enable this functionality, and mal-formed techniques may cause the generator to fail. From b9cd498c41b8e4acd2460774f514af02cb46c7e1 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Thu, 12 Dec 2024 12:00:01 +0000 Subject: [PATCH 08/14] 2024 post publication fixes (#4172) --- guidelines/index.html | 26 +++++++++++++------------- guidelines/input-purposes.html | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/guidelines/index.html b/guidelines/index.html index fbfa8a9807..a5a7e668a5 100644 --- a/guidelines/index.html +++ b/guidelines/index.html @@ -792,19 +792,19 @@

Change Log

  • 2022-03-22: Added Focus Not Obscured (Minimum).
  • 2022-05-30: Added Focus Not Obscured (Enhanced).
  • 2023-06-05: Added privacy and security sections within conformance.
  • -
  • 2024-11-15: Republished WCAG 2.2, incorporating the following errata: - -
  • +
  • 2024-12-1w: Republished WCAG 2.2, incorporating the following errata: + +
  • diff --git a/guidelines/input-purposes.html b/guidelines/input-purposes.html index 61fe70a97a..8c6baf14ad 100644 --- a/guidelines/input-purposes.html +++ b/guidelines/input-purposes.html @@ -29,7 +29,7 @@

    Input Purposes for User Interface Components

  • address-level1 - The broadest administrative level in the address, i.e., the province within which the locality is found; for example, in the US, this would be the state; in Switzerland it would be the canton; in the UK, the post town
  • country - Country code
  • country-name - Country name
  • -
  • postal-code - Postal code, post code, ZIP code, CEDEX code (if CEDEX, append "CEDEX", and the dissement, if relevant, to the address-level2 field)
  • +
  • postal-code - Postal code, post code, ZIP code, CEDEX code (if CEDEX, append "CEDEX", and the arrondissement, if relevant, to the address-level2 field)
  • cc-name - Full name as given on the payment instrument
  • cc-given-name - Given name as given on the payment instrument (in some Western cultures, also known as the first name)
  • cc-additional-name - Additional names given on the payment instrument (in some Western cultures, also known as middle names, forenames other than the first name)
  • From 3e937868e8d86f5f125d32a379644d4d7635aa24 Mon Sep 17 00:00:00 2001 From: JAWS-test2 <60307417+JAWS-test2@users.noreply.github.com> Date: Fri, 13 Dec 2024 23:40:44 +0100 Subject: [PATCH 09/14] Update F103 to remove progressbar as it's not an implicit live region (#1021) Fixes #892 Co-authored-by: JAWS-test2 <> Co-authored-by: Kenneth G. Franqueiro Co-authored-by: Patrick H. Lauke Co-authored-by: Mike Gower --- techniques/failures/F103.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/techniques/failures/F103.html b/techniques/failures/F103.html index aabec5461e..4c365aaa64 100644 --- a/techniques/failures/F103.html +++ b/techniques/failures/F103.html @@ -35,10 +35,9 @@

    Description

  • the HTML output element
  • role="status"
  • role="alert"
  • -
  • the use of an aria-live attribute on an element, set to either "polite" or "assertive"
  • role="log"
  • -
  • role="progressbar"
  • - +
  • the use of an aria-live attribute on an element, set to either "polite" or "assertive"
  • + The absence of all of these techniques predicts a failure for the status message be announced to the user. Additionally, if the role or property is not set before the dynamic content is added, this also predicts a failure.

    Since additional techniques may exist to alert an assistive technology, the final step of this failure technique is confirming whether an assistive technology (such as a screen reader) detects the dynamic content and exposes the information to users. Where a status message exists but is not surfaced by assistive technology, it is confirmation that a failure has taken place.

    @@ -73,7 +72,7 @@

    Procedure

  • the existence of errors
  • -
  • Check that the element containing the new content does not have a pre-existing aria role of status, alert, log, or progressbar, or an aria-live attribute
  • +
  • Check that the element containing the new content does not have a pre-existing aria role of status, alert, or log, or an aria-live attribute
  • Check that the status message is not surfaced (i.e., announced) by assistive technology
  • From 6ee72a7770b5d1fc1f565b70ab62382b02341f2b Mon Sep 17 00:00:00 2001 From: Detlev Fischer Date: Fri, 13 Dec 2024 23:41:29 +0100 Subject: [PATCH 10/14] Update H95.html (#2150) Adressing suggestions for updated links in https://github.com/w3c/wcag/issues/2079 Preview of[ amended Technique H95](https://raw.githack.com/w3c/wcag/cd6d94d7be2837be6a025650343acc652d02caf6/techniques/html/H95.html) Closes #2079 --------- Co-authored-by: Patrick H. Lauke Co-authored-by: Kenneth G. Franqueiro Co-authored-by: Mike Gower --- techniques/html/H95.html | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/techniques/html/H95.html b/techniques/html/H95.html index f9218fbac4..f7ebf97040 100644 --- a/techniques/html/H95.html +++ b/techniques/html/H95.html @@ -73,18 +73,27 @@

    Related Techniques

    Resources

    - \ No newline at end of file + From 4ab41bab26a3ce293c7c1df3c9f73c5275a2fc79 Mon Sep 17 00:00:00 2001 From: Detlev Fischer Date: Fri, 13 Dec 2024 23:42:03 +0100 Subject: [PATCH 11/14] Aria22 modification for aria-atomic (#1699) Addressing changes in response to #1137 Adding an explicit `aria-atomic="true"` in Technique [ARIA22: Using role=status to present status messages](https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA22) and the linked examples (search results, shopping cart) since the default behaviour of `role="status"` (reading the entire content of a changed container marked with `role="status"`) is currently not well supported. The change to search results example is actually unnecessary since the entire content is written into the container and thus exposed. So not sure whether it is better to skip that change, or change both examples for consistency's sake. Closes #1137 --------- Co-authored-by: Patrick H. Lauke Co-authored-by: Mike Gower --- techniques/aria/ARIA22.html | 8 ++++---- .../aria-role-status-searchresults/index.html | 2 +- working-examples/aria-role-status-shoppingcart/index.html | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/techniques/aria/ARIA22.html b/techniques/aria/ARIA22.html index 13b5c45310..e820b9b010 100644 --- a/techniques/aria/ARIA22.html +++ b/techniques/aria/ARIA22.html @@ -19,20 +19,20 @@

    When to Use

    Description

    This technique uses the status role from the ARIA specification to notify Assistive Technologies (AT) when content has been updated with information about the user's or application's status. This is done by adding role="status" to the element that contains the status message. The aria live region role of status has an implicit aria-live value of polite, which allows a user to be notified via AT (such as a screen reader) when status messages are added. The role of status also has a default aria-atomic value of true, so that updates to the container marked with a role of status will result in the AT presenting the entire contents of the container to the user, including any author-defined labels (or additional nested elements). Such additional context can be critical where the status message text alone will not provide an equivalent to the visual experience. The content of the aria-live container is automatically read by the AT, without the AT having to focus on the place where the text is displayed. See WAI-ARIA status (role) for more details.

    - +

    Note that since role="status" is currently not treated as atomic by default in some environments, it is advisable to add an explicit aria-atomic="true" if the entire contents of the container should be announced.

    Examples

    Including a search results message

    After a user presses a Search button, the page content is updated to include the results of the search, which are displayed in a section below the Search button. The change to content also includes the message "5 results returned" near the top of this new content. This text is given an appropriate role for a status message. A screen reader will announce "5 results returned".

    -
    <div role="status">5 results returned.</div>
    +
    <div role="status" aria-atomic="true">5 results returned.</div>

    Working example: role=status on search results

    Updating the shopping cart status

    -

    After a user presses an Add to Shopping Cart button, content near the Shopping Cart icon updates to read "1 items". The container for this text (in this case a <p>) is marked with the role of status. Because it adds visual context, the shopping cart image — with succinct and accurate alt text — is also placed in the container. Due to the default aria-atomic value, a screen reader will announce "Shopping cart, six items".

    -
    <p role="status" >
    +				

    After a user presses an Add to Shopping Cart button, content near the Shopping Cart icon updates to read "1 items". The container for this text (in this case a <p>) is marked with the role of status. Because it adds visual context, the shopping cart image — with succinct and accurate alt text — is also placed in the container. Due to the aria-atomic value, a screen reader will announce "Shopping cart, six items".

    +
    <p role="status" aria-atomic="true">
       <img src="shopping-cart.png" alt="Shopping Cart">
       <span id="cart">0</span> items
     </p>
    diff --git a/working-examples/aria-role-status-searchresults/index.html b/working-examples/aria-role-status-searchresults/index.html
    index ed7985ab7c..4b2f5f57fc 100644
    --- a/working-examples/aria-role-status-searchresults/index.html
    +++ b/working-examples/aria-role-status-searchresults/index.html
    @@ -19,7 +19,7 @@ 

    Using role=status to Provide Status Message on Search Results

    Results

    -

    +

    diff --git a/working-examples/aria-role-status-shoppingcart/index.html b/working-examples/aria-role-status-shoppingcart/index.html index a36fe2ac83..1c4cf71f59 100644 --- a/working-examples/aria-role-status-shoppingcart/index.html +++ b/working-examples/aria-role-status-shoppingcart/index.html @@ -17,7 +17,7 @@

    Using role=status to Provide Status Message on Shopping Cart

    This simple script demonstrates how a shopping cart counter is updated and surfaced using the aria status role. Here the role is placed on the paragraph containing the dynamically updated text, and the shopping cart image's alt provides additional context. Due to the default aria-atomic="true", a screenreader should announce "Shopping Cart # items" or (depending on browser compatibility) "# items" each time the Buy Pink Flamingos button is selected.


    -

    Shopping Cart
    +

    Shopping Cart
    0 items

    Shop at our single-product store

    From 784d4058efa37423c0ab54b564c99333cce428c9 Mon Sep 17 00:00:00 2001 From: Francis Storr Date: Fri, 13 Dec 2024 14:42:30 -0800 Subject: [PATCH 12/14] Update ARIA11 to address issue #1308 (#2339) Adds text for ARIA 1.2 form role. Closes https://github.com/w3c/wcag/issues/1308 --------- Co-authored-by: Mike Gower --- techniques/aria/ARIA11.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techniques/aria/ARIA11.html b/techniques/aria/ARIA11.html index 40194469f6..206c2c86d1 100644 --- a/techniques/aria/ARIA11.html +++ b/techniques/aria/ARIA11.html @@ -20,7 +20,7 @@

    Using ARIA landmarks to identify regions of a page

    Landmarks also can help sighted keyboard-only users navigate to sections of a page using a browser plugin.

    -

    Landmarks are inserted into the page using the role attribute on an element that marks the section. The value of the attribute is the name of the landmark. These role values are listed below:

    +

    Landmarks are inserted into the page using the role attribute on an element that marks the section. The value of the attribute is the name of the landmark. These role values are listed below. For HTML mappings of landmark roles, refer to the Rules of ARIA attribute usage by HTML element table in the ARIA In HTML recommendation.

    • banner: A region that contains the prime heading or internal title of a page.
    • navigation: A region that contains navigation links links to other pages or different parts of the same page.
    • From dd048226af3627ca5ad15d319afa90a2ac7bca74 Mon Sep 17 00:00:00 2001 From: "Patrick H. Lauke" Date: Fri, 13 Dec 2024 22:42:57 +0000 Subject: [PATCH 13/14] Tweak the concept of "draw" in 2.5.8 understanding for the spacing checks (#4057) Admittedly, not sure this is absolutely necessary, but hopefully this allays concerns raised in the original issue. Closes https://github.com/w3c/wcag/issues/3895 --------- Co-authored-by: Detlev Fischer Co-authored-by: Mike Gower --- understanding/22/target-size-minimum.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/understanding/22/target-size-minimum.html b/understanding/22/target-size-minimum.html index 70048d3c36..aad303daa5 100644 --- a/understanding/22/target-size-minimum.html +++ b/understanding/22/target-size-minimum.html @@ -40,7 +40,7 @@

      Exceptions

      Size requirement

      -

      For a target to be "at least 24 by 24 CSS pixels", it must be possible to draw a solid 24 by 24 CSS pixel square, aligned to the horizontal and vertical axis such that the square is completely within the target (does not extend outside the target's area).

      +

      For a target to be "at least 24 by 24 CSS pixels", it must be conceptually possible to draw a solid 24 by 24 CSS pixel square, aligned to the horizontal and vertical axis such that the square is completely within the target (does not extend outside the target's area).

      Three square boxes next to each other, each with a height and width of 24px @@ -81,7 +81,7 @@

      Spacing

      When the minimum size for a target is not met, spacing can at least improve the user experience. There is less chance of accidentally activating a neighboring target if a target is not immediately adjacent to another. Touchscreen devices and user agents generally have internal heuristics to identify which link or control is closest to a user's touch interaction - this means that sufficient spacing between targets can work as effectively as a larger target size itself.

      -

      When a target is smaller than 24 by 24 CSS pixels, it is undersized. In this case, we check if it at least has sufficient spacing by drawing a 24 CSS pixel diameter circle over the undersized target, centered on the target's bounding box. For rectangular targets, the bounding box coincides with the target itself – thus, the circle is placed on the center of the target. If the target is not rectangular – for instance, if the target is clipped, has rounded corners, or if it's a more complex clickable SVG shape – we need to first determine the bounding box, and then find the box's center. Note that for concave shapes, the center of the bounding box may be outside of the target itself. Now, we center the circle on the center of the bounding box.

      +

      When a target is smaller than 24 by 24 CSS pixels, it is undersized. In this case, we check if it at least has sufficient spacing by drawing an imaginary 24 CSS pixel diameter circle over the undersized target, centered on the target's bounding box. For rectangular targets, the bounding box coincides with the target itself – thus, the circle is placed on the center of the target. If the target is not rectangular – for instance, if the target is clipped, has rounded corners, or if it's a more complex clickable SVG shape – we need to first determine the bounding box, and then find the box's center. Note that for concave shapes, the center of the bounding box may be outside of the target itself. Now, we center the circle on the center of the bounding box.

      Three undersized targets - a square target, a convex target, and a concave target; the concave and convex targets have a bounding box around them; all three targets have a 24 CSS pixel circle centered on the center of their bounding box @@ -94,7 +94,7 @@

      Spacing

      • In the top row, the dimensions of each target are 24 by 24 CSS pixels, passing this Success Criterion.
      • In the second row, the same targets are only 20 by 20 CSS pixels, but have a 4 CSS pixel space between them – as the target size is below 24 by 24 CSS pixels, these need to be evaluated against the Success Criterion's spacing exception, and they pass.
      • -
      • In the last row, the targets are again 20 by 20 CSS pixels, but have no space between them – these fail the spacing exception. This is because, when drawing the 24 CSS pixel diameter circles over the targets, the circles intersect.
      • +
      • In the last row, the targets are again 20 by 20 CSS pixels, but have no space between them – these fail the spacing exception. This is because the imaginary 24 CSS pixel diameter circles over the targets would intersect.
      @@ -118,14 +118,14 @@

      Spacing

      The following example has one large target (an image that links to a new page related to that image) and a very small second target (a control with a magnifier icon to open a zoomed-in preview, possibly in a modal, of the image).

      -

      In the top row, the small target overlaps - or, to be more technically accurate, clips - the large target. The small target itself has a size of 24 by 24 CSS pixels, so passes. In the second row, we see that if the second target is any smaller – in this case 16 by 16 CSS pixels – it fails the criterion, as the circle with a 24 CSS pixel diameter we draw over the small target will intersect the large target itself.

      +

      In the top row, the small target overlaps - or, to be more technically accurate, clips - the large target. The small target itself has a size of 24 by 24 CSS pixels, so passes. In the second row, we see that if the second target is any smaller – in this case 16 by 16 CSS pixels – it fails the criterion, as the imaginary circle with a 24 CSS pixel diameter we draw over the small target will intersect the large target itself.

      Two rows showing a small target clipping a large target
      The 24 by 24 CSS pixel small target passes, while the 16 by 16 CSS pixel small target fails, since the 24 CSS pixel diameter circle used for undersized targets intersect the large target (image shown to scale - see the scalable original version)
      -

      In the following example, we have the same two targets – a large target and a small target. This time, the small target touches/abuts the large target. If the small target is smaller than 24 by 24 CSS pixels, the circle with a 24 CSS pixel diameter we draw over the small target will intersect the large target itself, failing the requirement. The undersized target must be spaced further away from the large target until its circle doesn't intersect the large target.

      +

      In the following example, we have the same two targets – a large target and a small target. This time, the small target touches/abuts the large target. If the small target is smaller than 24 by 24 CSS pixels, the imaginary circle with a 24 CSS pixel diameter we draw over the small target will intersect the large target itself, failing the requirement. The undersized target must be spaced further away from the large target until its circle doesn't intersect the large target.

      Two rows showing a small target and a large target touching/abutting From 4635e4c98d9ddf0ffcf198f9dc89b61204d33bb7 Mon Sep 17 00:00:00 2001 From: Francis Storr Date: Fri, 13 Dec 2024 14:43:24 -0800 Subject: [PATCH 14/14] update Target Size Minimum to add scrollbar example (#3966) Closes #3963 --------- Co-authored-by: fstorr Co-authored-by: Mike Gower Co-authored-by: gundulaniemann <57541275+gundulaniemann@users.noreply.github.com> Co-authored-by: Patrick H. Lauke --- .../img/target-custom-scrollbar-spacing.svg | 51 +++++++++++++++++++ understanding/22/target-size-minimum.html | 9 ++++ 2 files changed, 60 insertions(+) create mode 100644 understanding/22/img/target-custom-scrollbar-spacing.svg diff --git a/understanding/22/img/target-custom-scrollbar-spacing.svg b/understanding/22/img/target-custom-scrollbar-spacing.svg new file mode 100644 index 0000000000..4d0564f9ef --- /dev/null +++ b/understanding/22/img/target-custom-scrollbar-spacing.svg @@ -0,0 +1,51 @@ + + + Artboard + + + + + + + + + + + + + + + + + + + + + + FAIL + + + + + + + + + + + + + + + + + + + + + + PASS + + + + \ No newline at end of file diff --git a/understanding/22/target-size-minimum.html b/understanding/22/target-size-minimum.html index aad303daa5..c67849c150 100644 --- a/understanding/22/target-size-minimum.html +++ b/understanding/22/target-size-minimum.html @@ -134,6 +134,15 @@

      Spacing

      Users with different disabilities have different needs for control sizes. It can be beneficial to provide an option to increase the active target area without increasing the visible target size. Another option is to provide a mechanism to control the density of layout and thereby change target size or spacing, or both. This can be beneficial for a wide range of users. For example, users with visual field loss may prefer a more condensed layout with smaller sized controls while users with other forms of low vision may prefer large controls.

      + +
      +

      User agent control

      +

      This Success Criterion has an exception for the size of targets determined by a user agent and not modified by the author. An example of this kind of target is a browser's scrollbars. If a scrollbar's dimensions have been modified by the author then there must be a passing amount of spacing between the scrollbar and the content of the page. The following example shows a passing and a failing design.

      +
      + A page's scrollbar has been modified to give it custom track and thumb colors. The track is less than 24px wide and the thumb is narrower. The page has a back-to-top link that is next to the scrollbar. +
      The passing example has enough space between the link and the scrollbar for a 24 CSS pixel diameter circle, placed over the scrollbar, to not overlap the link. The failing example has no space between the link and the scrollbar, which fails the criterion because the 24 CSS pixel diameter circle overlaps the link. (Image shown to scale - see the scalable original version)
      +
      +