Skip
OpenAccess logo, circles representing the letters OA in BrailleOpenAccess

Accessible blockquotes in HTML

An exploration of blockquotes in HTML and CSS. Compare simple vs complex markup methods, with screen reader testing results across VoiceOver, NVDA, JAWS, and TalkBack.


Table of contents

A quest to quell quarrelsome queries on quotes

Quoting other sources is really common in web writing but doing it in a way that’s conformant to the HTML Living Standard and accessible to screen reader users, is surprisingly confusing. There are multiple competing implementations out there, each with different strengths and weaknesses.

I’ve been writing HTML for over a decade and I still have to read half a dozen blog posts, refer to the HTML spec, read tea leaves, and be hallucinated at by an AI or two, just to get it right.

Heydon Pickering’s The Blockquote Element was a great read — in classic Heydon Pickering style, it goes into the policy-wonk details of how the HTML spec mutated evolved over time. I’ve taken inspiration from this work.

The blockquote element

The blockquote element is intended for quoting longer passages of content that are best presented as a distinct block of text, rather than integrated into a paragraph for instance (which is handled by the q element).

The HTML Living Standard is oddly specific about situations in which you can use the blockquote element — it must be used for external quote sources, not quotes from the same source.

The blockquote element represents a section that is quoted from another source.

HTML Living Standard

Do you think users will actually care whether a blockquote is referencing text from another source, or the same source? I don’t think so. This is a frivolous requirement that provides no tangible user benefit, while simultaneously making it harder for authors to write conformant markup. Who is this requirement serving?

It can be argued an aside should be used when quoting the same source (e.g. if it’s a “pull quote”). This sounds reasonable to me, as long as the quote is tangentially related to the content (thus, meeting the semantic definition of aside). However, I think this creates annoying CSS styling consequences — you have to style the aside to look like a quote. Additionally, when quoting the same source, the quote might be integral to the text, rather than tangentially related — leaving no semantic element to use.

For quotes that are tangentially related to the document, from the same source, perhaps you could embed a blockquote inside an aside element — but it might be a bit overkill, and it’s theoretically non-conformant (as the blockquote element can’t be used for quotes from the same source).

The blockquote element may optionally have a cite attribute, which, as far as I can tell, is completely useless. The cite attribute may contain a URL to the source of the quote. The HTML Living Standard gives a mysterious example of how the cite attribute might be used:

User agents may allow users to follow such citation links, but they are primarily intended for private use (e.g., by server-side scripts collecting statistics about a site’s use of quotations), not for readers.

HTML Living Standard

Weird, right? I’ve never seen this usage in the real world.

The cite attribute is never really used by end-users in practice, so I don’t see its value. I think it’d be far more useful to provide an a href link to the source of the quote.

Again, this requirement clutters the HTML spec, doesn’t serve users, and complicates implementation for authors. Arguably it might help AI when attempting to fact-check quotes, but a simple web search is probably better.

You probably had no idea, but I actually added the cite attribute to the blockquote above, and it made exactly zero difference to the world.

The cite element

Now, just to make things even more confusing, the Standard also provides the cite element, which can be used to mark up the source of the blockquote in a way that’s visible, and exposed to screen readers.

Surprise, surprise, the HTML Living Standard has fussy requirements about how to use the cite element. I doubt many souls have had the misfortune of actually reading these requirements, but this is the version of hell I’ve found myself in.

Basically, the cite element can be used to attribute the source of a quote, but it must only contain the title of a work — the Standard explicitly states that it must not contain a person’s name.

The HTML Living Standard at least contains a bit of dry humour about it:

A person’s name is not the title of a work — even if people call that person a piece of work

HTML Living Standard

This requirement makes the cite element more difficult for web authors to use correctly. I think many authors will erroneously use the cite element for people’s names.

HTML is an encoding scheme for the transmission of data between a “metal computer” to “meat computers” (brains). This encoding scheme is designed to function irrespective of the “physical layer” used to transmit data. HTML can be transmitted to the brain via light, sound, touch, and (eventually) direct electrical signal connections — user agents and assistive technologies handle these conversions. When the formal semantics of HTML get so intricate, that most authors fail to implement it correctly, and most end-users don’t understand the meaning behind elements, such intricate semantic rules lack practical value. End users have to trust that authors correctly encode data, and when the rules get complex, such trust is difficult to establish.

