Accessibility
D3plus is a collection of tools built on top of the low-level helper functions made available by D3 to help aid in the generation of charts. While D3 itself can be considered accessible out of the box, as it doesn’t actively add any elements to a webpage (see this discussion), D3plus tries its best to make sure that the SVG elements that get added to the page include accessibility features automatically. This page outlines those features.
Color Contrast
Section titled “Color Contrast”The @d3plus/color package includes utilities that help ensure text and visual elements remain legible across different color contexts.
colorContrast
Section titled “colorContrast”The colorContrast function determines whether to use a light or dark text color for any given background. It returns whichever of the two text colors has the higher WCAG 2.x contrast ratio against the background, so the more legible option always wins (for example, bright greens and teals correctly receive dark text). This is applied automatically throughout D3plus when rendering text labels on colored shapes.
import { colorContrast } from "@d3plus/color";
colorContrast("#b22200"); // returns light text colorcolorContrast("#f8f9fa"); // returns dark text colorcolorLegible
Section titled “colorLegible”The colorLegible function adjusts a color to ensure it is legible when rendered on a white background. It operates in the HSL color space, capping lightness at 0.45 and reducing saturation when necessary. This is useful for ensuring axis labels, annotations, and legend text meet readability standards.
import { colorLegible } from "@d3plus/color";
colorLegible("#aaddff"); // returns a darkened, legible variantThese utilities support compliance with WCAG 1.4.3 (Contrast Minimum) for text elements within visualizations.
Colorblind-safe default palette
Section titled “Colorblind-safe default palette”D3plus’s default categorical palette is designed — and automatically validated — for colorblind accessibility. Its eight primary slots sit within a controlled OKLCH lightness band, clear a chroma floor, and stay distinguishable under protanopia, deuteranopia, and tritanopia (Machado-2009 simulation), while maintaining WCAG contrast against the chart surface.
colorValidate
Section titled “colorValidate”The colorValidate function checks any palette against those same criteria — OKLCH lightness band, chroma floor, colorblind (protan/deutan/tritan ΔE) separation, and WCAG contrast — so you can verify a custom palette is accessible before shipping it. It also supports an ordinal-ramp mode for sequential scales.
import { colorValidate } from "@d3plus/color";
colorValidate(["#4269d0", "#efb118", "#ff725c"]); // pass / warn / fail reportTexture Patterns
Section titled “Texture Patterns”D3plus supports built-in texture and pattern fills as an alternative to color-only data series differentiation, powered by the textures library. Textures can be applied to any shape via the shapeConfig property, providing a non-color visual channel that helps users who are colorblind or viewing charts in grayscale.
Available Texture Types
Section titled “Available Texture Types”| Type | Description |
|---|---|
lines |
Striped patterns with configurable orientation |
circles |
Circular dot patterns |
crosses |
Cross-shaped patterns |
nylon |
Nylon weave patterns |
waves |
Wave-shaped patterns |
woven |
Woven fabric patterns |
squares |
Square tile patterns |
caps |
Cap-shaped patterns |
hexagons |
Hexagonal tile patterns |
grid |
Shorthand for lines with both vertical and horizontal orientation |
Textures are configured through the texture and textureDefault properties inside shapeConfig:
<BarChart config={{ data, groupBy: "id", shapeConfig: { texture: "nylon", textureDefault: { size: 10, stroke: "rgba(0, 0, 0, 0.1)", strokeWidth: 1 } }}} />Textures can also be set as an object with additional options or as a data-driven accessor function:
// Object with configurationshapeConfig: { texture: { texture: "lines", orientation: "diagonal", stroke: "darkorange", strokeWidth: 2, }}
// Data-driven texture per groupshapeConfig: { texture: (d) => d.id === "alpha" ? "circles" : "nylon"}Localization
Section titled “Localization”All user-facing text in D3plus, including aria-labels and screen reader content, respects the configured locale. The @d3plus/locales package provides translations and number formatting for multiple locales:
UI Translations:
- Arabic (ar-SA)
- Spanish (es-ES)
- Portuguese (pt-BR)
- Chinese (zh-CN)
Number Formatting:
- English (en-US, en-GB)
- Spanish (es-ES, es-MX, es-CL)
- French (fr-FR)
- Arabic (ar-SA)
- Estonian (et-EE)
- Chinese (zh-CN)
This is relevant to WCAG 3.1.1 (Language of Page) and ensures that accessible text is presented in the appropriate language and number format for the target audience. Locales can be set via the locale configuration method on any visualization.
Shape aria-labels
Section titled “Shape aria-labels”All shape DOM elements created by D3plus contain a role attribute with the value “presentation”. They also contain an aria-label which describes the data related to the shape. At a minimum, the value will contain the text label of the data point, but additional information (such as rank and/or value) is provided depending on the visualization.
<rect aria-label="2. United States, 34%." role="presentation" width="300" height="371" x="-150" y="-185.5" fill="#b22200" />D3plus generates contextual aria-labels tailored to each chart type, so screen reader users receive the most relevant information for the visualization they are interacting with:
| Chart Type | Label Format | Example |
|---|---|---|
| Plot (Bar, Line, Area, Stacked Area, Box Whisker, Bump, and the other charts built on Plot) | Label with x/y coordinate values | "Texas, x: 2020, y: 43218." |
| Candlestick | Label and period with open, high, low, and close | "ACME, Jan 2, 2024: Open 101, High 104, Low 99.5, Close 103." |
| Hexbin | A bin’s measure with its x and y ranges, or a contour’s density range | "Count: 42, height 170 – 172, weight 68 – 71" |
| Waterfall | Category, step kind, and change | "Q2, Increase: +120." |
| Pyramid | Group, category, and value | "Male, 20–24: 1.2M." |
| Pie / Donut | Rank, label, and value | "1. Agriculture, 340." |
| Treemap | Rank, label, and sum | "3. California, 128000." |
| Network / Rings | Label with optional size | "Node A, 52." |
| ArcDiagram | Nodes: label with optional size; arcs: source to target, with the link size when sizes vary | "Node A, 52.", "Node A to Node B, 4." |
| Geomap (points) | Label with point size | "Houston, 2300000." |
| Geomap (regions) | Label with color scale value | "Texas, 43218." |
| Tree | Depth level and label | "2. Child Node." |
| Priestley | Label with time range | "Event A, 1820 - 1860." |
| Gantt | Label, dates, and progress (or a milestone’s date) | "Design, Mar 11, 2024 - Mar 22, 2024, Progress 60%." |
SVG title and desc
Section titled “SVG title and desc”The svgTitle and svgDesc methods can be set to include additional information about a chart for screen assistive technologies.
<svg aria-labelledby="title desc" aria-hidden="false">
<title id="title"> Bar Chart of Income Over Time </title>
<desc id="desc"> The income in Texas has been rising steadily over the past 10 years. </desc>
...
</svg>SVG “role”
Section titled “SVG “role””All SVG elements created by D3plus contain a role attribute with the value “img”. This ensures that all visualizations are identified as a graphic.
<svg role="img"> ... </svg>Inline Data Table
Section titled “Inline Data Table”If ariaHidden is set to "false", a visually hidden data table will be rendered inside of the SVG. This makes the data readable by screen assistive technologies, but may overload the DOM in larger websites.
<g role="table"> <text role="row"> <tspan role="columnheader" dy="-1000px">Year</tspan> <tspan role="columnheader" dy="-1000px">State</tspan> <tspan role="columnheader" dy="-1000px">Income</tspan> </text> <text role="row"> <tspan role="cell" dy="-1000px">2010</tspan> <tspan role="cell" dy="-1000px">Texas</tspan> <tspan role="cell" dy="-1000px">43218</tspan> </text> ...</g>Reduced Motion
Section titled “Reduced Motion”Charts honor the viewer’s operating-system “reduce motion” setting. Under the default reducedMotion: "auto", a chart reads the (prefers-reduced-motion: reduce) media query each time it draws; when it matches, the chart skips every animation: entering, updating, and exiting shapes, drill-down morphs, zooming, axis, legend, and timeline changes, and the fades of messages, map tiles, and controls all jump straight to their final state.
Set reducedMotion to true to always draw without motion, or to false to always animate. duration keeps the value you gave it either way, so turning motion back on restores your timing.
new BarChart() .data(data) .groupBy("id") .duration(800) .reducedMotion("auto") // default: follow the OS setting .render();The preference is read when the chart draws, so a change to the OS setting applies at the chart’s next render. Server-side rendering counts as not reduced.
Keyboard Navigation
Section titled “Keyboard Navigation”Every chart is one Tab stop, so keyboard users can reach its data without a mouse. Once a chart has focus, these keys move between its data marks:
| Key | Action |
|---|---|
| Tab / Shift+Tab | Moves focus into the chart (onto its first mark) and on out of it. Focus is never trapped. |
| ← → ↑ ↓ | Moves to the nearest mark in that direction. Line and area series are visited point by point, and the legend’s items come after the chart’s marks. |
| Home / End | Jumps to the first or last mark, reading left to right and then top to bottom. |
| Enter / Space | Selects the focused mark, as a click would: it runs click handlers, drills down into nested data, and toggles a legend item (Shift+Enter acts as a shift-click). |
| Escape | Clears the focused mark and its tooltip, leaving focus on the chart. |
The focused mark behaves as if the pointer were over it: its tooltip opens, the other marks dim, and a ring outlines it. The chart’s focusable element has role="application", so screen readers pass the arrow keys through to it, and an aria-roledescription of “interactive chart”. It is named by svgTitle (or the chart’s title), described by short instructions, and holds a polite live region that announces each focused mark’s aria-label (see Shape aria-labels). Every label is translated with the chart’s locale.
Keyboard navigation is on by default. keyboardNavConfig styles the focus ring, which defaults to a 2px ring in the color that contrasts with the chart’s background, over a halo of the background color so it stands out against any mark. keyboardNav(false) removes the Tab stop entirely.
new BarChart() .config({ data, groupBy: "id", keyboardNavConfig: {stroke: "#005fcc", strokeWidth: 3, padding: 4}, }) .render();
// No Tab stop, focus ring, or live region.new BarChart().config({data, groupBy: "id", keyboardNav: false}).render();WCAG 2.1 AA Conformance
Section titled “WCAG 2.1 AA Conformance”Section 508 of the Rehabilitation Act requires federal agencies to ensure their electronic and information technology is accessible. The current Section 508 standards incorporate WCAG 2.0 Level AA by reference, and federal guidance increasingly aligns with WCAG 2.1 Level AA.
The following table summarizes how D3plus addresses the WCAG success criteria most relevant to data visualizations:
Perceivable
Section titled “Perceivable”| # | Criterion | Status | Notes |
|---|---|---|---|
| 1.1.1 | Non-text Content | Supported | All shapes include aria-label attributes. Optional svgTitle and svgDesc provide chart-level text alternatives. Inline data table available via ariaHidden: false. |
| 1.3.1 | Info and Relationships | Supported | ARIA roles (img, presentation, table, row, cell, columnheader) convey structure programmatically. |
| 1.3.2 | Meaningful Sequence | Supported | DOM order follows a logical sequence: title, description, legend, axes, then data elements. |
| 1.4.1 | Use of Color | Supported | The default palette is colorblind-safe (validated for protan/deutan/tritan separation). Color is the primary differentiator for data series, and built-in texture and pattern fills (lines, circles, crosses, waves, and more) can be applied via shapeConfig as a non-color visual channel. See Texture Patterns below. |
| 1.4.3 | Contrast (Minimum) | Supported | colorContrast automatically selects light or dark text for labels based on background color. colorLegible ensures text colors meet readability thresholds. |
| 1.4.11 | Non-text Contrast | Partial | The default categorical palette is programmatically validated (colorValidate) for colorblind separation and contrast against the chart surface, and colorValidate is exposed for checking custom palettes. Contrast between arbitrary user-supplied colors is still not automatically enforced. |
Operable
Section titled “Operable”| # | Criterion | Status | Notes |
|---|---|---|---|
| 2.1.1 | Keyboard | Supported | keyboardNav (on by default) moves between data marks with the arrow keys, Home, and End, opens their tooltips, and selects them (click handlers, drill-down, legend toggles) with Enter or Space. See Keyboard Navigation. |
| 2.1.2 | No Keyboard Trap | Supported | Visualizations do not trap focus. |
| 2.3.3 | Animation from Interactions | Supported | Charts skip their transitions when the viewer’s OS asks for reduced motion (reducedMotion: "auto", the default), and reducedMotion: true removes them for everyone. See Reduced Motion. |
| 2.4.3 | Focus Order | Supported | Each chart is a single Tab stop in DOM order; inside it, arrow keys move spatially and Home/End follow reading order. |
| 2.4.7 | Focus Visible | Supported | The focused mark gets a ring in the color contrasting with the chart’s background, over a halo of the background color (keyboardNavConfig); the chart itself is outlined while it has focus with no mark selected. |
Understandable
Section titled “Understandable”| # | Criterion | Status | Notes |
|---|---|---|---|
| 3.1.1 | Language of Page | Supported | The locale configuration ensures accessible text is rendered in the appropriate language. |
Robust
Section titled “Robust”| # | Criterion | Status | Notes |
|---|---|---|---|
| 4.1.2 | Name, Role, Value | Supported | All shapes expose name (via aria-label), role (via role attribute), and value information to assistive technology. The keyboard-focusable chart has a role, name, and description, and announces the focused mark through a live region. |
Roadmap
Section titled “Roadmap”D3plus is actively working to improve accessibility. The following enhancements are planned:
- VPAT / Accessibility Conformance Report — Publish a formal ACR using the VPAT 2.5 template to support federal procurement evaluation under Section 508.