A guide to creating accessible PDFs using free tools
Before we look at what free alternatives there are for creating and checking PDFs, you should ask yourself the following question: do I really need to create a PDF, or could I create a website or write an email instead?
If the answer to that is “no” or even “I don’t know”, I recommend reading Inaccessible PDFs? How to know when to use HTML webpages instead of PDFs by Whitney Lewis.
If the answer was “yes”, I’m going to show you how to do the following things using a practical example:
- Creating an accessible PDF using LibreOffice
- Doing a quick structure check with a text editor
- Testing for PDF/UA and WCAG conformance on the axes4 website
- Checking our documents with different screenreaders (JAWS, NVDA and VoiceOver)
Why I’m writing thispermalink
As I write this, I am in the application phase of finding a new role. Every now and then, I am offered the option to have form fields filled in automatically by uploading my resume.
I created my resume in Pages and selected the “On” option under “Advanced Options” and “Accessibility” when exporting. I did this in the hope that it would be accessible and machine-readable from a technical point of view.
After uploading the resume, my first name was always displayed as “Mastodon” and many fields were filled in incorrectly, or not at all. Since “Mastodon” is not my first name, I suspected that there was some kind of technical problem. So, for the nth time, I researched how to create and test accessible PDFs, and for the nth time, I was told that this was only possible with Adobe Acrobat Reader Pro. I didn’t feel like throwing my money at a big corporation, so I frantically continued searching for a way to make my wish come true.
I quickly found an answer after asking on Mastodon, thanks to Grant, who pointed me to the official accessibility documentation and Eric Eggert, who showed me how to test it for PDF/UA and WCAG conformance.
Advert
Using LibreOffice to create and export accessible PDFspermalink
Often ridiculed by me and rarely needed, I wanted to give LibreOffice a real chance this time, so I transferred my resume manually and first got an overview of what the problems actually are.
Requirements for accessible PDFs in LibreOffice
PDFs are subject to very similar accessibility requirements as websites. Let’s take a look at them (taken from the Universal Accessibility (PDF/UA) documentation):
- The document title is set.
This is not the visible main heading, but the title of the document, think metadata.
- The document language is set, or all styles in use have the language property set.
The language for the document is set automatically. However, if there are sections in other languages, these must be adjusted accordingly. Go to “Tools”, “Languages” and select the appropriate option.
- All images, graphics, OLE objects have an alternate (alt) text or a title.
Graphics must either have a meaningful description or be marked as decorative. Got to “Format”, “Alt Text…” and either enter the text or tick the “Decorative” box. Check out What’s the alternative? How to write good alt text if you need help writing alternative text.
- Tables do not contain split or merged cells.
- Only integrated numbering is used, no manual numbering. For example, do not type “1.”, “2.”, “3.” at the beginning of paragraphs.
If numbers are generated, this should happen automatically and they should not be added manually. Example: Multiple lines of text are converted into a semantically correct element using “Ordered List” instead of adding the numbers yourself. Go to “Styles” and select “Numbering 123 List Style”.
- Hyperlink texts without the underlying hyperlinks.
Texts marked as hyperlinks should contain the corresponding path. This warning appears when you create a hyperlink and then remove the path it contains using “Remove Hyperlink,” which you shouldn’t; just leave it be!
- The contrast between text and the background meets the WCAG specification.
See Testing Color Contrast in Non-Web Documents and Images.
- No blinking text.
- No footnotes or endnotes.
- Headings must increase sequentially with no skips, for example, you cannot have Heading 1, Heading 3, and no Heading 2.
- Text does not convey additional meaning with (direct) formatting.
If the font or style for text is changed, this must not be applied to the text itself, but only to the semantic element itself representing this element. Example: All Heading 2 elements should be italic and in Comic Sans. Select the appropriate element either directly in the document or in the right-hand sidebar, go to “Styles” and select “Edit Style…” and change it accordingly.
Some of these points apply to our use case, as we will need headings, paragraphs, lists, hyperlinks, and a decorative image for the resume. If you work in web development and know a little about accessibility, these pain points should be very familiar to you.
Now that we know all the requirements, we can get started!
Displaying accessibility problems and warnings
On the right-hand side, you can click on “Accessibility Check” to display the corresponding warnings and notes. I have also selected “Entire page” under “Zoom” and “Formatting Marks” under “View.” This gives me an overview of the entire page and allows me to see where elements such as paragraphs, line breaks, or lists are located.
Not very pretty, but the good thing is that we only have one problem and a handful of warnings! The problem with the missing page title is quickly solved by clicking on the “Fix…” button and entering the title for the document, “Resume Steve Frenzel”:
Creating a heading structure
Before we look at the warnings for links, I want to start by creating a hierarchy using headings. On the right-hand side, you can either select “Properties” or use the select element at the top left of the toolbar.
To do this, we highlight the relevant text and select, for example, “Heading 1,” “Heading 2,” and so on.
That looks much clearer already. However, there are now two warnings for “Avoid new empty lines between numbered paragraphs.”
Before we look at how to solve this, let’s add the lists.
Adding lists
Lists can be added either via “Format,” “Lists,” and “Unordered List,” or via the toolbar and the button element with the list icon:
Our structure is coming along nicely, but what’s that: more warnings?! Let’s see how we can get rid of those.
Avoiding empty lines between paragraphs
By removing the empty paragraphs between headings, lists, and so on, we can significantly tidy up the “Accessibility Check” section:
The warnings have disappeared, but now the spacing between the “Heading 3” elements is virtually non-existent. “Heading 1” and “Heading 2” are fine for me.
To create a better visual hierarchy, we can go to “Styles” and “Edit styles…” and adjust the spacing under “Spacing” in “Indents & Spacing.”
I chose a value of 0.20 and checked the box next to “Do not add space between paragraphs of the same style” so that these values are applied above and below the element.
Now our document looks less squashed and we can take care of the warning about the links.
Implementing links correctly
There are two warnings, namely “Missing ‘name’ property of hyperlink.” and “Hyperlink text is the same as the link address […]”. Here is our list of links:
- Email:
[email protected]
- Website: https://stevefrenzel.dev/
- LinkedIn: https://linkedin.com/in/stevefrenzel/
- GitHub: https://github.com/stevefrenzel/
- Mastodon: https://mastodon.online/@stvfrnzl/
What we need to do is give the link itself an accessible name and replace the URL with a different word. For example:
To do this, select the relevant word and open the context menu via “Insert” and “Hyperlink” in the toolbar (or CMD + K on macOS). For the email address, select “Mail” and enter the email address under “Recipient:”.
For hyperlinks, we select “Internet” and paste the URL under “Hyperlink settings” and “URL” (it is automatically pasted from the clipboard).
Although the warning about the hyperlink text has disappeared, two of the six links are now too short. It’s “only” a warning, but my goal is to have zero errors or warnings, so we’re going to fix that. “Email” becomes “Send email” and ‘Blog’ becomes “Read blog.”
Nice! All that’s missing now is the accessible name for the links. To do this, we click the corresponding “Fix…” button and enter the appropriate name:
Adding a different font
This resume looks very plain, doesn’t it? I’m not interested in winning a design award, but I would like to make it a little more appealing by using a different font. I’ve chosen “Graphik” for the headings and “Atkinson Hyperlegible Next” for the paragraphs.
Let’s start by applying the style to the main heading:
It looks better (in my opinion), but we got the warning “The text formatting conveys additional meaning.” This warning appears when we apply the new font directly to the text instead of using it globally for all main headings.
A better approach is to change the font under “Styles,” “Edit Style…,” “Font,” and “Family.” Alternatively, you can select the corresponding element, right-click, and access it in the context menu via ‘Paragraph’ and “Edit Style…”.
Adding a decorative image
Perfect, no more accessibility problems or warnings anymore! Now let’s add a visual accent to the document with a visual separator. The toolbar has a button called “Insert line” (visualized by a diagonal line), which we can use to add the decorative image:
Interestingly, we do not receive a warning in the “Accessibility Check” section that this image has no alternative text or that it has not been marked as decorative. However, as we are aware of this issue, we will fix it immediately.
By right-clicking on the image (or selecting “Format” and “Alt Text…”), we can check the “Decorative” box. Done!
Exporting it as accessible PDF
Before exporting, we check whether we have implemented our elements correctly. To do this, we open the side panel under “Tools” and “Navigator,” which shows us semantic elements in the document. Although no paragraphs are displayed, all headings, hyperlinks, and images are shown as expected. Nice, moving on!
Go to “File”, “Export As” and “Export as PDF…” and tick the box labelled “Universal Accessibility (PDF/UA)” to make sure it’s meeting the technical requirements for an accessible PDF:
Testing the PDFpermalink
Let’s start with a very simple test to make sure our document structure is correct. As I’m on MacOS, I’m using the native Preview and TextEdit apps here but you can choose whatever is available to you.
After opening the PDF with Preview, we select all the text via CMD + A and copy it using CMD + C.
Now, we’re going to paste it into an empty TextEdit document with CMD + V.
So, what are we looking for? We’re checking for:
- A logical reading order without mixed up content
- Random text or characters
As both are not the case, we can assume our document is fine. Let’s move on to check if it fulfils the PDF/UA and WCAG requirements on axes4.
Checking PDF/UA and WCAG requirements on axes4
Head over to the axes4 website and either drag and drop your document where it says “Drag and drop your PDF here” or upload it by selecting the “select file” button.
Great, our document meets all requirements! In the “Document” and “Test Report” sections, you will find detailed information about the document and which criteria were checked.
To be really sure that everything is as we intended, we can check our document with a screen reader to see how it interacts with this type of assistive technology.
Testing it with different screen readers
There are many screen reader apps out there and I chose to test with JAWS, NVDA and VoiceOver, as these are the three most popular ones according to the WebAIM Screen Reader User Survey. A great resource on screen reader usage is Your Accessibility Claims Are Wrong, Unless… by Adrian Roselli.
I’m using MacOS Sequoia 15.6 and running Windows 11 on Mac with Parallels. Thanks to this wonderful explainer by Sara Soueidan, I was able to set it up quickly.
Screen reader and browser combinations
Regarding JAWS and NVDA: as I want to keep it as simple as possible, I open the PDF with Microsoft Edge, as it comes pre-installed with Windows 11.
However, some screen readers work better with certain browsers. These are some of the most popular combinations according to the WebAIM Screen Reader User Survey #10, which are also recommended by the IAAP (WAS Body of Knowledge, page 45):
- JAWS with Chrome
- NVDA with Firefox (or Chrome)
- VoiceOver with Safari
JAWS (Version 2025.2508.120) on Windows 11
By pressing H, I’m moving through all the headings in the document, which worked as expected. We can also check the speech output by opening the Speech History via Insert + Spacebar + H.
Next, let’s check the lists by pressing L. It should announce seven lists:
- Five lists with three items
- One list with two
- One list with five items
Sweet, this looks good as well! Lastly, let’s check if the links are working as expected by pressing TAB to traverse through the document:
Looks like we’re good here! As we formatted our “Send email” hyperlink as a link to send an email straight away, JAWS announces “Send Mail Link” after the accessible name.
NVDA (Version 2025.2) on Windows 11
As before, I’m opening the PDF in Microsoft Edge and press H to traverse through the headings. All of them are announced correctly, let’s have a look at them in the Speech Viewer:
Moving on to the lists by pressing L, they are all recognised and announced correctly. However, NVDA also announces the bullet points here. Which is fine, as the most important thing are lists being announced as lists.
When tabbing through the document using TAB, all links are announced as expected. Great, let’s check how this document behaves with VoiceOver.
VoiceOver (Version 10) on MacOS Sequoia 15.6
I am opening the document in Preview and use the so called Rotor feature in VoiceOver to get an overview of elements like headings, links, images and many more. Let’s have a look at our heading structure:
Everything looks as expected, layers and names are correct! Let’s continue with the links:
No surprises here either, wonderful. Let’s take a look at the “Images” section:
Nothing is displayed here because we have marked the image as decorative.
Since the lists are not displayed here in Rotor, I navigated directly through the document using VoiceOver, and the lists were announced to me correctly.
Wrapping uppermalink
Anyone familiar with Microsoft Word or similar word processing programs should have no problem quickly finding their way around LibreOffice. It is also a small step toward digital sovereignty, moving away from the products of US tech giants.
The example with my resume may not be very complex, but it should contain enough examples for everyday use to quickly and easily create an accessible PDF.
Thanks to axes4, we can test our PDFs without ever having to think about the words “Adobe Acrobat Reader Pro”. If you wan’t to make extra sure, you now know how to check the document with different screen readers too.
Enjoyed this article? You can support us by leaving a tip via Open Collective
