Building a Good Download… Button?

Avatar of Eric Bailey
Eric Bailey on (Updated on )

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

The semantics inherent in HTML elements tell us what we’re supposed to use them for. Need a heading? You’ll want a heading element. Want a paragraph? Our trusty friend <p> is here, loyal as ever. Want a download? Well, you’re going to want… hmm.

What best describes a download? Is it a triggered action, and therefore should be in the domain of the <button> element? Or is it a destination, and therefore best described using an <a> element?

Buttons Do Things, Links Go Places

There seems to be a lot of confusion over when to use buttons and when to use links. Much like tabs versus spaces or pullover hoodies versus zip-ups, this debate might rage without end.

However, the W3C provides us with an important clue as to who is right: the download attribute.

The What Now?

The internet as we know it couldn’t exist without links. They form the Semantic Web, the terribly wonderful, wonderfully terrible tangled ball of information that enables you to read this article at this very moment.

Like all other elements, anchor links can be modified by HTML’s global attributes. Anchor link elements also possess a number of unique attributes that help control how they connect to other documents and files.

One of those attributes is called download. It tells the browser that the destination of the link should be saved to your device instead of visiting it. You’re still “navigating” to the file, only instead of viewing it, you’re snagging a copy for your own use.

Any kind of file can be a download! This even includes HTML, something the browser would typically display. The presence of the attribute is effectively a human-authored flag that tells the browser to skip trying to render something it has retrieved and just store it instead:

<a download href="recipe.html">
  Download recipe

This raises a very important point: we can’t know every user’s reason for why they’re visiting our website, but we can use the tools made available to us to help guide them along their way. If that means storing an HTML document for use offline, we’re empowered to help make the experience as easy as possible.

Other Evidence

Still not convinced? Here’s some more food for thought:

Progressive Enhancement

JavaScript is more brittle than we care to admit. <a> elements function even if JavaScript breaks. Using anchors for your download means that a person can access what they need, even in suboptimal situations.

A robust solution is always the most desirable—in a time of crisis, it might even save a life. This might sound hyperbolic, but having a stable copy of something that works offline could make all the difference in a time of need.

Semantics and Accessibility

My friend Scott, who is paid to know these kinds of things, tells us:

The debate about whether a button or link should be used to download a file is a bit silly, as the whole purpose of a link has always been to download content. HTML is a file, and like all other files, it needs to be retrieved from a server and downloaded before it can be presented to a user.

The difference between a Photoshop file, HTML, and other understood media files, is that a browser automatically displays the latter two. If one were to link to a Photoshop .psd file, the browser would initiate a document change to render the file, likely be all like, “lol wut?” and then just initiate the OS download prompt.

The confusion seems to come from developers getting super literal with the “links go places, buttons perform actions.” Yes, that is true, but links don’t actually go anywhere. They retrieve information and download it. Buttons perform actions, but they don’t inherently “get” documents. While they can be used to get data, it’s often to change state of a current document, not to retrieve and render a new one. They can get data, in regards to the functionality of forms, but it continues to be within the context of updating a web document, not downloading an individual file.

Long story short, the download attribute is unique to anchor links for a reason. download augments the inherent functionality of the link retrieving data. It side steps the attempt to render the file in the browser and instead says, “You know what? I’m just going to save this for later…”

Thanks, Scott!

Designing a Good Download Link

The default experience of downloading a file can be jarring—it typically isn’t part of our normal browsing behavior. The user has to shift their mental model from flitting from page-to-page and filling out forms to navigating a file system and extracting compressed archives. For less technologically-savvy individuals, it can be a disorienting and frustrating context shift.

As responsible designers and developers, we want to make the experience of interacting with a download link as good as it possibly can be. As we can’t modify how the browser’s download behavior itself operates, we should make the surrounding user experience as transparent and streamlined as possible.

Tell Me What’s in Store

Give the user as much information as you can to help inform them on what’s about to happen. Anticipating and answering the following questions can help:


Verb plus noun is the winning combination. Describe what the link does and what it gets you:

<a download href="downloads/">
  Download Fonts

By itself, the verb Download would only signal what behavior will be triggered when the link is activated. Including the noun Fonts is great for removing ambiguity about what you’ll be getting.

In cases where there’s multiple download links on a page, the presence of the noun will help users navigating via screen reader. Here’s what it would sound like if you were browsing a page that had eight noun-less download links:

Do you know which one of those eight links gets you what you want? No? That’s not great. Similarly, the presence of the download attribute on an <a> element won’t be announced by screen readers, so the verb is equally vital. It’s important to provide context!

Remember that obvious always wins. While it is possible to make your compliance checks happy by using a visually hidden CSS class to hide the noun portion of your download, it places extra cognitive burden on your users. A hidden noun also sacrifices functionality like the browser’s search-on-page capability.

How Long?

KB, MB, GB, TB. We’re not talking about Kobe Beef, Mega Bloks, Ginkgo Biloba, or Tuberculosis. We’re talking about the size of the download, and consequently how long it will take for the download to finish.

Know your audience. A file with a size of 128 KB will download much faster than a file with a size of 2 GB, yet its number is drastically larger. Unless your audience has familiarity with the terminology used to describe file size, they may not understand what they’re getting themselves into if you only tell them the size of the payload.

For larger files, the wait time can be especially problematic. A standard download is an all-or-nothing affair—interruptions can corrupt them and render them useless. Worse, it can waste valuable data on a metered data plan, an unfortunately all-too-relevant concern.

