lucky.graphics

guides

Accessible SVG Markup: The Right Attributes for Each Use

Accessible SVG markup by delivery method: img, inline decorative or informative, icon buttons, sprites and charts, with title, aria-label and role img rules.

Published
November 13, 2026
Topic
guides
Reading time
19 min
Review
Reviewed against the primary source

Accessible SVG Markup: The Right Attributes for Each Use

The markup an accessible SVG needs depends on how it reaches the page. An SVG loaded with <img> takes an alt attribute like any image. An inline decorative SVG takes aria-hidden="true". An inline informative SVG takes role="img" plus a name from aria-labelledby pointing at its <title>, or from aria-label. An icon inside a button gets its name from the button, not the icon.

Those four rules cover most interfaces. The trouble starts with the cases between them: sprite icons pulled in with <use>, icon-only buttons, charts whose axis labels are real text, and exported files that arrive with an editor's <title>Layer 1</title> already inside. A stray title like that is not harmless. SVG Accessibility API Mappings lists a non-empty title child as one of the conditions that puts an element into the accessibility tree, and the Accessible Name computation treats SVG title as a host-language label, so the icon can be exposed with the name "Layer 1".

The decision table: delivery method to markup

This is the table to keep open while you build or review a page. Each row names the delivery method, the exact attributes, and the reason the choice holds up against the specs listed at the end.

How the SVG is deliveredMarkup to useWhat a screen reader should getWhy this is the right choice
<img src="logo.svg">, informative<img src="logo.svg" alt="Northwind Coffee">An image named "Northwind Coffee"For an img element the name comes from alt. The file's internal <title> is not the attribute HTML and ARIA in HTML define for an img.
<img src="divider.svg">, decorative<img src="divider.svg" alt="">NothingARIA in HTML maps an img with empty alt to none or presentation; the WAI decorative images tutorial says null alt is more widely supported than role="presentation".
Inline <svg>, decorative<svg aria-hidden="true" ...> with no <title>Nothingaria-hidden="true" removes the element and all its children from the accessibility tree (MDN). Leaving a stray title in is what makes an unnamed decoration show up.
Inline <svg>, informative<svg role="img" aria-labelledby="t1"><title id="t1">Sales up 12%</title>...</svg> or <svg role="img" aria-label="Sales up 12%">One image with that namerole="img" makes the descendants presentational, so the graphic is announced once. SVG-AAM calls aria-labelledby the current best practice for fallback support when the name lives in a title child.
Icon inside a <button> or <a><button aria-label="Delete"><svg aria-hidden="true" ...></svg></button>, or visible text beside an aria-hidden iconA button named "Delete"The WAI functional images tutorial says the text alternative should convey the action. The control carries the name; the icon is hidden so it is not announced twice or at all.
Sprite icon via <use href="#trash">Same as the inline rows, applied to the outer <svg> at each place it is used; no <title> inside the <symbol>Depends on the row it falls intoA symbol "must never be rendered directly" (SVG 2). One symbol is reused with different meanings, so the name belongs to each use, not to the shared artwork.
Complex chart or diagram<svg role="img" aria-labelledby="c-t" aria-describedby="c-d">, a short <title>, and a visible summary or HTML data table outside the SVGA short name, then a description, then the data in real HTMLWAI's complex images tutorial requires a two-part alternative. With role="img" every label inside the SVG becomes presentational, so the data has to exist somewhere else.

Two rows deserve a note before the detail. The first row says nothing about a <title> inside logo.svg, and that is on purpose: once you have written alt, the internal title is not the name to rely on, whatever it says. And the sprite row has no markup of its own because a sprite is a way of shipping artwork, not a fourth kind of meaning. You still have to decide whether each icon is decorative, informative or the label of a control.

If you are deciding whether an image is decorative in the first place, that question belongs to the decorative versus informative alt text decision table. The sections below take that decision as made and cover only how to express it in SVG markup.

Why an inline SVG cannot just take alt

An <svg> element has no alt attribute. It is not a replaced element pointing at a file; it is a small document of its own, sitting in the page's DOM, and by default it is exposed that way. ARIA in HTML gives svg the implicit role graphics-document, and the Graphics ARIA module defines that role as "A type of document in which the visual appearance or layout of content conveys meaning." That definition fits a map or an interactive chart. It is a poor fit for a 24 pixel trash can.

