Skip to main content
Back

File upload

This pattern is experimental

This is currently experimental because more research is needed. You should continue using it until we collect more research.

The file upload pattern lets users upload files to an HMRC service. It is optimised for integration with Upscan (the HMRC file upload service).

When to use

Use this pattern when users must upload a file to complete their journey.

When not to use

Do not use this pattern if there is no need for users to upload a file, or no good reason to ask for one. The interaction of uploading a file can be challenging for some users.

How it works

You need HMRC Frontend to use this pattern — find out how to install HMRC Frontend. If you use the HMRC Nunjucks macro, you must copy and paste the entire macro into your code.

How it works depends on whether the user needs the option to upload a single file, more than one file, or select the file type.

Let users upload a single file

Use the file upload component to let users upload a single file.

              <div class="govuk-form-group">
  <div class="govuk-form-group">
    <h1 class="govuk-label-wrapper"><label class="govuk-label govuk-label--xl" for="file-upload-1">
        Upload receipt
      </label>
    </h1>
    <div id="file-upload-1-hint" class="govuk-hint">
      You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
    </div>
    <input class="govuk-file-upload" id="file-upload-1" name="file-upload-1" type="file" aria-describedby="file-upload-1-hint">
  </div>

</div>

<button class="govuk-button" data-module="govuk-button">
  Continue
</button>
            
                {% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %}

<div class="govuk-form-group">
  {{ govukFileUpload({
    id: "file-upload-1",
    name: "file-upload-1",
    hint: {
      text: "You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB."
    },
    label: {
      text: "Upload receipt",
      classes: "govuk-label--xl",
      isPageHeading: true
    }
  }) }}
</div>

{{ govukButton({
  text: "Continue"
}) }}
              

Let users upload additional files

If users need the option to upload more than one file include an 'Upload another...' button.

              <div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">
    <h1 class="govuk-heading-xl">Upload receipts</h1>

    <div id="file-upload-1-hint" class="govuk-hint">
      You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
    </div>

    <p class="govuk-body" aria-live="polite">1 of 2 files uploaded</p>

    <button class="govuk-button govuk-button--secondary" data-module="govuk-button">
      Upload another receipt
    </button>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          receipt2.jpg
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--yellow">
  uploading
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt1.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <a class="govuk-link" href="#">receipt1.jpg</a>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--green">
  uploaded
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt1.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>
  </div>