One argument for cite usage, is that cite elements are useful for machine interpretation of content. I’m unsure how correct that is, given LLMs can understand attribution text without cite elements.

I think the main practical benefit of the cite element, is it provides a way to apply styles to text. It’s more succinct and readable than using a span class="cite" solution. However, I’m uncomfortable with HTML being used as a styling language — HTML should encode meaning, not style.

However, as an iOS/macOS user, I have a particular dislike of text that’s littered with various inline elements, like cite, and span — VoiceOver notoriously stops reading text when it encounters inline elements, requiring users to continually keep swiping/interacting with the screen reader to keep reading.

I’ve tested the cite element using VoiceOver on macOS and iOS, NVDA/JAWS, and TalkBack on Android — the cite element’s presence is not announced by screen readers.

This is unsurprising, as the HTML Accessibility API Mappings document shows that cite has No corresponding role in WAI-ARIA 1.2, and for the Windows and Linux accessibility APIs, it corresponds to No accessible object. — instead, the cite element is expressed through purely stylistic attributes on the text it contains. However, Apple’s Accessibility API differs — the API Mappings doc states cite should be mapped to a role of AXGroup.

Because I don’t like the complex rules around the cite element’s usage, and its lack of obvious benefit, I won’t be using it.

A better approach: linking to quote sources

Instead of worrying about cite elements, I think it’s far more beneficial to provide a link to the source of the quote. This has a tangible, real impact for users, whereas the cite attributes and elements seem… weirdly performative. Users can follow links using user agent functionality that is universally available.

Some works (e.g. a book) may not have a publicly available webpage that contains the quote source — in this case, you can link to a page where you can access the book.

Implementation method 1: simple blockquote

This implementation is a more basic way to mark up a blockquote in HTML. The specific implementation provided here contains parts that aren’t strictly necessary — I added them for practical styling and usage reasons. For a stock-standard implementation, see <blockquote>: The Block Quotation element — MDN Web Docs.

I’ve made some stylistic choices:

Live example

HTML is weird sometimes.

Joe Bloggs

Simple blockquote HTML markup

<div class="blockquote-wrapper">
  <blockquote>
    <p>HTML is weird sometimes.</p>
  </blockquote>
  <p>
    <a href="https://example.com/">
      Joe Bloggs
    </a>
  </p>
</div>

Simple blockquote CSS (optional)

The CSS below is similar to what I’ve used to style the blockquotes on this site.

I’ve made some stylistic choices:

.blockquote-wrapper {
  border-inline-start: 6px solid rebeccapurple;
  background-color: var(--bg);
}

.blockquote-wrapper blockquote::before {
  /* `/ ""` is like aria-hidden="true"
     but for CSS pseudo-elements */
  content: "“" / "";
  line-height: 0;
  vertical-align: -1.17rem;
}

.blockquote-wrapper > p::before {
  /* Adds em dash before attribution,
     and hyphen-minus for screen readers */
  content: "— " / "- ";
}

Implementation method 1: simple blockquote analysis

VoiceOver (macOS 15.5, Safari) output

Assessment
  • ❌ VoiceOver fails to announce the boundaries of the blockquote
  • ✅ VoiceOver successfully announces the dash, assisting users in understanding that the text is an attribution.

VoiceOver (iOS 18.5) output

Assessment
  • ❌ VoiceOver fails to announce the boundaries of the blockquote
  • ✅ VoiceOver successfully announces the dash, assisting users in understanding that the text is an attribution.

NVDA 2025.1.2 (Firefox) output

Assessment
  • ✅ NVDA correctly announces the start and end of the blockquote, so users clearly know the boundaries of the quoted text.
  • ❌ NVDA doesn’t announce the dash (with default punctuation verbosity). It might be harder for users to understand that the text is an attribution — it must be inferred through context alone.

JAWS 2025.2506.170 (Edge) output

