User-downloadable files face a significant UX problem: many have auto-generated, cryptic filenames that are difficult to read, and browsers often open linked files such as PDFs in a new tab, rather than downloading them. This is problematic: if you provide a button that says “Download X”, it’s reasonable to assume that the browser will download it, not open it.

Traditionally, these issues have been solved with complex server-side configuration and JavaScript foolery; today, you can use a little-known called download to address both problems.

Using download with files

download is simply added to a link: the attribute’s value is the new filename of the document for the user, including the extension. For example:

<a href="contract-856EF.pdf" download="Author Publishing Contract.pdf">
    Author Contract
</a>

The same format can be used to link a button:

<a href="contract-856EF.pdf" download="Author Publishing Contract.pdf">
    <button>Download Document</button>
</a>

There are a few limits: download only works on pages delivered from a server: the code won’t work tested in a page on your desktop. Both Chrome and Firefox disable download if the link points to a file on a domain different from the current one (the file can still be viewed and downloaded; it’s just the download feature that is disabled).

Support and Feature Detection

Support for download is excellent: all modern browsers - including the latest version of Microsoft Edge - support it, with the sole exception of Safari. download is a nice example of HTML’s approach to progressive enhancement: if the browser doesn’t support the attribute, it will simply use the linked file’s filename, and view it appropriately. If you want to provide users with a little more guidance, feature detection is fairly straightforward:

var downloadSupported = ("download" in document.createElement("a"));

If downloadSupported is false, we can locate all the links with a download attribute on the current page and modify them with a quick tip. To make the help and button text accurate, I’ll also detect the platform for a customized message:

function replaceWord(el) {
    el.innerHTML = el.innerHTML
                    .replace("Download", "View")
}

    var downloadSupported = ("download" in document.createElement("a"));
if (downloadSupported == false) {
    var downloadLinks = document.querySelectorAll("a[download]"),
    hintText = "",
    ios = /iPad|iPhone|iPod/.test(navigator.platform),
    mac = /MacIntel/.test(navigator.platform),
    win = /Win32/.test(navigator.platform);
    if (ios || mac || win ) {
        if (win) { hintText = "Right-click"; }
        if (mac) { hintText = "Control-click"; }
        for (var i=0; i < downloadLinks.length; i++) {
            replaceWord(downloadLinks[i]);
            if ( mac || win ) {
            downloadLinks[i].insertAdjacentHTML("afterend", "<div class="hint">"+hintText+" to download file</div>");
            }
        }
    }
}

Modernizr also has a download feature detection option, but if that’s the only feature you’re after, it’s better to write the script yourself.

Using download with other media

<canvas> drawings can be saved from the browser, but only with a right / control-click… and the files always have the helpful name of download.png. We can use a link with the download attribute to improve that:

<figure>
    <a href="#" download="starfield.png">
        <canvas id="starfield" width="800" height="400"></canvas>
    </a>
    <figcaption>Click to download image</figcaption>
</figure>

Alternatively, this could be written as a seperate link, with JavaScript added later in the page:

<canvas id="starfield" width="800" height="400"></canvas>
<a href="#" id="canvas-download">Download this image</a>

The JavaScript:

var starfield = document.getElementById("starfield"),
downloadLink = document.getElementById("canvas-download");
…
downloadLink.href = starfield.toDataURL();
downloadLink.download = "starfield.png";

download can also be used with dataURI encoded media, audio and video… essentially, any media the user has access to on your page.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.