ARIA in HTML allows "Any role" on svg, and adds that writing role="graphics-document" explicitly is "NOT RECOMMENDED", since it only repeats the default. In practice that leaves three useful states for an inline SVG:

  1. Hidden, with aria-hidden="true", for decoration.
  2. One image, with role="img" and a name, for anything that means a single thing.
  3. A document of parts, the default or the graphics roles, for a graphic whose pieces a reader needs to explore.

Most graphics on a marketing site or in an app interface belong in the first two. The third is rare, takes much more work to build well, and is covered in the chart section below.

What role="img" actually does

WAI-ARIA 1.2 defines img as "A container for a collection of elements that form an image" and lists it among the roles whose name is required. The part that matters for SVG is the presentational-children rule in section 5.2.9: for roles with this property, "The DOM (Document Object Model) descendants are presentational." MDN describes the result in plainer words: browsers apply presentation to every descendant of an element with role="img", and most screen readers treat that element "like a black box".

That black box is the point. A logo built from forty paths and a <text> element for the wordmark should be announced once as "Northwind Coffee, image", not as a group followed by fragments of text. It is also the trap for charts: every <text> label inside a role="img" SVG is presentational, so a reader hears the name and nothing of the axis values. Keep that trade in mind when you reach the complex chart row.

img src="file.svg": treat it as an image

When an SVG arrives through <img>, the page sees an image, full stop. Its internal structure, its <title>, and its <desc> are inside a separate document that the host page's markup does not reach. Google's image SEO documentation lists SVG among the formats it supports in an img element's src, and for an img element it says "you can add the alt attribute". That is the whole job.

The rules for that attribute are the ordinary image rules: describe the meaning for an informative image, write the action or destination for an image that is the only content of a link or button, and write alt="" for decoration. ARIA in HTML adds a constraint for the empty case. An img with an empty alt is allowed only the roles none and presentation, and the only aria-* attribute permitted is aria-hidden="true". So <img src="divider.svg" alt="" aria-label="divider"> is a contradiction: the empty alt says hide this, the label says announce it.

There is one SVG-specific reason to prefer <img> for some graphics: a file used as an image cannot be restyled or read into by the page, so its accessibility is entirely in the one attribute you can see in the HTML. That makes audits fast. The cost is that you lose CSS control of fills and strokes, a trade the delivery section of the SVG optimization guide weighs alongside file weight.

Should the file still carry a title?

Inside a standalone file, a <title> does no harm and can help when the SVG is opened directly in a browser tab. The hero images on this site carry role="img" and a <title> for that reason. But do not treat it as the accessible name when the file is embedded with <img>, and do not leave an editor's default title ("Artboard 1", "Group 12") in a file that you also inline elsewhere. The same file is a separate document in one context and part of your page's DOM in the other.

Inline decorative SVG: aria-hidden and nothing else

A decorative inline SVG needs one attribute:

<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
  <path d="M9 3h6l1 2h4v2H4V5h4zM6 9h12l-1 12H7z"/>
</svg>

MDN's aria-hidden reference puts it directly: adding the attribute "removes that element and all of its children from the accessibility tree", and the content stays visible unless CSS hides it too. Because the attribute covers every descendant, you do not need to strip or hide inner elements one by one.

Decorative here means the same thing it means for an img: the graphic adds no information that is not already in the text next to it. A star beside the words "Featured" is decorative. A star on its own, standing in for the word "Featured", is not.

Why not role="presentation" on the svg

role="presentation" (or its synonym none) removes the element's own role, but WAI-ARIA defines none narrowly as "An element whose implicit native role semantics will not be mapped to the accessibility API". It does not promise that the content inside disappears. A decorative SVG may still contain <text>, a <title>, or a <desc>, and SVG-AAM's inclusion rules let child elements with those features be exposed in the parent's place. aria-hidden="true" hides the subtree, which is what decoration needs. For an <img>, the WAI decorative tutorial makes a related point about the role: it is "not as widely supported as using a null alt attribute".

The one rule that breaks it

MDN warns: "Do not use aria-hidden="true" on focusable elements," and adds that because the attribute is inherited, it "should not be added onto the parent or ancestor of a focusable element." An SVG with a link inside it, or with tabindex on a shape, is not decoration, so it cannot be hidden this way. If a graphic is both clickable and decorative, the clickable wrapper is the thing that needs a name, which is the button row below.

Inline informative SVG: role="img" with a name

For a graphic that carries meaning on its own (a logo that is not inside a link, a status icon with no text, a small diagram), give the outer element role="img" and a name. There are three ways to supply the name. They are not equivalent.

