What I've Learned About Web Accessibility as a Dyslexic, Sighted, Mouse User

Skip to main content - Solaria's Homepage -

Headings are one of the most important HTML elements for improving accessibility, particularly for screen reader users. They are the main structure used to navigate page content based on topic.

Because screen reader users use headings to navigate, they should not be used just to make text look large and bold (if its not a heading). Likewise CSS styling should not be the only thing that indicates a portion of text is a heading, as screen reader users won't know its a heading and won't be able to navigate by using them.

h1 - the page title

The largest and most important heading, h1, should only be used once in the page, as the title of the page.

If your page is small or has only one type of content (ex. a gallery) you may only need to use the h1 heading. However, if your content would benifit from being broken down into smaller sections, you should use smaller headings accordingly.

h2 - the second heading and navigation

h2 is the second most important heading, which is often used to section articles into their major points or topics.

For example, the "Preface," "Table of Contents," "Headings," and "Semantic HTML" headings on this page are h2 headings.

Not only can h2 be used for article headings, but they can also be used to label sections like the following examples:

  • navigation
  • links
  • notices
  • updates
  • comments

Basically, any content that is separated into its own section should have an h2 heading.

h2 headings help screen reader users know right away what is in a section, so they can know if it is something they want to read or not, without having to listen to a whole chunk first.

h3 to h6 subheadings

h2 sections can be split up further into subsections using h3 headings. Likewise, h3 sections can be split into subsections using h4, h4 sections can be split into subsections using h5, and h5 sections can be split into subsections using h6.

Headings should only jump down in importance by 1 step.

The next heading after the h1 heading should be an h2 heading, not an h3, h4, h5, nor h6 heading. The next heading after an h2 heading should be an h3 heading, and so on.

The opposite is not true. You can jump up in importance by any amount. So if you finish the content under an h6 heading, and you're ready to move onto the next major topic in the article, you can use an h2 heading next.

Headings smaller than h6?

There aren't any smaller heading elements than h6, but if you have subsections within your h6 section, you can add two attributes to an element to make it function as an h7 element for screen readers!

<div aria-role="heading" aria-level="7">
  Example of a Seventh Level Heading

This method can be used for as many subsection headings as needed (ex. h8, h9, h10, etc). You will probably want to create a class for these to style, since they do not come pre styled.

Semantic HTML

Semantic HTML refers to HTML elements that indicate what they contain, so basically all HTML elements except span and div!

Some of these elements have preset styling and functions, like button and a, while others just indicate what part of a page something is (header) or what its purpose is (figure). They are very helpful for letting screen readers know what an element is, thus how they can interact with it. You can absolutely use span and div (very useful for CSS styling), but try to use semantic elements where they make sense.

You already use semantic elements like p and img (p holds a paragraph, and img holds an image)! But some semantic elements are less known. For a large list of semantic elements, check out the HTML semantics cheat sheet!

Landmark Elements

Landmark elements are among some of the lesser known semantic elements, but they provide important navigational tools for screen reader users, and help filter out unimportant content for reader mode users! These include:

  • main
  • aside
  • header
  • footer
  • nav
  • section

Heres a guide about landmark regions but I will also cover them.

Nav Element

If you have a div containing your page/site navigation links, use a nav instead! This allows screen readers to jump directly to the navigation to find the page they want, or skip navigation they are already familiar with.

Note that not every section containing links should be in a nav element, only links to your own pages or within your page. Links to other peoples websites or articles should not be in a nav element.

Unideal example with div:
<div class="nav">
    <li><a href="home.html">home</a></li>
    <li><a href="about.html">about</a></li>
    <li><a href="blog.html">blog</a></li>
Better example with nav:
<nav class="nav">
    <li><a href="home.html">home</a></li>
    <li><a href="about.html">about</a></li>
    <li><a href="blog.html">blog</a></li>

Both of the above examples would produce the same effect for a sighted user:

But since the second example in green has a nav element instead of a div element, screen reader users know what it is right away. This is extra helpful if a site has the same navigation on all pages, and the user wants to quickly jump to or past the navigation.

