Skip to content

Acessibilidade

A acessibilidade da web (também conhecida como a11y) refere-se a prática de criar páginas e aplicações de web que podem ser usadas por qualquer um — seja essa uma pessoa com uma deficiência, uma conexão lenta, hardware destroçado ou desatualizado ou simplesmente alguém em um ambiente desfavorável. Por exemplo, adicionar legendas à um vídeo ajuda tanto os teus utilizadores surdos e com dificuldades de audição quanto os teus utilizadores que estão em um ambiente ruidoso e que não podem ouvir seus telemóveis. Similarmente, certificar-te que o teu texto não é de muito contraste muito baixo ajudará tanto os teus utilizadores de visão fraca quanto os teus utilizadores que estão a tentar usar os seus telemóveis na luz do sol forte.

Pronto para começar mas não sem a certeza de por onde?

Consulte o guia de planeamento e gerência da acessibilidade da web fornecido pelo Consórcio da World Wide Web (W3C)

Tu deves adicionar uma ligação no topo de cada página que vai diretamente para a área do conteúdo principal assim os utilizadores podem salter o conteúdo que é repetido em várias páginas de Web.

Normalmente, isto é feito no topo de App.vue visto que será o primeiro elemento concentrável em todas as tuas páginas:

template
<ul class="skip-links">
  <li>
    <a href="#main" ref="skipLink" class="skip-link">Skip to main content</a>
  </li>
</ul>

Para esconder a ligação se não ela é focada, podes adicionar o seguinte estilo:

css
.skip-link {
  white-space: nowrap;
  margin: 1em auto;
  top: 0;
  position: fixed;
  left: 50%;
  margin-left: -72px;
  opacity: 0;
}
.skip-link:focus {
  opacity: 1;
  background-color: white;
  padding: 0.5em;
  border: 1px solid black;
}

Uma vez que o utilizador mudar a rota, traga o foco de volta para a ligação saltar. Isto pode ser alcançado chamando o foco na referência do modelo de marcação da ligação saltar (assumindo o uso da vue-router):

vue
<script>
export default {
  watch: {
    $route() {
      this.$refs.skipLink.focus()
    }
  }
}
</script>
vue
<script setup>
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const skipLink = ref()

watch(
  () => route.path,
  () => {
    skipLink.value.focus()
  }
)
</script>

Leia a documentação sobre a ligação "saltar para o conteúdo principal"

Estrutura de Conteúdo

Um dos pedaços mais importantes da acessibilidade é garantir que o desenho possa suportar a implementação acessível. O desenho deve considerar não apenas o contraste de cor, seleção de fonte, tamanho de texto, e linguagem mas também como o conteúdo é estruturado na aplicação.

Cabeçalhos

Os utilizadores podem navegar em uma aplicação através dos cabeçalhos. Ter cabeçalhos descritivos para cada seção da tua aplicação torna mais fácil para os utilizadores prever o conteúdo de cada seção. Quando falamos de cabeçalhos, existem algumas práticas de acessibilidade recomendadas:

  • Encaixar cabeçalhos nas suas ordem de classificação: <h1> - <h6>
  • Não saltar cabeçalhos dentro de uma seção
  • Usar marcadores de cabeçalho verdadeiros ao invés da estilização de texto para dar a aparência visual dos cabeçalhos

Leia mais sobre cabeçalhos:

template
<main role="main" aria-labelledby="main-title">
  <h1 id="main-title">Main title</h1>
  <section aria-labelledby="section-title">
    <h2 id="section-title"> Section Title </h2>
    <h3>Section Subtitle</h3>
    <!-- Content -->
  </section>
  <section aria-labelledby="section-title">
    <h2 id="section-title"> Section Title </h2>
    <h3>Section Subtitle</h3>
    <!-- Content -->
    <h3>Section Subtitle</h3>
    <!-- Content -->
  </section>
</main>

Marcos

Os marcos fornecem acesso programático às seções dentro de uma aplicação. Os utilizadores que dependem de tecnologia ajustantes podem navegar para cada seção da aplicação e saltar sobre o conteúdo. Tu podes usar os papeis de ARIA para ajudar-te a alcançar isto.