It is also incredibly difficult to accurately ascertain someone’s current connection speed. While the Network Information API looks promising, current browser support isn’t so hot.

There is hidden nuance living in the gap between reported and actual connection. A high speed 5G connection could drop the second someone enters a tunnel or walks to a spot in their house where coverage isn’t good. This isn’t even beginning to cover the complexities involved with throttling, an unfortunately all-too-real concern.

To address these issues, apply a little micro-copy:

See the Pen Download movie by Eric Bailey (@ericwbailey) on CodePen.

Your user is going to know the particulars of their connection quality better than you ever will. Now they have what they need to make an informed decision, with a little intentional ambiguity to temper expectations.

But what about progress bars?

Progress bars are UI elements that show how close a computational task is to completion. For UX designers, they’re a staple (and an opportunity to play around with perceived performance). However, I’m wary of employing them when it comes to downloads.

At best, they’re redundant. Browsers already supply UI to indicate how the download is progressing. At worst, they’re a confusing liability. Adding them introduces unnecessary implementation and maintenance complications—especially when combined with the issues in determining connection speed and quality outlined earlier.


Sell the user on why they should care. Will it remove frustration by fixing an existing problem? Will it increase enjoyment by adding a new feature? Will it reassure by making things more secure? While not every download needs the “why?” question answered, it is good to have for payloads with a complicated or esoteric purpose.

If I am downloading router firmware, I may not understand (or care about) the nitty-gritty of what the update does behind the scenes. However, some high-level communication about why I need to undertake the endeavor will go a long way.

See the Pen Describe what the download does by Eric Bailey (@ericwbailey) on CodePen.

What Next?

Instructions on what to do after the download has completed could be useful. Again, knowing your audience is key.

With our router example, it is entirely possible that less technically-savvy individuals will find themselves on the product support page. It’s also highly possible that they’re in a distressed emotional state when they arrive. After a download has been initiated, step-by-step information on how to install the new firmware, as well as links to relevant support resources could go a long way to alleviating negative feelings.

This is practical empathy. Anticipating the user’s needs and emotional state and preemptively offering solutions has a direct effect on things like reducing expensive support calls. These savings means organizational resources can be reallocated to other important endeavors.

Taking it to Code

Signal That it’s Different

Links use underlines.

A good practice from both a user experience and an accessibility perspective is to create a distinction between internal and external links. This means creating an indicator that a link does something other than take you to another place on your website or webapp. For links that go off-site, a common practice is to use an arrow breaking out of a box. For downloads, a downward-facing arrow is the de facto standard.

Examples of icons for downloads (top) and external links (bottom). Courtesy of Noun Project.

Some may feel that the presence of the download attribute is redundant when applied to links the browser already knows to store. I disagree.

In addition to being an unambiguous semantic marker in the HTML, the download attribute can serve as a simple and elegant styling hook. CSS attribute selectors—code that lets us create styling based on the qualities that help describe HTML elements—allow us to target any link that is a download and style it without having to attach a special class:

a[download] {
  color: hsla(216, 70%, 53%, 1);
  text-decoration: underline;

a[download]::before {
  content: url('../icons/icon-download.svg');
  height: 1em;
  position: relative;
  top: 0.75em;
  right: 0.5em;
  width: 1em;

a[download]:focus {
  text-decoration: none;

Combined with the text describing the download, the presence of the icon clearly communicates that when you activate this link, download behavior will follow. It also provides extra target area, great for touch devices.

Targeting both the presence of the download attribute and the file extension at the end of the string in the href attribute allows us to get even fancier. We can take advantage of the cascade to set up a consistent treatment for all icons, but change the icon itself on a per-filetype basis. This is great for situations where there are multiple kinds of things you can download on a single page:

See the Pen Download icons by Eric Bailey (@ericwbailey) on CodePen.

I maintain a list of common filetypes, if you’re looking for a starting point. Remember to only include the selectors you need, so as to not create unnecessary bloat in your production CSS. If your website or webapp features many icons and/or a lot of fancy state management, consider using a SVG icon system instead. It will improve performance—just remember to make it accessible!

Name the Payload

The download attribute can accept an optional value, allowing the author to create a custom, human-friendly name for the downloaded file. In this example, we’re changing the name of a podcast episode to something that makes sense when downloaded to the user’s device, while maintaining something that makes sense to the podcast’s producer:

  Download Episode 12

For complicated sites, this attribute allows us to create downloads that make sense to the person requesting them, while also taking advantage of features like CDNs and dynamically-generated files. Not a lot of complicated backend sorcery here, just a little template logic:

  download="{{ | slugify }}-{{ 'now' | date: "%Y" }}-tax-return.pdf">
  Download your {{ 'now' | date: "%Y" }} Tax Return

Material Honesty

Keeping content looking and behaving like the HTML elements used to describe it is great for reinforcing external consistency. Externally consistent content is great for ensuring people can, and will use your website or webapp. Use is great for engagement, a metric that makes business-types happy.

And yet, link-y buttons and button-y links are everywhere.

We can lay blame for this semantic drift squarely at the feet of trend. Designers and developers eager to try the latest and greatest invite ambiguity in with outstretched arms. Leadership chases perceived value to stay relevant.

It doesn’t have to be this way. Websites can be both beautiful and accessible. Semantics and current frameworks/aesthetics aren’t mutually exclusive. Take a little time to review the fundamentals—you just might discover something simple that helps everyone get what they need with just a little bit less fuss.