Sometimes you may have more than one nav element in a page, usually for a site navigation and a page navigation. To differentiate these you can use an aria-label attribute in the nav element like so:

<nav aria-label="site">

<nav aria-label="page">

You do not need to put the word "navigation" in the aria label, since the screen reader already announces "navigation" for the nav element.

Note: aria-label should be used sparingly, usually just for multiple nav elements on one page, and interactive form elements. For more information read the article, Aria-Label is Not Always the Answer.

Header and Footer

Headers are the bars at the top of some websites, usually containing the site navigation/menu and the organization's logo. Personal sites don't always have a header, so if you don't have one, you don't need to use the header element.

Likewise, footers are at the bottom of a page and more common on professional sites. They tend to contain copyright information and site links.

Since both headers and footers are usually the same on each page across a single site, screen reader users usually skip them so they dont have to hear the same information over and over. This is easier to do if they are actually in header and footer elements.

Main and Aside (and Reader Mode)

It can be helpful to determine what goes in the main and aside elements by considering reader mode. Reader mode is a browser feature designed to hide distracting content and make articles easier to read by displaying them in plain font with minimal styling. This is helpful for readers with learning or cognitive disabilities, and anyone who wants to read news articles without all the ads and article previews on the side.

So with that in mind, the main element should contain only important content on the page.

This excludes headers, footers, some side bars, comment sections, or anything that isn't the main point of the page.

Like the h1 element, there should be only one main element in a page.

Unimportant content that isn't in a header or footer should be put in an aside element.

This is true whether its actually on the side or not. Reader mode hides aside elements from the reader, so if content is needed to understand the article, don't put an aside element. Read more about aside.

According to Owl in Please Let Me Use Reader Mode, your page should have its main content in an article tag nested in a main tag, have p elements, and have at least a sentance's worth of text in order for your article to show in reader mode. Note that this is true for articles, blogs, guides, or any text heavy pages. Reader mode is less relevant for pages with minimal text.

Unfortunately each browser's reader mode works a bit differently, and if a page does not meet the reader mode's (unpublished) requirements, the reader won't be able to use reader mode on it. Thus, its best to use semantic HTML and make sure your page content is understandable without CSS styling. Its also a good idea in general to style text heavy articles or guides with minimal distractions and easy to read font.


The section element is a rather generic element compared to the other landmark elements. They are typically used to create different sections in an article. Section elements are not for content that can be presented on its own page (use an article for this).

Sections should be labeled with a heading element.

Not only can they be used in articles, but they can also house specific seperate content.

  • widgets
  • comment sections

You would usually use h2 to label these.

I would advise using section elements carefully (rather than for every single heading). Section elements are landmark elements, which describe major parts of a page, and too many section elements would create a cluttered landmark "map". More about the accessibility of the section element.

If you do use section elements to contain your topics, label them by using aria-labelledby. Give the heading an ID, and put that ID into the aria-labelledby attribute. If you can't give a section a heading, you can use the aria-label attribute with the label as text inside the quotes.

<section aria-labelledby="updates">
  <h2 id="updates">Page Updates</h2>
    [updates here]
<section aria-label="side notes">
  [notes here]

Note that using aria-labelledby with a heading is prefered to using aria-label. This is because the aria-labelledby method allows screen reader users to navigate sections by using both landmark elements and headings. Aria-label does not involve headings, thus screen reader users can't navigate these elements by headings.

Example Layouts with Landmark Elements and Headings

Now that we've covered both landmark elements and headings, we can put them together to create a semantic page layout that screen readers can navigate.

(Note: I used fieldset elements as visual grouping in the examples below, no form elements are actually used.)

Site with header and footer:
(h2) Site Menu

[navigation links here]

(h2) Updates

[updates here]

(h2) Cool Sites

[links here]

(h1) My Art
(h2) Illustrations
(h3) Digital
(h4) Pixel Art
(h4) Paintings
(h3) Traditional
(h4) Drawings
(h4) Paintings
(h2) Crafts
(h3) Jewelry
(h3) Sewing
(h4) Stuffed Animals
(h4) Clothes
(h4) Embroidery
(h3) Origami