HTMLPapeis de ARIAPropósito do Marco
headerrole="banner"Cabeçalho principal: título da página.
navrole="navigation"Coleção de ligações adequadas para uso quando estiveres a navegar pelo documento ou documentos relacionados.
mainrole="main"O conteúdo principal ou central do documento.
footerrole="contentinfo"Informação sobre o documento pai: notas de rodapé ou direitos de autor ou ligações para o relatório de privacidade.
asiderole="complementary"Sustenta o conteúdo principal, mais é separado e significativo em seu próprio conteúdo.
searchrole="search"Esta seção contém a funcionalidade de pesquisa para a aplicação.
formrole="form"Coleção de elementos associados ao formulário.
sectionrole="region"O conteúdo que é relevante e para o qual os utilizadores provavelmente quererão navegar. O rótulo deve ser fornecido para este elemento.

DICA:

É recomendado usar os elementos de HTML de marco com atributos do papel do marco redundante para maximizar a compatibilidade com navegadores antigos que não suportam os elementos semânticos da HTML5.

Leia mais sobre os marcos

Formulários Semânticos

Quando criares um formulário, podes usar os seguintes elementos: <form>, <label>, <input>, <textarea>, e <button>.

Os rótulos são normalmente colocados no princípio ou a esquerda dos campos do formulário:

template
<form action="/dataCollectionLocation" method="post" autocomplete="on">
  <div v-for="item in formItems" :key="item.id" class="form-item">
    <label :for="item.id">{{ item.label }}: </label>
    <input
      :type="item.type"
      :id="item.id"
      :name="item.id"
      v-model="item.value"
    />
  </div>
  <button type="submit">Submit</button>
</form>

Nota como podes incluir autocomplete='on' no elemento de formulário e aplicar-se-á à todas entradas no teu formulário. Tu podes também definir valores diferentes para o atributo autocomplete para cada entrada.

Rótulos

Forneça rótulos para descrever o propósito de todos os mecanismo de controlo do formulário: ligando for e id:

template
<label for="name">Name</label>
<input type="text" name="name" id="name" v-model="name" />

Se inspecionares este elemento nas ferramentas de programação do teu navegador Google Chrome e abrires a aba de Acessibilidade dentro da aba de Elementos, verás como a entrada recebe o seu nome a partir do rótulo:

Ferramentas de Programação do Chrome exibindo o nome acessível da entrada do rótulo

Aviso:

Embora tenhas visto rótulos envolvendo os campos de entrada como este:

template
<label>
  Name:
  <input type="text" name="name" id="name" v-model="name" />
</label>

A definição explícita dos rótulos com um identificador correspondente é melhor suportado pela tecnologia ajudante.

aria-label

Tu podes também atribuir a entrada um nome acessível com o aria-label:

template
<label for="name">Name</label>
<input
  type="text"
  name="name"
  id="name"
  v-model="name"
  :aria-label="nameLabel"
/>

Esteja a vontade para inspecionar este elemento nas Ferramentas de Programação do Chrome para veres como o nome acessível tem mudado:

Ferramentas de Programação do Chrome exibindo o nome acessível da entrada do

aria-labelledby

O uso de aria-labelledby é parecido com o aria-label exceto que é usado se o texto do rótulo estiver visível na tela. É emparelhado com os outros elementos pelo seu id e podes ligar vários id:

template
<form
  class="demo"
  action="/dataCollectionLocation"
  method="post"
  autocomplete="on"
>
  <h1 id="billing">Billing</h1>
  <div class="form-item">
    <label for="name">Name:</label>
    <input
      type="text"
      name="name"
      id="name"
      v-model="name"
      aria-labelledby="billing name"
    />
  </div>
  <button type="submit">Submit</button>
</form>

Ferramentas de Programação do Chrome exibindo o nome acessível da entrada do

aria-describedby

O aria-describedby é usado da mesma maneira que o aria-labelledby exceto que fornece uma descrição com informação adicional que o utilizador possa precisar. Isto pode ser usado para descrever o critério para qualquer entrada:

template
<form
  class="demo"
  action="/dataCollectionLocation"
  method="post"
  autocomplete="on"
