Uploads de arquivos acessíveis

Feb 03 2023
Os uploads de arquivos HTML funcionam muito bem, mas eles parecem horríveis, vamos corrigir isso de uma forma semântica e acessível. A entrada do Arquivo de Problema parece ruim.

Os uploads de arquivos HTML funcionam muito bem, mas eles parecem horríveis, vamos corrigir isso de uma forma semântica e acessível.

O problema

A entrada do arquivo parece ruim.

Confira este, eu não estilizei nada. Este é o estilo padrão para a entrada de arquivo no Firefox.

Captura de tela da entrada de arquivo padrão do Firefox

Para ser bem claro, o código para adicionar essa entrada à página é <input type="file">.

Agora, é claro, sempre argumentarei que a funcionalidade deve ser priorizada em relação aos visuais, mas deve haver algo que possamos fazer para estilizar essa entrada sem perder sua funcionalidade.

Estilos CSS

Infelizmente, esta é uma seção curta.

Realmente não há muitas propriedades que possamos usar para estilizar nossa entrada. Claro, podemos adicionar background-colorou fornecer um novo font-family, mas não temos como estilizar o botão 'Procurar…'.

E agora?

De um modo geral, o uso de elementos nativos do navegador nos fornecerá acessibilidade sem nenhum trabalho extra. Então, como podemos manter essa entrada na página enquanto estilizamos outra coisa em seu lugar?

Rótulos.

O labelelemento tem uma longa história de uso no lugar de inputs para estilizar. Aqui estão algumas marcações:

<label class="file-upload">
  <span class="file-upload__text">
    Click or Drag file here...
  </span>
  <input type="file" class="file-upload__input">
</label>

Agora que temos nossa marcação, vamos estilizar um pouco a entrada.

.file-upload {
  box-sizing: border-box;
  height: 200px;
  width: 100%;
  background-color: hsl(317, 20%, 80%);
  border: 5px dashed hsl(317, 20%, 60%);
  border-radius: 20px;
  position: relative;
  transition: 0.2s ease all;
// Align all children to the center of the container
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.file-upload:hover {
  background-color: hsl(317, 20%, 90%);
}
.file-upload:focus,
.file-upload:focus-within {
  outline: 5px solid hsl(317, 20%, 60%);
  outline-offset: 5px;
}
.file-upload__text {
  font-size: 2em;
  font-family: sans-serif;
}
.file-upload__input {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
// Temporary Styles 
  background-color: lightblue;
}

Como nosso labelestá vinculado ao nosso input, ele se comportará da mesma forma que clicar em nossa inputvontade. Tudo o que temos a fazer agora é ocultar o inputvisual e estamos prontos!

Captura de tela dos dois exemplos de código mais recentes

Ao atualizar os estilos para .file-upload__inputremover nosso background-colore adicionar nosso opacity, podemos ocultar visualmente a entrada do arquivo enquanto o mantemos na página para manter a acessibilidade e os comportamentos padrão do navegador (como clicar e arrastar).

.file-upload__input {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
// New Styles
  opacity: 0;
}

      
                
Screenshot of the file upload with new changes to our CSS from most recent code example

Um dos comportamentos padrão de uma entrada de arquivo é mostrar o nome do arquivo que você selecionou. Infelizmente, não há como mostrar essas informações sem um pouco de Javascript. Vamos observar a funcionalidade que gostaríamos de adicionar abaixo:

  1. Informar o usuário quando nenhum arquivo for selecionado
  2. Mostra o nome do arquivo do usuário quando um arquivo é selecionado

<input type="file" class="file-upload__input" id="FileUploadInput">

<span class="file-upload__file-name" id="FileUploadFileName">No file selected</span>

<label class="file-upload">
  <span class="file-upload__text">
    Click or Drag file here...
  </span>
  <span role="presentation" class="file-upload__file-name" id="FileUploadFileName">
    No file selected
  </span>
  <input type="file" class="file-upload__input" id="FileUploadInput">
</label>

var fileInput = document.querySelector("#FileUploadInput");
var fileName = document.querySelector("#FileUploadFileName");

fileInput.addEventListener("change", function () {
  fileName.innerText = fileInput.value.split("\\").pop();
});

var fileInput = document.querySelector("#FileUploadInput");
var fileName = document.querySelector("#FileUploadFileName");
fileInput.addEventListener("change", function () {
  fileName.innerText = fileInput.value.split("\\").pop();
});

Com a adição de algumas linhas de Javascript, podemos fornecer aos usuários um feedback visual sobre qual arquivo foi carregado. O que é melhor, conseguimos fazer tudo isso sem quebrar a funcionalidade subjacente e a acessibilidade do nosso código!

Aproveitando os elementos HTML disponíveis para nós, usando CSS para estilizá-los de forma que possamos apresentar aos nossos usuários uma melhor experiência visual e contando apenas com Javascript para preencher as lacunas, conseguimos criar um upload de arquivo que deve precisar de manutenção mínima e depende da funcionalidade nativa do navegador.

Isso é bem legal!