[copyright here]

Site with title at very top:
(h1) My Art
(h2) Page Contents

[page nav links here]

(h2) Updates

[updates here]

(h2) Cool Sites

[links here]

(h2) Illustrations
(h3) Digital
(h4) Pixel Art
(h4) Paintings
(h3) Traditional
(h4) Drawings
(h4) Paintings
(h2) Crafts
(h3) Jewelry
(h3) Sewing
(h4) Stuffed Animals
(h4) Clothes
(h4) Embroidery
(h3) Origami


The article element is not a landmark element, but like landmark elements, its useful for semantically defining major sections of a page.

The article element describes a section that could be presented independently from the rest of the page.

Most pages usually contain only one article, but they can contain multiple (unlike main and h1 elements). For example, a blog or journal that shows all entries on the same page could have each entry contained in its own article element. Multiple articles on a blog or news page should have a h2 as their title (as the h1 header is reserved for the title of the entire page).

Div and Span

Although it's important to use semantic HTML, that doesn't mean you shouldn't use div and span elements. In fact, trying to use a semantic element like a section in place of a div, may make your page less accessible. A small section of text may not warrant the importance the section or article tag gives it.

It's more important to avoid misuing semantic elements than it is to avoid using divs and spans. Use semantic HTML where it is useful and makes obvious sense, like putting a picture in an img tag, or an article in an article tag. Divs are very appropriate for separating content into blocks with visual styles. Span is good for when you want to outline some text in a paragraph (but not as buttons).


Any element that the user needs to select to preform an action (close, submit, open, etc) should be a button element. Some web designers make a div, span, link, or image and give it an onclick event instead of just using the button element. This is like making an empty div and giving it a background image instead of just using the img element (except its actually worse).

Links can be styled to look like buttons, but the a element should only used if it takes the user to a different location (site, page, or place within a page).

Unideal example with a fake button:
<span onclick="function()">change font</span>
Better example with a real button:
<button onclick="function()">change font</button>

The great thing about buttons is that they already function as they should. They let screen reader users know that its a button, and they let keyboard users activate them by pressing enter or space. Buttons also have built in styling that gives them a border and outline when the keyboard is positioned on them (this outline is important for sighted keyboard users to tell where they are on the screen). A span or div element does not do this with only an onclick function, you would have to add these abilities with role="button" and extra JavaScript.

For related information, visit the article Use semantic HTML for easy keyboard wins.

Making an element function as a button

Temporary quick fix for making fake buttons more accessible.

Ideally, a button element should be used from the get go, but if you have a large groups of divs or spans with onclick events, heres a dirty temporary fix.

The following code is cobbled together by me, someone who is not an accessability nor JavaScript expert.

Making an element keyboard selectable

First make the not-buttons keyboard selectable (with the tab key) using JavaScript.

  var x = document.querySelectorAll('.classexample'); 
  for(var i=0; i<x.length; i++) {
    x[i].setAttribute('tabindex', '0');}

This code goes at the bottom of the body in the HTML document.

The tab index attribute tabindex="0" makes an element focusable using the tab key, but the above JavaScript is useful for giving it to multiple elements of the same class or tag. Put your class name or the element tag in place of .classexample (you can even combine selectors if you want, like 'p.classex'). If it is just one or a few buttons rather than a large section of elements, consider just changing them into real buttons.

Note that tabindex="0" can mess up the order elements are read by some screen readers, which is why this fix is not ideal.

That only allows the user to focus on an element, not actually activate the function if they don't use a mouse. You will need to give your element an onkeypress event that activates the same function as the onclick event.

<span onclick="function()" onkeypress="function()">
  change font

Theres probably a better way to give this function to all not-button elements (this requires you to give it to each one manually), but my JavaScript knowledge is limited.

Focus styling

