Making Your Zonelets Blog More Accessible
Table of Contents
Zonelets is a free to use, static blogging engine. It's aimed at absolute beginners and especially popular with young people on platforms like Neocities. Unfortunately, the default Zonelets layout lacks a lot of basic accessibility features. Because so many of its users are newbies, they're either unaware of or unable to fix these issues. This post is me throwing my hat in the ring and trying to fix those issues myself.
Before I continue, I want to make it very clear that I have nothing but the upmost respect for Zonelets and it's creator, Marina. All of the issues I'll be pointing out in this post are purely technical. I hope this post can be a nice introduction to web accessibility for beginners, using a framework that they're already familiar with as a jumping-off point.
All of the changes I'm showing can be downloaded from my projects page if you'd prefer to start from scratch. If you had a lot of blog posts before you'd just have to back those up somewhere and then copy-paste the content of your old ones over to the new template. If you'd prefer to update your existing Zonelets files, or just want to know how I did it, keep reading and follow the steps below!
Key Terms
There are some terms I'm going to be using a lot throughout this post. It's important that you're familiar with them before we start.
- Screen Reader
- A screen reader is a type of software frequently used by people who're blind or have low vision. It's main job is to read aloud the text on screen. Most screen readers will also announce when certain elements are interacted with (For example: when a button is pressed), and what section of the page it's currently reading.
Further Reading: "Designing for Screen Reader Compatibility" on WebAIM. - Keyboard User
- A keyboard user is someone who (solely or primarily) uses a keyboard to navigate a web page instead of a mouse, trackpad, or touch screen. This is typically, but not always, because of motor disabilities. There is also a significant overlap between keyboard users and screen reader users, since people who're totally blind can't see/use a mouse cursor.
Further Reading: "Keyboard Accessibility" on WebAIM. - Semantic HTML
- When an HTML element or HTML structure is semantic that means it's being used to convey information, not just decoration. For example, using headings to give a title to a section of a page, not just using it because you want large text.
Further Reading: "Semantics" on MDN Web Docs. - Styling
- Styling refers to changing the appearance, but not the content or functionality, of an HTML element using CSS. For example: changing the font, size, or color of text on a page.
Further Reading: "CSS styling basics" on MDN Web Docs.
Step 1: Defining the language
Why?
Screen readers have the ability to read text aloud in multiple languages. Sometimes there can be ambiguity as to what language a block of text is supposed to be in, and that goes on to effect how the screen reader pronounces it and how the user interprets its meaning. For example, without context, most screen readers can't tell the difference between "pan", the English word for a skillet, and "pan" the Spanish word for bread. Defining what language the page is using can help with these problems.
What You Should Do
Change the very first <html> at the top of all your HTML files to <html lang="en">.
If your blog isn't in English, you can search through this list to find your languages two letter code. Just replace en with whatever your languages code is.
Country Codes
In some cases, you might want to add a country code to the end of your language code. This is usually unnecessary for English, since most dialects of English are mutually intelligible (someone who speaks American English can understand British English and vice versa), but may be necessary for other languages. For example, there's pt-PT for Portuguese Portuguese and pt-BR for Brazilian Portuguese.
Defining Multiple Languages
The lang tag is a global attribute, which means it can be applied to any HTML element. This can be useful in situations where you use words or phrases in other languages.
You can set the overall language of your page to English, but then set individual sections, paragraphs, or spans to a different language. For example:
<p>The national anthem of France is <span lang="fr">La Marseillaise</span>.</p>
Step 2: Adding Landmark Regions
Why?
Landmarks help define what kind of content that part of the page has. There are multiple different landmark elements, each with their own purpose, but here are the ones we'll be going over in this tutorial:
- <header>
- The header at the top of your site. Usually includes the sites name, banner, and main links.
- <footer>
- The footer at the bottom of your site. Usually includes legal information, secondary links, and contact info.
- <main>
- The main content of the page. In this case: your blog post.
- <nav>
- Used for navigation menus. Note that unlike the other landmarks mentioned, some sites might have more than one <nav> element.
Both screen reader and keyboard users can use landmarks to jump to different sections of a page. It's also just generally considered best practice to use landmarks when designing web pages, for a bunch of reasons besides accessibility that I won't bother going into here. For now, just know that it's a good thing to get into the habit of doing!
What You Should Do
Replace div with the appropriate landmark element.
Do not change or remove the IDs! It might seem repetitive, but they effect both the styling of your elements and tell the JavaScript where to place certain text.
Header, Footer, and Main Regions
Change <div id="header"> to <header id="header">.
<header id="header">...</header>
Then, change <div id="footer"> to <footer id="footer">.
<footer id="footer"></footer>
Lastly, change <div id="content"> to <main id="content">
<main id="content">
<!--your content here-->
</main>
Pretty easy, right?
Navigation Region
Navigation is where things get a little more complicated. In Zonelet's post template, it has both a main navigation menu in the header, and a "next and previous post" navigation menu towards the end of every post. We could just replace <div> with <nav> and leave it at that, like we did with the other landmark elements, but that might be confusing for some users.
Instead, we're going to make each <nav> unique by using aria-label, a special attribute that is read out loud by a screen reader. aria-label is helpful in situations where surrounding text isn't enough to describe an element. We can give our <nav> in the header the aria-label "main navigation" and the <nav> towards the bottom the aria-label "post navigation". Now, people using screen readers will be able to easily tell the two apart!
Edit 2025-03-15: I feel like I should have done a better job explaining how accidentally using ARIA incorrectly can hinder accessibility instead of enhancing it. When using it for your own projects, please remember to do proper research and testing.
Remember: No ARIA is better than Bad ARIA
Editing the post navigation can be done similarly to our other landmark edits. Change <div id="nextprev"> to <nav id="nextprev"> and make sure to include aria-label="post navigation".
<nav id="nextprev" aria-label="post navigation"></nav>
Unlike the rest of our edits so far, the contents of the header menu is defined in our JavaScript file. Open script.js and look for the variable headerHTML (should be on line 63). It might look intimidating at first, but don't worry! All the stuff we're going to edit is just HTML formatted in a way that's easier for the JavaScript to understand.
You'll see that the header links are wrapped in an unordered list (<ul>). We're going to wrap a <nav> around that and give it aria-label="main navigation". Now, every time our header is loaded, it'll load with those elements as well.
Your JS code will look like this if done correctly:
let headerHTML = '<nav aria-label="main navigation"><ul> <li><a href="' + relativePath + '/index.html">Home</a></li>' +
'<li><a href="' + relativePath + '/archive.html">Archive</a></li>' +
'<li><a href="' + relativePath + '/about.html">About</a></li> </ul></nav>';
Step 3: Fixing Headings
Why?
A mistake that nearly every newbie webdev makes at first is using semantic HTML elements, when they should have just used styling. For example, a lot of beginners use the heading elements because they think that all it does is make the text bigger, and just want large text that grabs the reader's attention. In actuality, headings tell your browser that there's a hierarchy of information. <h2> is a subset of <h1>, <h3> is a subset of <h2>, and so on.
Similarly to landmarks, screen reader and keyboard users can use headings to jump to different sections of a page. Labeling something as a heading when it's actually not can be confusing and annoying to the user.
What You Should Do
Using CSS, we can give a regular paragraph the appearance of a heading, without giving it the semantics of one.
First, we replace our post dates <h4> tags with <p>.
<p id="postDate"></p>
The post date is now just a normal paragraph, but it still has the postDate ID, which we can customize in our stylesheet.
Now is a good time to mention that heading levels should only increase by one! You should never just skip from <h1> to <h4>, like in the original post template.
This next part may be slightly different depending on what theme your using. I'll be using the default Zonelets stylesheet. In your style folder, go to style.css and scroll down to around line 59. You should see a comma separated list of heading elements (<h1>-<h5>). Add #postDate to that list.
h1, h2, h3, h4, h5, #postDate {
font-family: Tahoma, Geneva, sans-serif;
color: #34436f;
}
Now, your post date will be the same font and color as your headings, but there's still a few properties we have to define if we want it to look like it did before.
Most elements have default styles that render even when not defined in the stylesheet. For example, all h4 elements will render with a font-size of 1em, unless explicitly defined otherwise. We can use W3Schools list of default CSS values for HTML elements to find and apply relevant ones from h4 to #postDate.
I also set the line height to "normal". Originally the line height for paragraphs was set to 1.6em, which gave our post date a lot of awkward extra spacing. Giving it the value of "normal" resets that number to the browsers default and makes it look more uniform with the other heading elements.
h1, h2, h3, h4, h5, #postDate {
font-family: Tahoma, Geneva, sans-serif;
color: #34436f;
}
#postDate {
font-size: 1em;
margin: 1.33em 0;
font-weight: bold;
line-height: normal;
}
Congratulations! Now your post date looks just like a heading, without any of the semantics!
Step 4: Small Tweaks
The rest of my edits were super small quick changes that don't need too much explanation.
Using Relative Units
Relative units are more flexible and work better with screen magnifiers and mobile devices. Whenever possible, it's best to use relative units, like em and rem, over absolute units like px. Better yet, you can ditch units all together in some cases! The recommended way to set line-height is to just type a number without defining the unit.
Here I used a pixel to ems converter to help change the font-size unit, and removed the unit from our paragraphs line-hight.
body {
background-color: #436a7b;
background-image: url('../images/bg_diamond.png');
background-position: top;
font-size: 1.125em;
font-family: Georgia, "Times New Roman", serif;
margin: 0;
}
p {
line-height: 1.6;
}
Insuring Decent Color Contrast
Make sure that all of your text, including links, are easily distinguishable from the background. You can use WebAIMs color contrast checker to help you out.
The specifics of how you fix this will depend on the specific theme of your blog. For the default Zonelets theme, the body text was fine, but the link text was too light, so I adjusted it to make it darker.
Adding :focus Effects
Keyboard-only users can't hover over links or buttons with a mouse, instead they have to focus on them by pressing tab. Most stylesheets have it set so that links and buttons change appearance when hovered over. It's usually a good idea to apply whatever effect is set to hovered elements to focused elements as well.
This can be done by simply adding a comma separated list, copy-pasting the element, and replacing :hover with :focus. Now, whatever styles you define will effect both hovered over and focused on states of that element.
a:hover, a:focus {
/* whatever you want it to look like when hovered over/focused on */
}
Adding Skip Links
Skip links rarely ever make or break a sites accessibility, but can still make your site slightly more convenient for some people. Most websites have features that appear on every page, like the header and navigation menu. This can be annoying and repetitive for screen reader users and keyboard users. To remedy this, you can add a "Skip to Content" link.
I was originally going to add my own code that I stitched together for this, but then I found Kalechip's code snippet for it and it's a lot cleaner and better explained than mine, so I'll just recommend that you use that.
Additionally, you can add a visible "back to top" link at the bottom of your blog. This is useful not only for disabled users, but able-bodied users who're reading your blog on their phone or tablet.
Further Reading: "Skip Navigation Links" on WebAIM
Using the Figure and Figcaption Elements
The default Zonelets framework lets you turn regular paragraphs into image captions by giving it the caption class. This doesn't actually change the semantics of the element, though, just the way it looks. This setup isn't inherently inaccessible, but in some situations it might be ambiguous as to which paragraphs are normal parts of a post and which are directly referring to an image.
To make it clear that a caption is grouped with an image or set of images, you can use the figure and figcaption tags. You can still apply the caption class to your figcaption so that it's styled differently from the main text. You can also apply classes meant for images (left, right, center, and small) to figure so that it affects both the image and the caption.
For example:
<figure class="small right">
<img src="dog.png" alt="photograph of a small dog lying in the sun">
<figcaption class="caption">Me and my dog had a fun summer!</figcaption>
</figure>
In Conclusion
For those interested in learning more about web accessibility, I'd highly recommend checking out WebAIM. They provide a lot of in-depth information and I used them as a resource multiple times while writing this post. MDN Web Docs and W3Schools also have very good overviews on the subject.
Once you understand the basics, you can start using tools like WAVE or axe DevTools. Automated accessibility tests aren't foolproof, you should always do them in conjunction with manual testing, but they can still help you notice things that you might have glossed over otherwise. I also recently found out about the A11Y Project Checklist, which I think a lot of people might find useful.
Phew! That took a lot longer to write than I thought it would! I hope this tutorial was easy to understand. Technically, I guess this isn't my first time writing a long tutorial like this, but it is my first time actually finishing and publishing one.
If you have any questions, or think I got something wrong and want to correct me, feel free to contact me!