Skip to main content

Testing

Help us to improve the ONS Design System. Take part in a short study

Upload

A file upload input allows a user to select a file from their computer’s file system.

<div class="field">
  <div class="field">
    <label class="label  label--with-description " for="file">Upload a file
    </label>
    <span id="description-hint" class="label__description  input--with-description">
      File types accepted are XLS and XLSX or PDF
    </span>
    <input type="file" id="file" class="input input--text input-type__input input--upload" accept=".xls,.xlsx,.pdf" aria-describedby="description-hint" />
  </div>
</div>
Nunjucks macro options
Name Type Required Description
id string true The id of the input. This will also be added to the label if a label is specified
label Label (ref) false Settings for the input label. for will automatically be set to match the input id
description string true The hint text for the upload input
accept string false Provides the allowed file types; file_extension, audio/, video/, image/, media_type. Further information on this attribute at w3 schools
size string false Set to ‘small’ to render the small variant
fieldId string false Id for the field
fieldClasses string false Classes for the field
listeners object false Creates a script element that adds an event listener to the element by id. Takes key { event } and value { function }
{% from "components/upload/_macro.njk" import onsUpload %}
{{
    onsUpload({
        "id": "file",
        "accept": ".xls,.xlsx,.pdf",
        "label": {
            "description": "File types accepted are XLS and XLSX or PDF",
            "text": "Upload a file"
        }
    })
}}

{% macro onsUpload(params) %}
    {% from "components/input/_macro.njk" import onsInput %}
    {% from "components/field/_macro.njk" import onsField %}
    {% set field %}
        {{ onsInput({
            "id": params.id,
            "type": "file",
            "label": params.label,
            "classes": "input--upload" + (" input--error" if params.error else ""),
            "accept": params.accept,
            "name": params.name,
            "attributes": params.attributes,
            "listeners": params.listeners
        }) }}
    {% endset %}
    {% call onsField({
        "id": params.fieldId,
        "classes": params.fieldClasses,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        {{ field | safe }}
    {% endcall %}
{% endmacro %}

.input--upload {
  background: $color-white;
  border: 1px solid $color-input;
  border-radius: $input-radius;
  font-size: 1rem;
  padding: 0;
  width: 100%;
  &::-webkit-file-upload-button {
    background: $color-button-secondary;
    border: 0;
    border-bottom-right-radius: 0;
    border-right: 1px solid $color-input;
    border-top-right-radius: 0;
    color: $color-text;
    font-size: 1rem;
    outline: none;
    padding: 0.5rem 1rem;
    transition: border-color 200ms ease-in;
  }
  &:hover {
    cursor: pointer;
    &::-webkit-file-upload-button {
      border-right-color: $color-text-link-hover;
      cursor: pointer;
    }
  }
  @include mq(m) {
    width: 80%;
  }
  @include mq(l) {
    width: 70%;
  }
}

When to use this component

Use this component when there is a requirement for a user to select and submit a local file as part of their task.

How to use this component

The <input> value is set to type="file". A file upload input also takes the attribute accepts= which take a comma separated list of file extensions with the . prefix for example: accept=".xls,.xlsx,.pdf".

How to check uploads

To help users upload a file, you should:

  • check they have uploaded something
  • check that what they have uploaded is a valid file type
  • show an error message if they have not uploaded anything or what they have uploaded is not a valid file type

Error messages

Use the correct errors pattern and show the error details above the checkbox options.

<div class="panel panel--error panel--no-title u-mb-s" id="file-error">
  <span class="u-vh">Error: </span>
  <div class="panel__body">
    <p class="panel__error">
      <strong>Select a file that is an XLS, XLSX or PDF</strong>
    </p>
    <div class="field">
      <div class="field">
        <label class="label  label--with-description " for="file">Upload a file
        </label>
        <span id="description-hint" class="label__description  input--with-description">
          File types accepted are XLS and XLSX or PDF
        </span>
        <input type="file" id="file" class="input input--text input-type__input input--upload input--error" accept=".xls,.xlsx,.pdf" aria-describedby="description-hint" />
      </div>
    </div>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
id string true The id of the input. This will also be added to the label if a label is specified
label Label (ref) false Settings for the input label. for will automatically be set to match the input id
description string true The hint text for the upload input
accept string false Provides the allowed file types; file_extension, audio/, video/, image/, media_type. Further information on this attribute at w3 schools
size string false Set to ‘small’ to render the small variant
fieldId string false Id for the field
fieldClasses string false Classes for the field
listeners object false Creates a script element that adds an event listener to the element by id. Takes key { event } and value { function }
{% from "components/upload/_macro.njk" import onsUpload %}
{{
    onsUpload({
        "id": "file",
        "accept": ".xls,.xlsx,.pdf",
        "label": {
            "description": "File types accepted are XLS and XLSX or PDF",
            "text": "Upload a file"
        },
        "error": {
            "id": "file-error",
            "text": "Select a file that is an XLS, XLSX or PDF",
            "dsExample": isPatternLib
        }
    })
}}

{% macro onsUpload(params) %}
    {% from "components/input/_macro.njk" import onsInput %}
    {% from "components/field/_macro.njk" import onsField %}
    {% set field %}
        {{ onsInput({
            "id": params.id,
            "type": "file",
            "label": params.label,
            "classes": "input--upload" + (" input--error" if params.error else ""),
            "accept": params.accept,
            "name": params.name,
            "attributes": params.attributes,
            "listeners": params.listeners
        }) }}
    {% endset %}
    {% call onsField({
        "id": params.fieldId,
        "classes": params.fieldClasses,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        {{ field | safe }}
    {% endcall %}
{% endmacro %}

.input--upload {
  background: $color-white;
  border: 1px solid $color-input;
  border-radius: $input-radius;
  font-size: 1rem;
  padding: 0;
  width: 100%;
  &::-webkit-file-upload-button {
    background: $color-button-secondary;
    border: 0;
    border-bottom-right-radius: 0;
    border-right: 1px solid $color-input;
    border-top-right-radius: 0;
    color: $color-text;
    font-size: 1rem;
    outline: none;
    padding: 0.5rem 1rem;
    transition: border-color 200ms ease-in;
  }
  &:hover {
    cursor: pointer;
    &::-webkit-file-upload-button {
      border-right-color: $color-text-link-hover;
      cursor: pointer;
    }
  }
  @include mq(m) {
    width: 80%;
  }
  @include mq(l) {
    width: 70%;
  }
}

If no file has been selected

Use “Select a [whatever they need to select]”.
For example, “Select a report”.

If there was a problem and the file was not uploaded

Use “The selected file could not be uploaded. Please try again”.

If the file is the wrong file type

Use “Select a file that is [list of file types]”.
For example, “Select a file that is an XLS, XLSX or PDF”.

If the file is too big

Use “Select a file that is smaller than [largest file size]”.
For example, “Select a file that is smaller than 2MB”.

Help improve this component

Let us know how we could improve this component or share your user research findings.

Discuss the ‘Upload’ component on GitHub