Next I use CSS to make it so that if the user is on the element (focused), there is a visual indication (useful for sighted users who can't use a mouse).

.classexample:focus {
  border: 2px solid blue;
  outline: 2px solid white;}

A border and outline are standard focus properties given to buttons and links, so I emulated it here.

Button role

Using JavaScript to give elements the button aria role (role="button") lets the screen reader user know that the elements are buttons that can be selected.

  var x = document.querySelectorAll('.classexample'); 
  for(var i=0; i<x.length; i++) {
    x[i].setAttribute('role', 'button');}

Image Descriptions

Image descriptions give pictures a text alternative, useful for screen reader users who would otherwise miss out on the information contained in the picture.

Images that contain relevant text should have the text transcribed exactly. This is particularly true for screenshots, though if you can, consider putting the plain text in a blockquote element with credit, that way everyone can access the same thing.

Text that is not important to the image however, does not need to be transcribed. A photo of a city scene does not need to have every traffic or building sign transcribed.

Alt Text

Brief descriptions go in the alt attribute.

Alt text is basically a quick look at an image. Sighted users don't closely study every image they come across, so do not put a paragraph's worth of text in the alt text, a phrase to two sentances is usually good. Note that not every img element needs a description.

Decorative images should have an empty alt like so: alt="" (no space between the quotations).

This prevents cluttering the listener experience with irrelevant or distracting details. You would do this for fun little gifs on your homepage (though if the page's entire purpose is to collect gifs, give them alt text.) Note that you shouldn't omit the alt attribute entirely, as the screen reader may read the file name (possibly a long string of numbers) and the user will wonder if the image was important or not.

For image links, the alt text should describe the link destination, not the image.

For example, the alt text of a book gif linking to your guestbook should read something like "guestbook," not "book with flipping pages"

Confusing alt for image links
<a href="guestbook.html">
  <img src="book.gif" alt="animated book with flipping pages">
Alt that clarifies where the link goes
<a href="guestbook.html">
  <img src="book.gif" alt="guestbook">

You may already have text next to an icon (like the word "home" next to a house icon). An alt attribute would be redundant, so you should leave the alt empty.

You don't need to put "image of", "picture of", or "graphic of" in the alt text, because the screen reader will announce that the element is an image. However, if the image being a painting, photo, diagram, screenshot, illustration, etc is relevant, include it in the description.

Redundant example:

Image of a cat.

Better examples:

A cat.

Photo of a cat.

Line drawing of a cat.

Alternative Text by WebAIM.

Figure and Figcaption

figure is a semantic HTML element that holds both a caption (figcaption) and the figure, which is usually an image (but it can be other things, like code).

< figure>
  <img src="rainbow.jpg" 
    alt="photo of a rainbow over a forest">
    (imagine a detailed description here)

The figcaption should be either ther first or last element inside the figure element.

Figure captions are usually used to give relevant information, such as title, author, date, and location, but you can put other kinds of information in them.

Figures are particularly useful if you have multiple related images, and want give them a caption as a group.

Aria Described By and Aria Details

Most images only need a short description, but you may want longer descriptions for artwork and complex diagrams.

You can write a description in a paragraph and use the aria-describedby attribute to "link" the description to its image. This is particularly useful if you were already going to describe the image in the text. "Linking" it prevents redundancy that would be created if you repeated the description in the alt text.

This is done by giving the description an ID, and putting that ID into the image's aria-describedby attribute.
<img src="rainbow.jpg" 
  alt="photo of a rainbow over a forest">
<p id="rainbowdesc">
  (imagine a detailed description here)

You can name the description anything (as long as no other element has the same ID).

Unfortunately aria-describedby still only reads the text as a single string, making it limited to a paragraph. To preserve more complex formatting, use aria-details, which also uses IDs. Here's a guide on aria-details.

If necessary, you can hide descriptions from sighted users. Theres a few ways to do this with CSS, just don't use display: none; since screen readers can't access elements hidden this way. Hiding the description should not be your default choice though, anyone (not just screen reader users) can benefit from image descriptions.

CSS code for visually hiding elements, by J. Renée Beach.
.visually-hidden {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;

Skip Content Links and Keyboard Navigation

Skip links allow keyboard users to skip past a large group of interactive elements, so they don't have to press the tab key a bunch of times. This is particularly important for people who have limited mobility where pressing keys is difficult or painful (yet less so than using a mouse).

Links, buttons, form elements, and details, are all elements that a keyboard user will have to tab through on a page. Links and buttons will activate if the user presses enter or space.

If you have a bunch of interactive elements in a group (like a list of links,) put a link before them, linking to the ID of the element after the group.

Just make sure that you have described the links or other repetitive content somehow before or in the skip link, so the user can decide if they want to bypass the elements or not.

<h2>Cool Sites</h2>
  <a href="#next"skip past 3 links</a>
    <li><a href="url1">first site</a></li>
    <li><a href="url2">second site</a></li>
    <li><a href="url3">third site</a></li>
<h2 id="next">Next Section</h2>

The above example only has three links, which would not actually warrant a skip link. Putting too many skip links on a page defeats the purpose of skip links (it simply adds more things for users to tab through).

Skip links are commonly used at the very beginning of HTML documents to allow users to skip to the main content. This is not needed if the main content starts right away, but it is recommended if you have a header or navigation containing links. (Just like screen reader users get tired of hearing the same header over and over, keyboard users get tired of tabing past the same header links).

Skip links may also be used to bypass keyboard traps. Keyboard traps are places where the user can't escape using keys alone. This usually occurs with iframes or widgets, for example, calander widgets and cbox. If you can't fix the keyboard trap or find an alternative, you must put a link to bypass it so a keyboard user can navigate your page.

You can leave bypass links out in the open, but sometimes, in order to save space, you will want to hide them until a keyboard user tabs to them. Heres a guide explaining skip links and how to reveal links when they are focused on. Note that its important to make them visible when focused on for sighted keyboard users who need to know where they are tabbed at on a page.

Note that you should not make random elements keyboard focusable in attempt to make your page more keyboard navigatable, since the arrow buttons and space bar already do that.

Tooltips, Title, and Hover

Tooltips are labels, short descriptions, definitions, or other pieces of info that appear when a user hovers over an element.

You might use the title attribute on some of your elements as a tooltip or as a screen reader label/description, however, title="example text" is rarely recommended.

The problem is that title text is only accessible on mouse hover or read by a screen reader, sighted keyboard users cannot access title text with a keyboard alone.

Most useful information for screen reader users is better put in an alt or aria-label attribute. The only exception to this is an iframe element which should have a title attribute labeling it. Read more about the title element.

You may have made your own tooltips without using the title element, but they often have the same problems.

Infact, any hidden content that only appears on hover will need to be made keyboard accessable.

Now, if your hover effect is just making a button or link different colored you don't need to worry about making it keyboard accessible, since browsers automatically give these elements a border and outline to show when they are focused on.

In my research into tooltips, I've found a lot of contradictory, inconclusive, and incomplete advice, so unfortunately theres not a clear solution, other than avoiding using tooltips. If the content inside the tooltip is important, consider leaving it visible all the time.

If a tooltip is necessary you can make the element (that a mouse user hovers over) a button, this allows keyboard users to tab into it, and lets screen readers know that its an interactive element. Your button doesn't need JavaScript, just make sure it has the same styling on :focus as the :hover effects.

The button and tooltip are in a container, which is important for the :hover effect to work.
<div class="tipcontainer">
  <button class="tipactivator">
    example button text
  <p class="tooltip">
    extra text in a tooltip

extra text in a tooltip

Credit to OhScee on CodePen for the button recommendation and code demo.

The tool tip is hidden by default, and the containers position is set to relative.
.tooltip {
  display: none;}
.tipcontainer {
  position: relative;}
The :focus and :hover styling are the same, both displaying the tooltip, which is positioned absolute to the container. Style the tooltip how you want.
.tipcontainer:hover .tooltip,
.tipactivator:focus + .tooltip {
  display: inline-block;
  position: absolute;}

Note that the next sibling selector (+) is what allows the tooltip to be shown when the button (.activator) is focused on.

The following is a quick temporary fix for making a large group of elements focusable using the tab key.

If it is only a few elements use a button. You will also still have to make the :focus properties the same as the :hover properties.

  var x = document.querySelectorAll('.classexample'); 
  for(var i=0; i<x.length; i++) {
    x[i].setAttribute('tabindex', '0');}
This javascript gives elements you want the tabindex="0" attribute, which unfortunately does have some accessability issues, which is why this is not a permanent solution. Replace .classexample with the class or element tag you want to be focusable.

Text Readability

Color Contrast

Make sure that your text is legible against its background. Dark text should have a light background, and light text should have a dark background.

This text has decent contrast.

This text has low contrast, making it harder to read.

Bright red against medium grey.

Even if a color is very different from another (ex. red and grey) the value (light and dark) of the colors must be different enough.

The WCAG has minimum contrast requirements, and you can check your text background contrast using online tools like WebAIM's Contrast Checker.

The WCAG has three levels of accessability, A, AA, and AAA, with AAA being the best. They have a contrast ratio requirement for each level, where black and white (the most contrast) is 21:1, and text with the same color as the background (zero contrast) is 1:1. Your site should meet at least AA which is 4.5:1 for normal text, and 3:1 for large text). I recommend meeting AAA for normal text in guides and educational pages like this one, which is 7:1 (4.5:1 for large text).

This is not a perfect tool, since it does not account for how thin or bold a certain font is, but its a good place to start. Just keep in mind that if your font is thin, you will want its contrast with the background to be higher than the minimum.

Some users encounter eye strain when there is too much contrast, while some users with low vision can't read text without full contrast. There is no perfect solution to this, but I like to give my text enough contrast to pass the WCAG's standards, but not pure black and white. Fortunately reader modes usually give users the option to read in full contrast light mode, full contrast dark mode, and sepia.

Regarding color, make sure that a different color is not the only thing that distinguishes text, as color blind users may not notice the difference. This is particularly important for links, which may not be recognizable as links without an underline or other style (some web designers put an arrow after the link text to indicate its a link). Likewise you should not remove links hover and focus states.

Light and Dark Modes

Some users can only read in one mode, light or dark. Light mode may cause too much eye strain and headaches, where as dark mode may be too blurry for users with astigmatisms. Forced dark or light mode browser extentions exist, but you can also create custom light/dark versions of your pages!

You can create light and dark modes for your page by using only CSS if you don't feel comfortable with JavaScript, but if you want the user to be able to change it with a button you will need JS.

On another page I detail how to make light and dark modes using CSS with or without JS.

Font Style, Size, and Spacing

Other than color, there are many different reasons why a font can be difficult to read.

  • thin letters
  • complicated letter designs - (caligraphy, curly cursive)
  • letters that look too similar - (capital I and lowercase l)
  • letters and words that are too close together - (ol may look like d)

Thin letters, small letters, and close letters can be fixed with CSS. You can make the thin font bold, a small font larger, and you can increase the space between letters and words.

Unfortunately, not much can be done with CSS to fix complicated letters, or letters that look too similar to other letters. These fonts are not as problematic for headings, since headings tend to be large with a few words rather than whole paragraphs. But you will want to consider a font with simple distinct letters for main text, especially if its in an informative page, so your reader can focus on understanding the content, rather than trying to parse the font.

When you define the size of your text in CSS, do so in rem units.

1rem = 16px. Some users may have their browser set to display text larger than default, text defined in pixels will not adjust accordingly, but text defined in rem units will. Likewise you will want to put word spacing, letter spacing, and text padding/margins in rem units, so the text and letters are not cramped if the users browser has a larger font size.

You don't necessarily need to use a different font if you can solve readability issues by using the following CSS properties to make sure there is enough space between letters, words, and lines.

  • letter-spacing
  • word-spacing
  • line-height

Making sure there is enough space between letters prevents them from touching and forming ambiguous shapes that can be confused with other letters (ex. ol may look like d, or lo may look like b). Making sure there is enough space between words allows each word to be distinct, rather than just forming a line of letters. Sufficient line height helps dyslexic users stay on the line they're on rather than skipping lines.

Related to word spacing is justified alignment, where text is spaced out so it sits flush against both the right and left sides of its dimensions. Be careful using it. In order to make text sit flushed on both sides, justified alignment changes the spacing between words on each line, meaning different lines will have different spacing between the words. If there is enough words in a small enough font, this is not too noticable, but when the font size is large, or there arent many words on each line, it becomes difficult to read due to inconsistent and large spaces between words.

Here is some example text in a justified text box.
In this example the first line has massive space between the three words, while theres barely any space between the last three words.

Keep in mind that users may be on mobile, or have increased the font size with their browsers, so even if justified text looks good on a wide screen at default size, it may not always.

Screen Reader Pronunciation


The language of a page should be defined to ensure that screen readers pronounce the words correctly to the user. This is easily done by using adding the language attribute to the HTML tag.

<html lang="en">

Where en is the code for English. Here's a list of language codes.

If you want to include a portion of text in a language different from the HTML document's language, you can add the lang attribute to the element that the different language text is contained in (blockquote, quote, p, span, etc).

<p>I had a moment of <span lang="fr">déjà vu</span> just now!</p>

Note that the French language tag would not actually need to be used in this example, since "déjà vu" is a commonly used phrase in English. This example just demonstrates what using the language attribute would look like.

WebAim has a more indepth guide on defining language for screen readers.

Typing Quirks and Censors

Typing quirks like those featured in Leet speak or the Homestuck webcomic prevent screen readers from speaking in an intelligible way.

Screen readers would pronounce n00b, not as noob, but as something like N zero zero B.

Be careful with text speak, as something like b4 would be read as before like intended, but h8 would be read as H eight rather than hate.

You can put emoticons like >:^) and >:3c in a span element with the aria-hidden="true" attribute to hide them from screen reader users, since they will be read as each character. Though, some basic emoticons like :) and :P may be recognized by a screen reader, and can be kept.