</div>
            
                {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/tag/macro.njk" import govukTag %}


<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">
    <h1 class="govuk-heading-xl">Upload receipts</h1>

    <div id="file-upload-1-hint" class="govuk-hint">
        You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
    </div>

    <p class="govuk-body" aria-live="polite">1 of 2 files uploaded</p>

    {{ govukButton({
      text: "Upload another receipt",
      classes: "govuk-button--secondary"
    }) }}

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            text: "receipt2.jpg"
          },
          value: {
            text: govukTag({ text: "uploading", classes: "govuk-tag--yellow" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt1.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: '<a class="govuk-link" href="#">receipt1.jpg</a>'
          },
          value: {
            text: govukTag({ text: "uploaded", classes: "govuk-tag--green" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt1.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    {{ govukButton({
      text: "Continue"
    }) }}
  </div>
</div>
              

The button adds a new upload row.

              <div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">
    <h1 class="govuk-heading-xl">Upload receipts</h1>

    <div id="file-upload-1-hint" class="govuk-hint">
      You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
    </div>

    <p class="govuk-body" aria-live="polite">1 of 2 files uploaded</p>

    <div class="govuk-form-group">
      <label class="govuk-label govuk-visually-hidden" for="file-upload-1">
        Upload receipts
      </label>
      <input class="govuk-file-upload" id="file-upload-1" name="file-upload-1" type="file">
    </div>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          receipt2.jpg
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--yellow">
  uploading
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt2.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <a class="govuk-link" href="#">receipt1.jpg</a>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--green">
  uploaded
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt1.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>
  </div>
</div>
            
                {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/tag/macro.njk" import govukTag %}
{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %}

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">
    <h1 class="govuk-heading-xl">Upload receipts</h1>

    <div id="file-upload-1-hint" class="govuk-hint">
        You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
    </div>

    <p class="govuk-body" aria-live="polite">1 of 2 files uploaded</p>

    {{ govukFileUpload({
      id: "file-upload-1",
      name: "file-upload-1",
      label: {
        text: "Upload receipts",
        classes: "govuk-visually-hidden"
      }
    }) }}

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            text: "receipt2.jpg"
          },
          value: {
            text: govukTag({ text: "uploading", classes: "govuk-tag--yellow" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt2.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: '<a class="govuk-link" href="#">receipt1.jpg</a>'
          },
          value: {
            text: govukTag({ text: "uploaded", classes: "govuk-tag--green" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt1.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    {{ govukButton({
      text: "Continue"
    }) }}
  </div>
</div>
              

Let users select file types

If file type selection is required use a question page.

              <div class="govuk-form-group">
  <fieldset class="govuk-fieldset" aria-describedby="want-to-register-hint">
    <legend class="govuk-fieldset__legend govuk-fieldset__legend--l">
      <h1 class="govuk-fieldset__heading">
        Add supporting documents to your claim
      </h1>
    </legend>
    <div id="want-to-register-hint" class="govuk-hint">
      You can repeat this step to add more types of documents to your claim.
    </div>
    <div class="govuk-radios govuk-radios" data-module="govuk-radios">
      <div class="govuk-radios__item">
        <input class="govuk-radios__input" id="want-to-register" name="want-to-register" type="radio" value="declaration">
        <label class="govuk-label govuk-radios__label" for="want-to-register">
          Declaration
        </label>
      </div>
      <div class="govuk-radios__item">
        <input class="govuk-radios__input" id="want-to-register-2" name="want-to-register" type="radio" value="invoice">
        <label class="govuk-label govuk-radios__label" for="want-to-register-2">
          Invoice
        </label>
      </div>
      <div class="govuk-radios__item">
        <input class="govuk-radios__input" id="want-to-register-3" name="want-to-register" type="radio" value="receipt">
        <label class="govuk-label govuk-radios__label" for="want-to-register-3">
          Receipt
        </label>
      </div>
    </div>

  </fieldset>
</div>

<button class="govuk-button" data-module="govuk-button">
  Continue
</button>
            
                {% from "govuk/components/radios/macro.njk" import govukRadios %}
{% from "govuk/components/button/macro.njk" import govukButton %}

{{ govukRadios({
  classes: "govuk-radios",
  idPrefix: "want-to-register",
  name: "want-to-register",
  hint: {
    text: "You can repeat this step to add more types of documents to your claim."
  },
  fieldset: {
    legend: {
      text: "Add supporting documents to your claim",
      isPageHeading: true,
      classes: "govuk-fieldset__legend--l"
    }
  },
  items: [
    {
      value: "declaration",
      text: "Declaration"
    },
    {
      value: "invoice",
      text: "Invoice"
    },
    {
      value: "receipt",
      text: "Receipt"
    }
  ]
}) }}

{{ govukButton({
  text: "Continue"
}) }}
              

Use a Yes/No question to route the user back to file type selection. Label previous upload rows. In the following example the user has:

  1. Selected 'Declaration'
  2. Uploaded a declaration
  3. Selected 'Add a different type of supporting evidence to your claim?'
  4. Selected 'Invoice'
              <div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">
    <div class="govuk-form-group">
      <h1 class="govuk-label-wrapper"><label class="govuk-label govuk-label--xl" for="file-upload-1">
          Upload invoice
        </label>
      </h1>
      <div id="file-upload-1-hint" class="govuk-hint">
        You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
      </div>
      <input class="govuk-file-upload" id="file-upload-1" name="file-upload-1" type="file" aria-describedby="file-upload-1-hint">
    </div>

    <hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">1 of 1 files uploaded.</div>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <a class="govuk-link" href="#">declaration.jpg</a>
          <div class="govuk-body govuk-!-margin-0">Declaration</div>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--green">
  uploaded
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> declaration.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <div class="govuk-form-group">
      <fieldset class="govuk-fieldset">
        <legend class="govuk-fieldset__legend govuk-fieldset__legend govuk-fieldset__legend--m">
          Add a different type of supporting evidence to your claim?
        </legend>
        <div class="govuk-radios" data-module="govuk-radios">
          <div class="govuk-radios__item">
            <input class="govuk-radios__input" id="add-a-different-type-of-evidence" name="add-a-different-type-of-evidence" type="radio" value="yes">
            <label class="govuk-label govuk-radios__label" for="add-a-different-type-of-evidence">
              Yes
            </label>
          </div>
          <div class="govuk-radios__item">
            <input class="govuk-radios__input" id="add-a-different-type-of-evidence-2" name="add-a-different-type-of-evidence" type="radio" value="no">
            <label class="govuk-label govuk-radios__label" for="add-a-different-type-of-evidence-2">
              No
            </label>
          </div>
        </div>

      </fieldset>
    </div>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>
            
                {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/tag/macro.njk" import govukTag %}
{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %}
{% from "govuk/components/radios/macro.njk" import govukRadios %}

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">
    {{ govukFileUpload({
      id: "file-upload-1",
      name: "file-upload-1",
      hint: {
        text: "You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB."
      },
      label: {
        text: "Upload invoice",
        classes: "govuk-label--xl",
        isPageHeading: true
      }
    }) }}

    <hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">1 of 1 files uploaded.</div>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            html: '<a class="govuk-link" href="#">declaration.jpg</a><div class="govuk-body govuk-!-margin-0">Declaration</div>'
          },
          value: {
            text: govukTag({ text: "uploaded", classes: "govuk-tag--green" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "declaration.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    {{ govukRadios({
      name: "add-a-different-type-of-evidence",
      fieldset: {
        legend: {
          text: "Add a different type of supporting evidence to your claim?",
          classes: "govuk-fieldset__legend govuk-fieldset__legend--m"
        }
      },
      items: [
        {
          value: "yes",
          text: "Yes"
        },
        {
          value: "no",
          text: "No"
        }
      ]
    }) }}

    {{ govukButton({
      text: "Continue"
    }) }}
              

Let users upload a fixed set of documents

If multiple specific file uploads are required show labelled upload rows.

              <h1 class="govuk-heading-xl">Upload declaration, receipt and calculation worksheet</h1>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <div id="file-upload-1-hint" class="govuk-hint">
      You can upload a scanned copy or photo of the original. Each selected file must be smaller than 100MB.
    </div>

    <p class="govuk-body" aria-live="polite">1 of 3 files uploaded</p>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <a class="govuk-link" href="#">declaration.jpg</a>
          <div class="govuk-body govuk-!-margin-0">Declaration</div>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--green">
  uploaded
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> declaration.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <div class="govuk-form-group">
      <label class="govuk-label" for="file-upload-1">
        Receipt
      </label>
      <input class="govuk-file-upload" id="file-upload-1" name="file-upload-1" type="file">
    </div>

    <hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

    <div class="govuk-form-group">
      <label class="govuk-label" for="file-upload-2">
        Calculation worksheet
      </label>
      <input class="govuk-file-upload" id="file-upload-2" name="file-upload-2" type="file">
    </div>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>
  </div>
</div>
            
                {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/tag/macro.njk" import govukTag %}
{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %}

<h1 class="govuk-heading-xl">Upload declaration, receipt and calculation worksheet</h1>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <div id="file-upload-1-hint" class="govuk-hint">
        You can upload a scanned copy or photo of the original. Each selected file must be smaller than 100MB.
    </div>

    <p class="govuk-body" aria-live="polite">1 of 3 files uploaded</p>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            html: '<a class="govuk-link" href="#">declaration.jpg</a><div class="govuk-body govuk-!-margin-0">Declaration</div>'
          },
          value: {
            text: govukTag({ text: "uploaded", classes: "govuk-tag--green" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "declaration.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    {{ govukFileUpload({
      id: "file-upload-1",
      name: "file-upload-1",
      label: {
        text: "Receipt"
      }
    }) }}

    <hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

    {{ govukFileUpload({
      id: "file-upload-2",
      name: "file-upload-2",
      label: {
        text: "Calculation worksheet"
      }
    }) }}

    {{ govukButton({
      text: "Continue"
    }) }}
  </div>
</div>
              

Make users aware of the status of their upload

Use a yellow 'UPLOADING' tag to show that a file is being uploaded or scanned. When JavaScript isn’t available include a ‘Refresh page to update file upload progress’ link to the same page above the summary list.

              <h1 class="govuk-heading-xl">Upload receipt</h1>

<div id="file-upload-1-hint" class="govuk-hint">
  You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
</div>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation"></div>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          receipt1.jpg
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--yellow">
  uploading
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt1.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>
  </div>
</div>
            
                {% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/tag/macro.njk" import govukTag %}

<h1 class="govuk-heading-xl">Upload receipt</h1>

<div id="file-upload-1-hint" class="govuk-hint">
    You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
</div>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation"></div>

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            text: "receipt1.jpg"
          },
          value: {
            text: govukTag({ text: "uploading", classes: "govuk-tag--yellow" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt1.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    {{ govukButton({
      text: "Continue"
    }) }}
  </div>
</div>
              

Use a green 'UPLOADED' tag to show the user that their file has been uploaded and scanned successfully. Announce 'file uploaded' in an aria-live region. Link to a copy of the file from the filename.

              <h1 class="govuk-heading-xl">Upload receipt</h1>

<div id="file-upload-1-hint" class="govuk-hint">
  You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
</div>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">File uploaded.</div>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <a class="govuk-link" href="#">receipt1.jpg</a>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--green">
  uploaded
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt1.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">file uploaded.</div>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>
  </div>
</div>
            
                {% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/tag/macro.njk" import govukTag %}

<h1 class="govuk-heading-xl">Upload receipt</h1>

<div id="file-upload-1-hint" class="govuk-hint">
    You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
</div>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">File uploaded.</div>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            html: '<a class="govuk-link" href="#">receipt1.jpg</a>'
          },
          value: {
            text: govukTag({ text: "uploaded", classes: "govuk-tag--green" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt1.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">file uploaded.</div>

    {{ govukButton({
      text: "Continue"
    }) }}
  </div>
</div>
              

Multiple file uploads

Add a polite aria-live region above the summary list of files ‘X of X files uploaded.‘.

Removing files

When a file is removed add a polite visually hidden aria-live region ‘file [file name] removed’ above the summary list of files.

Accept multiple file types

Let users upload as many different file types as possible. Convert them automatically, if you need to.

If you must limit file types, let users know by using hint text.

Error messages

Use the file upload error messages below. Error 'The selected file could not be uploaded' should only be used if Upscan reports unknown problems with the file.

              <div class="govuk-error-summary" data-module="govuk-error-summary">

  <div role="alert">
    <h2 class="govuk-error-summary__title">
      There is a problem
    </h2>
    <div class="govuk-error-summary__body">
      <ul class="govuk-list govuk-error-summary__list">
        <li>
          <a href="#not-uploaded-error">The selected file has not fully uploaded</a>
        </li>
        <li>
          <a href="#select-error">Select a file</a>
        </li>
        <li>
          <a href="#empty-error">The selected file is empty</a>
        </li>
        <li>
          <a href="#smaller-error">The selected file must be smaller than 100MB</a>
        </li>
        <li>
          <a href="#already-error">The selected file has already been uploaded</a>
        </li>
        <li>
          <a href="#type-error">The selected file must be a JPG, PNG or PDF</a>
        </li>
        <li>
          <a href="#virus-error">The selected file contains a virus — upload a different one</a>
        </li>
        <li>
          <a href="#could-not-error">The selected file could not be uploaded</a>
        </li>
        <li>
          <a href="#add-a-different-type-of-evidence-error">Select yes if you want to add a different type of supporting evidence</a>
        </li>
      </ul>
    </div>
  </div>
</div>

<h1 class="govuk-heading-xl">Upload receipts</h1>

<div id="file-upload-1-hint" class="govuk-hint">
  You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
</div>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">1 of 1 files uploaded.</div>

    <dl class="govuk-summary-list govuk-summary-list--long-key">
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <a class="govuk-link" href="#">receipt1.jpg</a>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--green">
  uploaded
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt1.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            receipt2.jpg
            <p id="not-uploaded-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file has not fully uploaded
            </p>
          </div>
        </dt>
        <dd class="govuk-summary-list__value">
          <strong class="govuk-tag govuk-tag--yellow">
  uploading
</strong>

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt2.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="select-error">
              receipt3.jpg
            </label>
            <p id="select-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> Select a file
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="select-error" name="select-error" type="file" aria-describedby="select-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt3.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="empty-error">
              receipt4.jpg
            </label>
            <p id="empty-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file is empty
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="empty-error" name="empty-error" type="file" aria-describedby="empty-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt4.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="smaller-error">
              receipt5.jpg
            </label>
            <p id="smaller-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file must be smaller than 100MB
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="smaller-error" name="smaller-error" type="file" aria-describedby="smaller-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt5.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="already-error">
              receipt6.jpg
            </label>
            <p id="already-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file has already been uploaded
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="already-error" name="already-error" type="file" aria-describedby="already-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt6.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="type-error">
              receipt7.jpg
            </label>
            <p id="type-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file must be a JPG, PNG or PDF
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="type-error" name="type-error" type="file" aria-describedby="type-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt7.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="virus-error">
              receipt8.jpg
            </label>
            <p id="virus-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file contains a virus — upload a different one
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="virus-error" name="virus-error" type="file" aria-describedby="virus-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt8.jpg</span>
          </a>
        </dd>
      </div>
      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          <div class="govuk-form-group govuk-form-group--error">
            <label class="govuk-label govuk-!-font-weight-bold" for="could-not-error">
              receipt9.jpg
            </label>
            <p id="could-not-error-error" class="govuk-error-message">
              <span class="govuk-visually-hidden">Error:</span> The selected file could not be uploaded
            </p>
            <input class="govuk-file-upload govuk-file-upload--error" id="could-not-error" name="could-not-error" type="file" aria-describedby="could-not-error-error">
          </div>

        </dt>
        <dd class="govuk-summary-list__value">

        </dd>
        <dd class="govuk-summary-list__actions">
          <a class="govuk-link" href="#">
            Remove<span class="govuk-visually-hidden"> receipt9.jpg</span>
          </a>
        </dd>
      </div>
    </dl>

    <button class="govuk-button govuk-button--secondary" data-module="govuk-button">
      Upload another receipt
    </button>

    <hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

    <div class="govuk-form-group govuk-form-group--error">
      <fieldset class="govuk-fieldset" aria-describedby="add-a-different-type-of-evidence-error">
        <legend class="govuk-fieldset__legend govuk-fieldset__legend govuk-fieldset__legend--m">
          Add a different type of supporting evidence to your claim?
        </legend>
        <p id="add-a-different-type-of-evidence-error" class="govuk-error-message">
          <span class="govuk-visually-hidden">Error:</span> Select yes if you want to add a different type of supporting evidence
        </p>
        <div class="govuk-radios" data-module="govuk-radios">
          <div class="govuk-radios__item">
            <input class="govuk-radios__input" id="add-a-different-type-of-evidence" name="add-a-different-type-of-evidence" type="radio" value="yes">
            <label class="govuk-label govuk-radios__label" for="add-a-different-type-of-evidence">
              Yes
            </label>
          </div>
          <div class="govuk-radios__item">
            <input class="govuk-radios__input" id="add-a-different-type-of-evidence-2" name="add-a-different-type-of-evidence" type="radio" value="no">
            <label class="govuk-label govuk-radios__label" for="add-a-different-type-of-evidence-2">
              No
            </label>
          </div>
        </div>

      </fieldset>
    </div>

    <button class="govuk-button" data-module="govuk-button">
      Continue
    </button>

  </div>
</div>
            
                {% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/tag/macro.njk" import govukTag %}
{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %}
{% from "govuk/components/radios/macro.njk" import govukRadios %}

{{ govukErrorSummary({
  titleText: "There is a problem",
  errorList: [
    {
      text: "The selected file has not fully uploaded",
      href: "#not-uploaded-error"
    },
    {
      text: "Select a file",
      href: "#select-error"
    },
    {
      text: "The selected file is empty",
      href: "#empty-error"
    },
    {
      text: "The selected file must be smaller than 100MB",
      href: "#smaller-error"
    },
    {
      text: "The selected file has already been uploaded",
      href: "#already-error"
    },
    {
      text: "The selected file must be a JPG, PNG or PDF",
      href: "#type-error"
    },
    {
      text: "The selected file contains a virus — upload a different one",
      href: "#virus-error"
    },
    {
      text: "The selected file could not be uploaded",
      href: "#could-not-error"
    },
    {
      text: "Select yes if you want to add a different type of supporting evidence",
      href: "#add-a-different-type-of-evidence-error"
    }
  ]
}) }}

<h1 class="govuk-heading-xl">Upload receipts</h1>

<div id="file-upload-1-hint" class="govuk-hint">
    You can upload your receipt as a scanned copy or photo of the original. The selected file must be smaller than 100MB.
</div>

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <p class="govuk-body govuk-!-display-none" id="refreshPageProgress"><a href="#" class="govuk-link">Refresh page to update file upload progress</a></p>

    <div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">1 of 1 files uploaded.</div>

    {{ govukSummaryList({
      classes: 'govuk-summary-list--long-key',
      rows: [
        {
          key: {
            html: '<a class="govuk-link" href="#">receipt1.jpg</a>'
          },
          value: {
            text: govukTag({ text: "uploaded", classes: "govuk-tag--green" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt1.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: '<div class="govuk-form-group govuk-form-group--error">
              receipt2.jpg
              <p id="not-uploaded-error" class="govuk-error-message">
                <span class="govuk-visually-hidden">Error:</span> The selected file has not fully uploaded
              </p>
            </div>'
          },
          value: {
            text: govukTag({ text: "uploading", classes: "govuk-tag--yellow" })
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt2.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "select-error",
              name: "select-error",
              errorMessage: {
                text: "Select a file"
              },
              label: {
                text: "receipt3.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt3.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "empty-error",
              name: "empty-error",
              errorMessage: {
                text: "The selected file is empty"
              },
              label: {
                text: "receipt4.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt4.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "smaller-error",
              name: "smaller-error",
              errorMessage: {
                text: "The selected file must be smaller than 100MB"
              },
              label: {
                text: "receipt5.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt5.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "already-error",
              name: "already-error",
              errorMessage: {
                text: "The selected file has already been uploaded"
              },
              label: {
                text: "receipt6.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt6.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "type-error",
              name: "type-error",
              errorMessage: {
                text: "The selected file must be a JPG, PNG or PDF"
              },
              label: {
                text: "receipt7.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt7.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "virus-error",
              name: "virus-error",
              errorMessage: {
                text: "The selected file contains a virus — upload a different one"
              },
              label: {
                text: "receipt8.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt8.jpg"
              }
            ]
          }
        },
        {
          key: {
            html: govukFileUpload({
              id: "could-not-error",
              name: "could-not-error",
              errorMessage: {
                text: "The selected file could not be uploaded"
              },
              label: {
                text: "receipt9.jpg",
                classes: "govuk-!-font-weight-bold"
              }
            })
          },
          value: {
            text: ''
          },
          actions: {
            items: [
              {
                href: "#",
                text: "Remove",
                visuallyHiddenText: "receipt9.jpg"
              }
            ]
          }
        }
      ]
    }) }}

    {{ govukButton({
      text: "Upload another receipt",
      classes: "govuk-button--secondary"
    }) }}

    <hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

    {{ govukRadios({
      name: "add-a-different-type-of-evidence",
      fieldset: {
        legend: {
          text: "Add a different type of supporting evidence to your claim?",
          classes: "govuk-fieldset__legend govuk-fieldset__legend--m"
        }
      },
      items: [
        {
          value: "yes",
          text: "Yes"
        },
        {
          value: "no",
          text: "No"
        }
      ],
      errorMessage: {
        text: "Select yes if you want to add a different type of supporting evidence"
      }
    }) }}

    {{ govukButton({
      text: "Continue"
    }) }}

  </div>
</div>
              

Research

We need more research. If you have used the file upload pattern get in touch to share your research findings.

Discuss file upload on GitHub