Assessment
  • ✅ JAWS correctly announces the start and end of the blockquote, so users clearly know the boundaries of the quoted text.
  • ✅ JAWS announces the dash, which helps users understand that the text is an attribution.

TalkBack (Android 14, Chrome) output

Note: my Android version is old.

Assessment
  • ❌ TalkBack does not announce the boundaries of the blockquote, so users may not understand where the quote starts and ends.
  • ❌ TalkBack does not announce the dash, so users may not understand that the text is an attribution (with default punctuation verbosity settings).

Implementation method 2: complex blockquote

Another common implementation method I’ve seen, is to wrap the blockquote using a figure element, and to put the quote attribution into the figcaption element.

This does help to programmatically associate the quote with its attribution — something which isn’t achieved by the cite element, or the blockquote on their own.

In this example, I’ve also included a link within the figcaption to demonstrate how you can provide direct access to the quote’s source, which is a helpful way to enable users to verify the quote’s context.

Complex blockquote HTML

<figure aria-label="quote">
  <blockquote>
    <p>HTML is weird sometimes.</p>
  </blockquote>
  <figcaption>
    <a href="https://www.example.com/">
      Joe Bloggs
    </a>
  </figcaption>
</figure>

Complex blockquote CSS

figcaption::before {
  content: "— " / "- ";
}

Implementation method 2: complex blockquote analysis

VoiceOver (macOS 15.5, Safari) output

Assessment
  • ✅ VoiceOver successfully announces the bounds of figure elements, which helps users understand where the quote starts and ends (except, the attribution is mixed in)
  • ✅ VoiceOver announces the aria-label of “quote”, which helps to communicate that the figure contains a quote — however, this approach increases verbosity for other screen readers.
  • ❌ VoiceOver fails to communicate the presence of the blockquote element, which is why I included the aria-label="quote" attribute on the figure, as a fallback. But again, this has drawbacks (verbosity).
  • ✅ VoiceOver announces the dash — great.

VoiceOver (iOS 18.5) output

Assessment
  • ❌ VoiceOver on iOS deviates significantly from macOS here!
  • ❌ VoiceOver fails to announce the figure element’s bounds
  • ❌ VoiceOver fails to announce the aria-label of “quote” on the figure
  • ❌ VoiceOver fails to announce the bounds of the blockquote element
  • ✅ VoiceOver announces the dash on the attribution — good.

NVDA 2025.1.2 (Firefox) output

Assessment
  • ✅ NVDA correctly announces the bounds of the figure
  • ⚠️ NVDA announces the aria-label of “quote” on the figure. However, because NVDA correctly announces the blockquote element, this causes redundant verbosity.
  • ✅ NVDA announces the bounds of the figcaption
  • ❌ NVDA does not announce the dash on the attribution — however, since it correctly announces the bounds of the figcaption, this may not be a big deal.

JAWS 2025.2506.170 (Edge) output

Assessment
  • ✅ JAWS announces figure elements as a “group” — this seems unusual to me, however JAWS isn’t my daily driver — so who am I to judge.
  • ⚠️ JAWS announces the aria-label of “quote” on the figure — but, because JAWS correctly announces the blockquote element, this causes redundant verbosity.
  • ✅ JAWS correctly announces the start and end of the blockquote — marvellous.
  • ✅ JAWS announces the attribution’s dash, noice!
  • ⚠️ Interestingly, JAWS does not announce the start/end of the figcaption element.

TalkBack (Android 14, Chrome) output

Note: my Android version is old.

Assessment
  • ❌ TalkBack does not announce the bounds of the figure element, so users may not understand where the quote starts and ends.
  • ❌ TalkBack does not announce the bounds of the blockquote element, so users may not understand where the quote starts and ends.
  • ❌ TalkBack does not announce the dash on the attribution, so users may not understand that the text is an attribution (with default punctuation verbosity settings).

Why is macOS/iOS so bad?

I inspected this doc: HTML Accessibility API Mappings: blockquote