Likewise, if words are censored, I would recommend using something like f-word rather than f*ck or f***, for a clearer and smoother reading flow. If its just profanity and not a slur, consider just writing it out. Fuck.

Similarly, some censors seen on TikTok may not translate well through a screen reader. Thankfully, on personal sites, you can curse and talk about sensitive topics without censoring yourself, because there are no algorithms to ban or shadowban you.

Caps Lock, and All Lowercase

In my experience, the NVDA screen reader is pretty good at reading the individual letters in acronyms even if they are not capitalized. It also reads caps lock text normally rather than letter by letter. For example these two sentances are read the same: I LOVE HTML AND CSS. i love html and css.

However different screen readers function differently, so you may want to capitalize acronyms and avoid all caps on regular text.

Mispellings and Typos

Mispellings and typos are usually easy for sighted users to understand because we can recognize words and phrases even if some letters are mixed up. However, some mispellings may cause the screen reader to pronounce the word in a way that the user is unable to recognize. If you're dyslexic like me, this may be difficult to look out for, but luckily many text editors have spell check, and testing your page with a screen reader can expose mispelled words you may have missed.


In paragraphs where there is more than one sentance or clause, be sure to use commas and periods to give natural pauses, so that the screen reader isn't spitting a relentless long string of text at the user.