Name sourceMarkupAccessible Name step that uses itSide effects
aria-labelledby to a <title> child<svg role="img" aria-labelledby="t1"><title id="t1">Order shipped</title>The aria-labelledby step, which comes firstName and tooltip text stay the same string; needs a unique id per instance
aria-label<svg role="img" aria-label="Order shipped">The aria-label step, after aria-labelledbyNo tooltip; the name is not in the SVG file if you copy it elsewhere
<title> child alone<svg role="img"><title>Order shipped</title>The host-language label step, after both ARIA attributesRelies on the user agent mapping the SVG title; browsers usually show it as a tooltip (MDN)
aria-labelledby to visible text outside the SVG<svg role="img" aria-labelledby="cap1"> and <p id="cap1">Order shipped</p>The aria-labelledby stepNo duplicate text; MDN recommends this when visible text exists

The order comes from Accessible Name and Description Computation 1.2. An element's name is taken from the first source that produces one: aria-labelledby, then aria-label, then a host-language label, which the spec's own examples describe as an HTML alt or an SVG title. A tooltip attribute such as HTML's title attribute is used "only if nothing else, including subtree content, has provided results."

So why does the common pattern use both a <title> and an aria-labelledby that points at it? Because the <title> route on its own depends on the host-language step being implemented for SVG, and the ARIA route does not. SVG-AAM says it in its own words: "current best practice for fallback browser support is to use aria-labelledby and aria-describedby" to link to title and desc children. Google's image documentation shows the same pairing in its inline SVG example, with aria-labelledby="svgtitle1" on the <svg> and id="svgtitle1" on the <title>.

aria-label or title: how to choose

Pick aria-label when you do not want a hover tooltip, or when the name is generated in a component and never needs to live in the file. MDN notes that title text "is not rendered as part of the graphic, but browsers usually display it as a tooltip", which some designers do not want on a logo.

Pick <title> plus aria-labelledby when the SVG file is the unit that travels: copied between projects, opened standalone, or edited by people who will not see the HTML around it. The name stays with the artwork.

Pick aria-labelledby to visible text whenever that text exists. A caption under a diagram already names it; pointing at the caption means one string to translate and keep correct, not two.

Placement and ids

MDN asks that <title> be "the first child element of their parent" for compatibility with SVG 1.1. Put it before any shapes.

