Showing File Types in Links
Links to files can be a surprise for users, especially those who cannot use, do not notice, or do not have the status bar to show a link destination. Some users may appreciate knowing a link points to a file, sometimes even a particular file. For links with the download
attribute, it just seems nice to warn them.
Following are some techniques…
Common
I see this little CSS developer convenience touted every now and then:
a[href]::after { content: ""; display: inline-block; height: 1em; width: 1em; margin-left: 0.25em; vertical-align: center; background: center/contain; } a[href$=".pdf"]::after { background-image: url(/img/pdf.png); } a[href$=".doc"]::after { background-image: url(/img/doc.png); } a[href$=".docx"]::after { background-image: url(/img/docx.png); } a[href$=".zip"]::after { background-image: url(/img/zip.png); }
For a quick indication of the type of file in a link, this is handy. It means authors who maybe only use a WYSIWYG never have to think about it; the CSS just does the work for them.
This has some drawbacks, though:
- As a developer, you have to maintain a library of images for all file types you intend to support;
- When the page is scaled (by zooming or scaling the text), the image can look fuzzy or pixelated (unless you use SVGs);
- Every reference to a different file type equals one additional HTTP request;
- Few general users know what the icons mean, particularly if it does not match what they see on their operating system;
- The
margin-left
will need to be made language-aware and text-direction-aware should the page ever be translated into a non-LTR language; - The same applies for aligning the icons to the baseline, in addition the regular challenge of aligning to the baseline;
- Orphaned icons can look out of place;
- Icon images may have poor contrast, be indistinguishable from one another, or just make no visual sense;
- The image will not be announced by screen readers;
- For users on old versions of legacy Edge or Internet Explorer, when using Windows High Contrast Mode, the image will disappear;
Enhanced
An alternative pattern, however, can wipe those issues away:
a[href$=".pdf"]::after { content: " (PDF)"; } a[href$=".doc"]::after { content: " (Microsoft Word)"; } a[href$=".docx"]::after { content: " (Microsoft Word)"; } a[href$=".zip"]::after { content: " (ZIP archive)"; }
Right out of the gate you get:
- No library of icon images to manage;
- No weird fuzziness on zoom;
- No additional HTTP requests;
- No reliance on visual cues that may be unclear for users;
- Localization issues around spacing go away;
- The same is true for aligning to the text axis;
- Users are more accustomed to orphaned text on the web;
- No poor icon design decisions to manage;
- Text that will be announced by screen readers;
- Support for contrast / dark modes;
It still has some drawbacks:
- As a developer, you have to make a CSS rule for each file type you want to support;
- For file types you do not include, users may be surprised when presented with a file;
- It does not tell the user anything else about the file;
- For anal-retentive / automated / uncompromising WCAG testing, this still fails SC 1.3.1 under F87.
Usable
Potentially an even better solution is this:
a[href]::after { /* Yeah, do nothing */ }
And then in your links themselves, do this:
<a href="foo.pdf">Annual Report (PDF, 25MB)</a> <a href="foo.doc">expense report (Microsoft Word, 250KB)</a> <a href="foo.docx">medical leave form (Microsoft Word, 250KB)</a> <a href="foo.zip">Doom installer (ZIP archive, 1.44MB)</a>
It brings you the following benefits:
- No more CSS rule to support, no matter the file type;
- Can handle for any file type;
- Customized messages per link, even among files of the same type;
- More information to let users decide if the link is worth following, respecting their data plans or speed;
- No risk of a genuine failure under SC 1.3.1 for F87 because even if CSS is disabled the content displays.
Sure, it has its drawbacks:
- You or your authors need to make links that help users.
That can be a lot to ask for some folks, I know. That is not me being snarky; it can really be a problem for some authors or organizations, particularly when not technical. Provide training and documentation for those cases. Give them the skills to be successful.
Example
Visit the pen directly if the embed does not load.
See the Pen Showing File Types in Links by Adrian Roselli (@aardrian) on CodePen.
Wrap-up
For some audiences any one of these approaches may be too much. It may not be a good fit for an intranet or for a file repository. None of these are probably a good idea within navigation, and pages full of links to the same file type or even size may not warrant the extra text. Links can get verbose for screen reader users or difficult to use for voice control users.
The point is — test. Test with the users of the site or application where you want to use one of these techniques.
Similarly, you can apply these techniques (ideally the last one) to the target
attribute, specific domains, HTTPs versus HTTP links, and so on.
Update: 14 October 2020
While I recommend against using CSS generated content to embed an icon (for reasons outlined above), in the future it can be less awful than using a background image because it will at least allow for alternative text: Alternative Text for CSS Generated Content
One Comment
Thanks for hashing this out, Adrian. So many points I hadn’t even considered. I especially love the last suggestion (usable), which is what I’ve been doing during my day job for 2 years now, even though it’s not “pretty” or “elegant”. However, it’s been an important step to help our users since we often have lots of downloads available.
Leave a Comment or Response