Gifs and Animations

Certain animations can be distracting or nausia inducing. In extreme cases they can even induce fatal seizures in people with epilepsy. Fortunately there are ways to reduce these risks without omitting animations entirely.

Gifs, Videos, and Other Animated Files

Risky animations have all three traits:

  • flash more than 3 times in 1 second
  • are large
  • and have high contrast flashes

High contrast flashes are usually flashes of white against dark, flashes of red, or flashes of yellow.

Blinkies seen on Neocities pages are unlikley to cause seizures due to being small, but some larger flashing gifs are more risky.

Note that there are browser extentions like this gif toggling extention that viewers can use. But if you'd like to be extra safe here are some options for your site:

  • a JavaScript alert or entry page for pages with flashing gifs
  • Using CSS to hide gifs from users who have prefers-reduced-motion set in thier browser
  • Using JS to hide/show gifs with a button
  • Using JS to pause/play gifs

I go into more detail for each method in my beginners' accessibility guide.

Pausing/playing gifs is very appealing, but the most difficult solution out of these. If it is only a few gifs, you can manually make a static version of each gif, and use JavaScript to change the source of the image. Of course this gets cumbersome the more gifs you want to pause. I have a guide for freezing gifs with JS.

The Freezeframe library allows users to freeze all of their gifs on a page by using the freezeframe class. This is done by overlaying a canvas element over the original gif, which is not without its flaws. I could not get this to work for my homepage, but you may have success. Bechnokid has a guide on implementing freezeframe with buttons.