>
  <h1 id="billing">Billing</h1>
  <div class="form-item">
    <label for="name">Full Name:</label>
    <input
      type="text"
      name="name"
      id="name"
      v-model="name"
      aria-labelledby="billing name"
      aria-describedby="nameDescription"
    />
    <p id="nameDescription">Please provide first and last name.</p>
  </div>
  <button type="submit">Submit</button>
</form>

Tu podes ver a descrição inspecionando as Ferramentas de Programação do Chrome:

Ferramentas de Programação do Chrome exibindo o nome acessível da entrada do  e a descrição com o

Espaço Reservado

Evite usar espaços reservados visto que podem confundir muitos utilizadores.

Um dos problemas com os espaços reservados é que não cumprem com o critério de contraste de cor por padrão; corrigir o contraste de cor faz o espaço reservado parecer como dados pré-povoado nos campos de entrada. Olhando no seguinte exemplo, podes ver que o espaço reservado do Último Nome o qual cumpre com o critério de contraste de cor parece-se com dado pré-povoado:

Espaço reservado acessível

template
<form
  class="demo"
  action="/dataCollectionLocation"
  method="post"
  autocomplete="on"
>
  <div v-for="item in formItems" :key="item.id" class="form-item">
    <label :for="item.id">{{ item.label }}: </label>
    <input
      type="text"
      :id="item.id"
      :name="item.id"
      v-model="item.value"
      :placeholder="item.placeholder"
    />
  </div>
  <button type="submit">Submit</button>
</form>
css
/* https://www.w3schools.com/howto/howto_css_placeholder.asp */

#lastName::placeholder {
  /* Chrome, Firefox, Opera, Safari 10.1+ */
  color: black;
  opacity: 1; /* Firefox */
}

#lastName:-ms-input-placeholder {
  /* Internet Explorer 10-11 */
  color: black;
}

#lastName::-ms-input-placeholder {
  /* Microsoft Edge */
  color: black;
}

É melhor fornecer todas as informações que o utilizador precisa para preencher os formulários fora de quaisquer entradas.

Instruções

Quando estiveres a adicionar as instruções para os teus campos de entrada, certifica-te de ligá-lo corretamente ao campo de entrada. Tu podes fornecer instruções adicionais e vincule vários identificadores dentro de um aria-labelledby. Isto permite um desenho mais flexível:

template
<fieldset>
  <legend>Using aria-labelledby</legend>
  <label id="date-label" for="date">Current Date:</label>
  <input
    type="date"
    name="date"
    id="date"
    aria-labelledby="date-label date-instructions"
  />
  <p id="date-instructions">MM/DD/YYYY</p>
</fieldset>

Alternativamente, podes atribuir as instruções ao campo de entrada com o aria-describedby:

template
<fieldset>
  <legend>Using aria-describedby</legend>
  <label id="dob" for="dob">Date of Birth:</label>
  <input type="date" name="dob" id="dob" aria-describedby="dob-instructions" />
  <p id="dob-instructions">MM/DD/YYYY</p>
</fieldset>

Escondendo Conteúdo

Normalmente não é recomendado esconder visualmente os rótulos, mesmo se a entrada tiver um nome acessível. No entanto, se a funcionalidade da entrada pode ser entendida com o conteúdo circundante, então podemos esconder o rótulo visual.

Observemos este campo de pesquisa:

template
<form role="search">
  <label for="search" class="hidden-visually">Search: </label>
  <input type="text" name="search" id="search" v-model="search" />
  <button type="submit">Search</button>
</form>

Nós podemos fazer isto porque o botão de pesquisa ajudará os utilizadores visuais a identificarem o propósito do campo de entrada.

Nós podemos usar a CSS para esconder visualmente os elementos mas mantê-los disponíveis para a tecnologia assistiva:

css
.hidden-visually {
  position: absolute;
  overflow: hidden;
  white-space: nowrap;
  margin: 0;
  padding: 0;
  height: 1px;
  width: 1px;
  clip: rect(0 0 0 0);
  clip-path: inset(100%);
}

aria-hidden="true"