The HTML Accessibility API Mappings document tells us how HTML elements are mapped to your operating system’s accessibility API. Sometimes, it can explain why HTML elements behave differently across platforms. It’s important to check, because sometimes issues are not the screen reader’s fault, but rather the way the HTML element has been mapped to the accessibility API.

It shows that blockquote elements are mapped to dedicated blockquote-related API roles for Windows and Linux — which explains why Windows-based screen readers were able to announce the start and end of blockquote elements. However, the Apple accessibility API lacks a blockquote-specific role — so the API Mappings doc maps it to the generic AXGroup role. I think a way to improve the macOS/iOS experience would be to provide an AXRoleDescription of “quote” — but that’s not something web authors can control.

Conclusion

So, there are two examples for blockquote implementation.

The ‘basic’ implementation is my favourite. It’s the easiest to code, no figure headaches, and it results in lower amounts of verbosity in screen reader output, but it doesn’t programmatically associate the quote with its attribution — but this might not be a big deal, because the attribution comes right after the quote. macOS/VoiceOver users can be supported by adding minor additional affordances, like the CSS-based stylistic opening quote marks, and the dash that VoiceOver announces — but, these approaches admittedly feel a bit hacky.

There’s a common (and correct) view that authors shouldn’t predetermine the preferred output of screen readers for given web content. This enables users to customise their assistive technology and browser settings to suit their needs. I think this is generally a good principle, but sometimes I like to bend the rules if I identify a specific usability problem for a platform I am dedicated to fully supporting (macOS, and iOS). If I read through my own website in VoiceOver and struggle to understand something, I feel compelled to try and fix it, even if it means implementing a hacky solution. But this should be done with caution, in very limited circumstances, with broad testing across all major assistive technologies and platforms you wish to support, to eliminate unintended consequences.

I think there are problems with VoiceOver’s handling of blockquote elements — it’s difficult to understand where the quote starts and ends. This is more a fault of the HTML Accessibility API Mappings and Apple’s Accessibility API lacking a proper role for blockquote elements.

I get frustrated when I can’t make my content work well on macOS and iOS — as they’re the main platforms I use. There are various hacks you could implement to make blockquote elements announce their start and end, but these techniques probably add verbosity for screen readers that handle the blockquote element well.

The ‘complex’ implementation may be more verbose, especially for users of Braille displays with limited Braille cells. The ‘complex’ implementation seems to provide a slightly more understandable experience on VoiceOver for macOS, as the start and end of the quote are announced.

Screen readers handle em dashes in a wide variety of ways — with default settings, it can be difficult to understand via screen reader speech output whether a piece of text is an attribution, since often the em dash is not announced at all, or in the case of VoiceOver is announced as “comma”. These issues are partially mitigated by using a CSS trick to provide screen readers with a hyphen-minus instead of an em dash — while also making Braille output slightly more efficient.

Screen readers, whether it’s VoiceOver, NVDA, TalkBack, etc — all come pre-loaded with verbosity settings for punctuation that typically cause em dashes to not be announced audibly. If all punctuation is announced, it gets annoying pretty quickly.

These verbosity settings do give users choice over how their content is presented, but changing those settings is like throwing the baby out with the bathwater sometimes — as the settings often aren’t fine-grained enough to allow users to hear contextually important punctuation, where the punctuation actually provides semantic meaning. The meaning and function of the em dash changes — sometimes the em dash is used a bit like a comma, and just results in a non-voiced pause in speech, but other times, the em dash provides a primary affordance that some text is actually a quote attribution.

I’ve encountered this kind of problem with other accessibility settings, like the “reduced motion” setting on iOS. These settings are often an overly-blunt instrument, that don’t allow users to express their actual accessibility preferences. Sometimes, some motion in an app or website really annoys me — but, if I switch on the “reduced motion” setting, it totally nukes all animations from the entire operating system, which makes it harder for me to understand where things have moved to in the interface.

— Callum


Buy me a coffee?

If you like this content and want to support it, consider buying me a coffee. I’ll use the funds to keep writing free accessibility content.

Buy me a coffee on Ko-fi ☕️


Need accessibility help?

If you need support with accessibility audits, team training, or ongoing accessibility consulting, OpenAccess can help.

Get in contact