Full video files should not autoplay, and neither should audio files. This can be disorienting/distracting, and also make it so that screen reader users can't hear their screen readers.

CSS and JS Animations

I would avoid CSS animations that continually wiggle or pulse, like obnxious ads that try to get your attention. These are very distracting, and frankly irritating to any user. Animations that occur on hover or focus are usually fine. Likewise slowly changing color should also be fine. Animations that move or change the size of elements are the troublesome ones.

Carousels, a rotating selection of photos or article thumbnails, are usually an accessability nightmare. Its best to avoid these, and just let users navigate a gallery of photos or list of articles on their own.

Similarly, marquees or other scrolling content should be used sparingly. Like animations, they can result in nausia, but it can also be frustrating to not be able to read text or buttons at your own pace.

The reduced motion media query can be used to specify styles for users who have their browsers set to reduce motion.
@media (prefers-reduced-motion) {}

In this media query you might make the animation a lot more subtle, or remove it entirely. It can also be paired with the freezeframe JS library to make gifs paused from the start for reduced motion users. However, don't rely on this media query alone, as this browser setting is not as widely known compared to light and dark mode preferences.

Viewers should be able to disable CRT filters (a somewhat common stylistic choice on Neocities to evoke nostaligia). The thin lines featured in CRT filters can make it difficult to read text and can give users headaches, especially if they flicker or have moving lines.