Adding aria-hidden="true" will hide the element from assistive technology but leave it visually available for other users. Do not use it on focusable elements, purely on decorative, duplicated or offscreen content.

template
<p>This is not hidden from screen readers.</p>
<p aria-hidden="true">This is hidden from screen readers.</p>

Botões

Quando estiveres a usar os botões dentro de um formulário, deves definir o tipo para evitar a submissão do formulário. Tu podes também usar uma entrada para criar os botões:

template
<form action="/dataCollectionLocation" method="post" autocomplete="on">
  <!-- Botões -->
  <button type="button">Cancel</button>
  <button type="submit">Submit</button>

  <!-- Botões de entrada -->
  <input type="button" value="Cancel" />
  <input type="submit" value="Submit" />
</form>

Imagens Funcionais

Tu podes usar esta técnica para criar imagens funcionais.

  • Campos de entrada

    • Estas imagens agirão como um botão de tipo submissão em formulários
    template
    <form role="search">
      <label for="search" class="hidden-visually">Search: </label>
      <input type="text" name="search" id="search" v-model="search" />
      <input
        type="image"
        class="btnImg"
        src="https://img.icons8.com/search"
        alt="Search"
      />
    </form>
  • Ícones

template
<form role="search">
  <label for="searchIcon" class="hidden-visually">Search: </label>
  <input type="text" name="searchIcon" id="searchIcon" v-model="searchIcon" />
  <button type="submit">
    <i class="fas fa-search" aria-hidden="true"></i>
    <span class="hidden-visually">Search</span>
  </button>
</form>

Padrões

A Iniciativa de Acessibilidade da Web (WAI, sigla em Inglês) do Consórcio da World Wide Web (W3C, sigla em Inglês) desenvolve os padrões de acessibilidade da web para os diferentes componentes:

Diretrizes de Acessibilidade do Conteúdo da Web (WCAG)

A WCAG 2.1 estende o WCAG 2.0 e permite a implementação de novas tecnologias endereçando as mudanças para a web. O W3C encoraja o uso da versão mais atual de WCAG quando estiveres a desenvolver ou a atualizar as políticas de acessibilidade da Web.

WCAG 2.1 Quatro Princípios Orientadores Principais (abreviado como POUR, em Inglês):

  • Percebível
    • Os utilizadores devem ser capazes de perceber a informação sendo apresentada
  • Operável
    • Formulários de interface, controlos, e navegação são operáveis
  • Compreensível
    • A informação e a operação da interface de utilizador devem ser compreensíveis para todos utilizadores.
  • Robusta
    • Os utilizadores devem ser capazes de acessar o conteúdo conforme o avanço das tecnologias

Iniciativa de Acessibilidade da Web - Aplicações de Internet Ricas em Acessibilidade (WAI-ARIA)

A WAI-ARIA do W3C fornece orientação sobre como construir conteúdo dinâmico e controlos de interface de utilizador avançados:

Recursos

Documentação

Tecnologias Assistivas

Testagem

Utilizadores

A Organização Mundial da Saúde estima que 15% da população mundial tem alguma forma de deficiência, 2-4% deles com severidade. Isto é estimado em 1 bilhão de pessoas mundialmente; tornando as pessoas com deficiências o maior grupo minoritário no mundo.

Existem uma grande gama de deficiência, que podem ser divididas aproximadamente em quatro categorias:

  • Visual - Estes utilizadores podem beneficiarem-se do uso de leitores de ecrã, ampliação de ecrã, controlo de contraste de ecrã, ou exibição de braille.
  • Auditiva - Estes utilizadores podem beneficiarem-se do legendamento, transcrições ou vídeo de linguagem gestual.
  • Motora - Estes utilizadores podem beneficiarem-se de uma gama de tecnologias assistivas para deficiências motoras: software de reconhecimento de voz, acompanhamento do olho, acesso de interruptor único, vara de mão, teclado adaptável ou outras tecnologias assistivas.
  • Cognitiva - Estes utilizadores podem beneficiarem-se de media complementar, organização estrutural do conteúdo, escrita clara e simples.

Consulte as seguintes ligações da WebAim para entenderes as necessidades dos utilizadores:

Acessibilidade has loaded