aria-labelledby takes id references, so every inline copy of the graphic needs its own id. A component library that renders the same icon with a hard-coded id="title" on every page produces several elements with one id, and the reference no longer points at a single, predictable element. Generate the id per instance (a counter, a hash of the label, or your framework's id helper) or use aria-label and avoid ids altogether.

Icon inside a button or link: the control owns the name

This is the most common SVG in any interface and the one most often marked up backwards. The rule from the WAI functional images tutorial is that the text alternative of a functional image "should convey the action that will be initiated." The action belongs to the button or link, so that is where the name goes.

There are three correct patterns.

Visible text beside the icon. The text is the name, and the icon is decoration.

<button type="button">
  <svg aria-hidden="true" viewBox="0 0 24 24" width="20" height="20">...</svg>
  Delete
</button>

Icon only, label on the control. The button gets aria-label; the icon is still hidden.

<button type="button" aria-label="Delete">
  <svg aria-hidden="true" viewBox="0 0 24 24" width="20" height="20">...</svg>
</button>

Icon only, hidden text in the control. A visually hidden span carries the name, so the label is ordinary text in the page.

<button type="button">
  <svg aria-hidden="true" viewBox="0 0 24 24" width="20" height="20">...</svg>
  <span class="visually-hidden">Delete</span>
</button>

All three work through the name computation's ordinary path. A button that has no aria-labelledby or aria-label takes its name from its content, and content hidden with aria-hidden is skipped. MDN's own aria-hidden example is a button with a hidden icon and a visible "Tweet" label, and it explains that this "hides the icon character from being included in the accessible name."

What breaks it:

  • aria-hidden on the button itself. That hides a focusable element, which MDN warns against directly. The button is still reachable with the Tab key and announced with no name.
  • A hidden icon as the only content, with no label. The button's content is now empty, so it has no name. This is the failure the alt text decision table flags for hidden SVG icons that are a control's only label.
  • Naming the picture instead of the action. aria-label="Trash can" describes the drawing. aria-label="Delete" or aria-label="Remove Blue Mug from cart" tells the reader what happens.
  • Both a name on the button and a name on the icon. <button aria-label="Delete"><svg role="img" aria-label="Delete"> is not needed: the button's aria-label comes earlier in the name computation than its content, so the icon's label is never used for the button's name. It is redundant markup that drifts when one label is edited and the other is not.

For a link, the same rules apply with "destination" in place of "action": an icon-only link to a profile page is named "Your profile", not "User icon". The touch area of an icon-only control is a separate requirement covered in the touch target size guide.

SVG sprites with use: name at the point of use

A sprite stores each icon once as a <symbol> and draws it with <use>:

<!-- once per page, or in /icons.svg -->
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
  <symbol id="i-trash" viewBox="0 0 24 24">
    <path d="M9 3h6l1 2h4v2H4V5h4zM6 9h12l-1 12H7z"/>
  </symbol>
</svg>

<!-- wherever the icon appears -->
<button type="button" aria-label="Delete draft">
  <svg aria-hidden="true" width="20" height="20"><use href="#i-trash"/></svg>
</button>

SVG 2 says symbol elements "must never be rendered directly" and that their "only usage is as something that can be referenced using the 'use' element." Each <use> creates a linked clone, which SVG 2 describes as instances that "remain linked to the referenced source and reflect DOM mutations in the original."

That clone is the reason to keep titles out of symbols. SVG-AAM says the content of a use element's shadow tree "MUST be processed as if it was child content of the use element", so a <title> written inside the symbol travels into every place the icon is drawn. That is fine for an icon that means one thing everywhere. It is wrong for the common case where one trash can means "Delete draft" in one place, "Remove from cart" in another, and nothing at all next to the visible word "Delete". A single title on the symbol cannot be right for all three.

The working pattern:

  1. Symbols hold artwork only: viewBox and shapes, no <title> or <desc>.
  2. The outer <svg> at each use takes the decision: aria-hidden="true" when it is decorative or inside a labelled control, role="img" plus aria-label when it stands alone and means something.
  3. The sprite container is hidden: the hidden container in the example uses display:none, which SVG-AAM lists among the things that keep an element out of the accessibility tree.

The pillar guide's delivery table notes that an external sprite file should be served from your own origin; that applies to the artwork, while the attributes above apply the same way to an inline or external sprite, because they sit on the outer <svg> in your HTML.

Complex charts: a short name plus the data somewhere real

A chart is the case where role="img" helps and hurts at once. It gives the chart a single, clean announcement, and it silences every label inside the SVG. The WAI complex images tutorial sets the requirement: complex images "contain substantial information", and "a two-part text alternative is required": a short description that names the image, and a long description that is "a textual representation of the essential information conveyed by the image."

In SVG, the two parts map like this:

<figure>
  <svg role="img" aria-labelledby="rev-t" aria-describedby="rev-d" viewBox="0 0 640 360">
    <title id="rev-t">Monthly revenue, January to June</title>
    <!-- bars, axes and labels -->
  </svg>
  <figcaption>
    <p id="rev-d">Revenue rose each month, from the lowest value in January to the highest in June.</p>
    <!-- a real HTML table with the values follows -->
  </figcaption>
</figure>

Three details make this hold together.

The description is visible text outside the SVG. aria-describedby points at a paragraph everyone can read, so sighted readers get the summary too and there is one string to maintain. The WAI tutorial notes that text linked this way is read as one continuous paragraph, so aria-describedby suits a prose summary, not a table.

The data lives in HTML. Because the descendants of a role="img" element are presentational, the numbers printed on the bars cannot be reached. A real <table> next to the chart, collapsed in a <details> element if space is tight, is what lets a reader check a single value. The chart colour accessibility checklist covers the visual side of the same chart: contrast, patterns and direct labels.

desc is the in-file alternative. If the summary must live inside the SVG file, put it in <desc> and point aria-describedby at it. SVG-AAM says no accessible object is created for a desc element, and that its text is used through the name and description mapping. In the description computation in Accessible Name 1.2, aria-describedby comes first, then aria-description, then host-language features such as desc that were not already used for the name. Using aria-describedby again follows SVG-AAM's fallback advice.

When to keep the graphics roles instead

A reader exploring a network diagram or a map may need to move between parts, not hear one summary. That is what the default graphics-document role and the Graphics ARIA roles are for: graphics-object for "a distinct object or sub-component with semantic meaning" and graphics-symbol for "a graphical object used to convey a simple meaning or category". The Graphics ARIA note even suggests writing role="graphics-symbol img" so that older user agents fall back to img.

Be realistic about this route. Graphics ARIA 1.0 is a 2018 Recommendation, but SVG-AAM, the document that maps these roles to platform APIs, is a Working Draft dated 21 October 2026 that tells readers "Please do not implement based on this draft." Test a structured chart with the screen readers your audience uses before you rely on it, and keep the HTML table either way.

What the markup costs, measured

A reason people give for stripping accessibility attributes is file size, usually through an optimizer preset that removes titles. To see what is at stake, we wrote the same 24 pixel trash-can icon five ways and counted the bytes of each file in this run (uncompressed, no line breaks). The path data was 49 bytes in every version.

VersionMarkup added to the bare iconBytesAdded
Bare iconnone1380
Decorativearia-hidden="true"15719
Informative, labelrole="img" aria-label="Delete"16931
Informative, titlerole="img" aria-labelledby="del-t" plus <title id="del-t">Delete</title>20567
Title and descriptionthe above plus aria-describedby and a 22 character <desc>276138

The most expensive version adds 138 bytes, all of it text a reader needs. Against the savings the SVG optimization guide's worked example finds in editor bloat (metadata, comments, excess precision), the accessible name is not where the weight is. Strip the editor's title; keep yours.

Measured here, these numbers are for this one icon. A longer label or description adds its own length, and an icon set with fifty icons inlined on one page pays the attributes fifty times, which is a reason to use a sprite, not a reason to drop the names.

Optimizers and exports: keep the decision in your hands

The SVG that leaves a design tool is not ready for any row of the decision table. Editors write titles from layer names, add ids that collide when two icons share a page, and sometimes add role or aria-* attributes of their own. Optimizers then remove some of that and keep the rest according to their preset.

Treat the accessibility attributes as page markup, not file content:

  • For icons, let the optimizer remove titles and descriptions, then add aria-hidden, role="img" and labels in the component that renders the icon. The component knows the context; the file does not.
  • For standalone graphics (logos, illustrations, diagrams used once), write the title by hand after optimizing, or configure the optimizer to keep it. The pillar guide's safe pass treats this as a deliberate step, and the reasons are the ones above.
  • For anything that will be inlined more than once, check the ids. Prefix them per file or let your build tool do it, so a <title id="t"> in one icon is never the target of another icon's aria-labelledby.

A quick review on an existing page takes a few minutes. Open the browser's accessibility inspector in its developer tools, select each SVG, and check that the name and role match the row of the table it belongs to. Decorative icons should not appear at all. Informative graphics should show one image with a sensible name. Buttons should show their action, not "image" or an empty name.

Ten markup lines, checked against the table

The patterns below are the ones most often seen in handoff files. Each line shows the markup, the row it should fall into, and whether it is right.

Markup foundIntended rowVerdict
<img src="logo.svg" alt="logo">img, informativeWrong: name the brand, not the word "logo"
<img src="wave.svg"> with no altimg, decorativeWrong: add alt="" so the file name is not announced
<svg aria-hidden="true"><title>Star</title>... beside the word "Featured"Inline, decorativeWorks: the title is hidden with the rest, though it is dead weight
<svg role="img"><title>Layer 1</title>... as a standalone badgeInline, informativeWrong: the name is "Layer 1"; write a real title and add aria-labelledby
<svg role="img" aria-label="Verified account">Inline, informativeRight
<button><svg aria-hidden="true">...</svg></button>Icon-only buttonWrong: the button has no name; add aria-label or hidden text
<button aria-hidden="true" aria-label="Close">Icon-only buttonWrong: a focusable element is hidden
<a href="/cart" aria-label="Cart, 2 items"><svg aria-hidden="true">Icon-only linkRight
<symbol id="i-trash"><title>Trash</title> reused in three contextsSpriteRisky: the symbol's title travels into each use; move the name to the outer svg
Chart with role="img" and a title, data only in <text> labelsComplex chartIncomplete: add a visible summary and an HTML table

Questions about accessible SVG markup

Do I need both title and aria-labelledby on an inline SVG?

You need one working name. A <title> with aria-labelledby pointing at it is the pairing SVG-AAM calls the current best practice for fallback support, and it is what Google's image documentation shows. If you do not want the hover tooltip that browsers usually show for a title, aria-label on the <svg> is a valid single source.

What is the difference between the SVG title element and aria-label?

The <title> element is SVG content: it lives in the file, browsers usually show it as a tooltip, and it supplies a name through the host-language step of the name computation. aria-label is an attribute on the element, comes earlier in that computation, and shows no tooltip. When both are present, aria-label wins, and aria-labelledby beats both.

Does role="img" hide the text inside my SVG?

Yes, for assistive technology. WAI-ARIA 1.2 makes the descendants of an img role presentational, and MDN says browsers apply presentation to all of them. Any <text> labels inside are still drawn on screen but are not reachable, so put important values in HTML outside the SVG.

Should a decorative SVG use role="presentation" or aria-hidden?

Use aria-hidden="true". It removes the element and all its children from the accessibility tree, while role="presentation" removes only the element's own role. Never put aria-hidden on an SVG that contains a link or anything focusable.

Is the title inside an SVG file used when I load it with img?

Write the name in the alt attribute and do not rely on the file's title. For an img element, alt is the host-language label the name computation reads, and the SVG file is a separate document from your page.

Does Google read SVG titles for image search?

Google's image SEO documentation supports SVG as an img src and asks for alt text there. For inline <svg> elements it says "you can use the <title> element", and shows it with aria-labelledby. Good accessible markup and Google's guidance point the same way.

How should I label an SVG logo that links to the home page?

The link carries the name: either <a href="/" aria-label="Northwind Coffee home"> with the SVG hidden, or an <img> logo inside the link with alt="Northwind Coffee home". The functional image rule applies, so the name says where the link goes.

Start with the component you ship most

Pick the icon button component your project uses most, render it in its icon-only state, and inspect its accessible name. If it shows an empty name or "image", the button row of the decision table is the fix, and it usually takes one attribute. The broader page-level checks, from contrast to keyboard focus, are in our WCAG compliance guide.

Sources, checked November 13, 2026

  • W3C, Accessible Rich Internet Applications (WAI-ARIA) 1.2, W3C Recommendation 6 June 2023: img role definition and name required, section 5.2.9 presentational children, none and presentation definitions. Checked November 13, 2026.
  • W3C, SVG Accessibility API Mappings, Working Draft 21 October 2026, and the Editor's Draft of 27 July 2026: svg mapped to graphics-document, desc creates no accessible object, inclusion criteria (title or desc child, aria-label, aria-labelledby, tabindex, role), display none exclusion, use shadow tree processed as child content, best practice of aria-labelledby and aria-describedby, "Please do not implement based on this draft". Checked November 13, 2026.
  • W3C, Accessible Name and Description Computation 1.2, Working Draft 4 November 2026: order of aria-labelledby, aria-label, host-language label (HTML alt, SVG title), tooltip last; description precedence. Checked November 13, 2026.
  • W3C, ARIA in HTML, W3C Recommendation 11 August 2026: svg implicit role graphics-document and allowed roles, img with empty alt allowed roles and attributes. Checked November 13, 2026.
  • W3C, WAI-ARIA Graphics Module 1.0, W3C Recommendation 2 October 2018: graphics-document, graphics-object and graphics-symbol definitions, "graphics-symbol img" fallback note. Checked November 13, 2026.
  • W3C, Scalable Vector Graphics (SVG) 2, chapter 5: Document Structure: symbol never rendered directly, use clones linked to the source. Checked November 13, 2026.
  • W3C WAI Images Tutorial: Decorative Images (updated 27 July 2019), Informative Images (updated 17 June 2019), Functional Images (updated 12 April 2017), Complex Images (updated 8 April 2026). Checked November 13, 2026.
  • MDN Web Docs, ARIA: img role, last modified October 14, 2026: black box behaviour, presentational descendants, SVG example with role img and aria-label. Checked November 13, 2026.
  • MDN Web Docs, aria-hidden, last modified October 30, 2025: removal of the subtree, no use on focusable elements or their ancestors, icon in button example. Checked November 13, 2026.
  • MDN Web Docs, SVG title element, last modified June 6, 2025: accessible short-text description, tooltip behaviour, first-child placement, aria-labelledby for visible text. Checked November 13, 2026.
  • Google Search Central, Image SEO best practices, last updated March 2, 2026: SVG among supported img formats, alt for img, title with aria-labelledby for inline svg. Checked November 13, 2026.

The byte counts in the cost table were measured on files written for this page on November 13, 2026. The decision table and the ten-line review are our own synthesis of the sources above.