JS Scrolling

I don't know anyone who likes their scrolling to be dictated or changed by JavaScript. Whether it be a "smooth" scrolling animation when you scroll or click an internal page link, or jerky scrolling that does not let you pause where you want to, forcing you at one position or another. The effort of changing the normal scrolling experience is not worth it when it causes most users frustration.

Showing scrolling when a user activates an internal page link, rather than jumping straight to the content, can also make viewers dizzy or nausiated.

Although I want this page to be comprehensive, theres so much more to online accessiblity than I can describe on one page alone, so please check out these sites and articles!

Skip the 30+ links

Websites about web accessibility in general

Articles about accessibility

Final Note

As you go through these guides, you may notice some contradictory advice.

Accessibility Checker recommends adding ARIA attributes to any elements that you feel will give screen readers and users more context.
Whereas the W3C Web Accessibility Initiative states that No ARIA is better than Bad ARIA.

Some people suggest using bold and italics to add emphasis for dyslexic and ADHD users, while some suggest avoiding bold and italics to reduce distractions for dyslexic and ADHD users.

For situations like these you will just have to make your best judgement. Go with the most credible source, or try both out and see which one is most accessible to the methods you are testing (keyboard, screen reader, reader mode, etc).

The accessibility features of browsers can also help with making decisions. I chose to emphasize bold and italics with colored font on this page to be more distinct to dyslexic and ADHD readers, knowing that because this page can be accessed through reader modes, these styles can be stripped for readers who find them distracting or difficult to read.

As a general rule, the best way to know if something is accessible, is to test it out. Use a keyboard only to navigate your page, use your browsers inspect tool to view your page at different screen sizes, increase your browsers default text size, zoom in on your page, use a screen reader to read your page, etc. NVDA is a free screen reader for windows.

It may be impossible to have a fully accessable webpage, due to some people having conflicting needs, especially if you as the creator are disabled yourself, but don't let perfectionism prevent your website from being accessible to more people.

However, at the end of the day, its your personal site, not an essential service, so its up to you to decide how you want to impliment accessiblity.

I just hope that thats this guide inspires you to consider making your public pages more accessible, and gives you someplace to start.

Back to Top - Home