1. Antes de começar

Os usuários indicam muitas preferências nos dispositivos atualmente. Eles querem que o sistema operacional e os apps tenham a aparência e a sensação de serem deles. As interfaces adaptáveis ao usuário são aquelas que estão prontas para usar essas preferências e melhorar a experiência do usuário, fazendo com que ele se sinta mais em casa, como se fosse dele. Se feito corretamente, o usuário talvez nunca saiba que a experiência do usuário está se adaptando ou já se adaptou.
Preferências do usuário
A escolha do hardware do dispositivo é uma preferência, o sistema operacional é uma escolha, as cores do app e do sistema operacional são preferências, e os idiomas dos documentos do app e do sistema operacional são preferências. A quantidade de preferências de um usuário só aumenta. Uma página da Web não pode acessar tudo, e por um bom motivo.
Confira alguns exemplos de preferências do usuário que podem ser usadas pelo CSS:
- Tamanho da janela de visualização do dispositivo
- Orientação do dispositivo (retrato | paisagem)
- Tamanho da fonte
- On-line / off-line
- Qualidade da rede
- Esquema de cores (claro | escuro)
- Animações da interface (ativadas | reduzidas)
- Qualidade da entrada (mouse | toque | stylus)
- Direção do documento e modo de escrita (da esquerda para a direita, de cima para baixo e muito mais)
- Modo de exibição (tela cheia | independente | interface mínima | navegador)
Confira alguns exemplos de preferências do usuário em breve no CSS:
- Dados reduzidos / Modo Lite
- Intervalo de cores
- Contraste (diminuir | aumentar | reduzir)
- Cores (força as cores do usuário na página)
- Transparência (ativada | reduzida)
Consultas de mídia
O CSS e a Web permitem adaptação e capacidade de resposta por meio de consultas de mídia, uma condição declarativa que contém um conjunto de estilos se essa condição for verdadeira. A mais comum é uma condição no tamanho da janela de visualização do dispositivo: se o tamanho for menor que 800 pixels, aqui estão alguns estilos melhores para esse caso.
Adaptável ao usuário
Uma interface não adaptável é aquela que não muda nada quando um usuário a visita, oferecendo essencialmente uma experiência para todos sem capacidade de ajuste. Uma interface adaptável ao usuário pode ter cinco aparências e estilos diferentes para cinco usuários diferentes. A funcionalidade é a mesma, mas a estética é melhor percebida, e a usabilidade da interface é mais fácil para os usuários que podem ajustar a UI.
Pré-requisitos
- Conhecimento de HTML e CSS
- Conhecimento de ferramentas para desenvolvedores, como as Ferramentas para desenvolvedores do Chrome
O que você vai criar
Neste codelab, você vai criar um formulário adaptável ao usuário que se adapta ao seguinte:
- A preferência de esquema de cores do sistema, oferecendo um esquema de cores claro e escuro para os controles de formulário e os elementos da interface ao redor
- As preferências de movimento do sistema oferecendo vários tipos de animações
- Viewports de dispositivos pequenos e grandes para oferecer experiências em dispositivos móveis e computadores
- Vários tipos de entrada, como teclado, leitor de tela, toque e mouse
- Qualquer idioma e modo de leitura/gravação

O que você vai aprender
Neste codelab, você vai aprender sobre recursos da Web modernos para ajudar a criar um formulário adaptável ao usuário. Você vai aprender a:
- Criar temas claro e escuro
- Criar formulários animados e acessíveis
- Formulários responsivos de layout
- Usar unidades relativas e propriedades lógicas

Este codelab é focado em interfaces adaptáveis ao usuário. Conceitos e blocos de códigos sem relevância não serão abordados. Eles são incluídos somente para você copiar e colar.
O que é necessário
- Google Chrome 89 e versões mais recentes ou seu navegador preferido

2. Começar a configuração
Buscar o código
Tudo o que você precisa para este projeto está em um repositório do GitHub. Para começar, abra o código no ambiente de desenvolvimento de sua preferência. Como alternativa, crie um fork deste Codepen e trabalhe a partir dele.
Recomendado: use o Codepen
- Abra uma nova guia do navegador.
- Acesse https://codepen.io/argyleink/pen/abBMeeq.
- Se você não tiver uma conta, crie uma para salvar o trabalho.
- Clique em Bifurcar.
Alternativa: trabalhar localmente
Se você quiser baixar o código e trabalhar localmente, precisará ter o Node.js versão 12 ou mais recente e um editor de código configurado e pronto para uso.
Usar o Git
- Acesse https://github.com/argyleink/Google-IO-2021-Workshop_User-Adaptive-Interfaces
- Clone o repositório em uma pasta.
- A ramificação padrão é
beginning.
Usar arquivos
- Descompacte o arquivo ZIP baixado em uma pasta.
Executar o projeto
Use o diretório do projeto estabelecido em uma das etapas acima e faça o seguinte:
- Execute
npm installpara instalar as dependências necessárias para executar o servidor. - Execute
npm startpara iniciar o servidor na porta 3000. - Abra uma nova guia do navegador.
- Acesse http://localhost:3000.
Sobre o HTML
Esta lição vai abordar os aspectos do HTML usados para oferecer suporte à interatividade adaptável ao usuário. Este workshop tem um foco específico em CSS. O HTML fornecido vale a pena ser revisado se você não tiver experiência na criação de formulários ou sites. As escolhas de elementos HTML podem ser cruciais quando se trata de acessibilidade e layout.
Quando você estiver pronto para começar, este será o esqueleto do que você vai transformar em uma experiência do usuário dinâmica e adaptável.

3. Interações adaptáveis
Ramificação do Git: beginning
Ao final desta seção, o formulário de configurações vai se adaptar a:
- Gamepad + teclado
- Mouse e toque
- Leitor de tela ou tecnologia adaptativa semelhante
Atributos para o HTML
O HTML fornecido no código-fonte é um ótimo ponto de partida porque já foram escolhidos elementos semânticos para ajudar a agrupar, ordenar e rotular as entradas do formulário.
Os formulários geralmente são um ponto de interação fundamental para uma empresa. Por isso, é importante que eles se adaptem aos vários tipos de entrada que a Web pode facilitar. Por exemplo, é importante ter um formulário que possa ser usado em dispositivos móveis com toque. Nesta seção, antes do layout e do estilo, você garante a usabilidade da entrada adaptável.
Agrupamento de entradas
O elemento <fieldset> no HTML é usado para agrupar entradas e controles semelhantes. No formulário, você tem dois grupos, um para volume e outro para notificações. Isso é importante para a experiência do usuário, já que permite pular seções inteiras.
Como ordenar elementos
A ordem dos elementos é lógica. Isso é importante para a experiência do usuário, já que a ordem da experiência visual é a mesma ou semelhante para tecnologias de gamepad, teclado ou leitor de tela.
Interação com o teclado
Os usuários da Web se acostumaram a navegar pelos formulários com a tecla Tab, o que felizmente o navegador faz se você fornecer os elementos HTML esperados. O uso de elementos como <button>, <input>, <h2> e <label> se torna automaticamente um destino de teclado ou leitor de tela.

O vídeo acima mostra como a tecla Tab e as setas podem navegar pela interface e fazer mudanças. O contorno azul, no entanto, é muito apertado em torno dos elementos de entrada. Adicione os seguintes estilos para dar um pouco de espaço a essa interação.
style.css
input {
outline-offset: 5px;
}
O que testar
- Analise os elementos HTML usados em
index.html. - Clique na página de demonstração no navegador.
- Pressione as teclas
tabeshift+tabpara mover o foco do elemento pelo formulário. - Use o teclado para mudar os valores dos controles deslizantes e das caixas de seleção.
- Conecte um controle de gamepad Bluetooth e mova o foco do elemento pelo formulário.
Interação com o mouse
Os usuários da Web se acostumaram a interagir com formulários usando o mouse. Tente usar o mouse no formulário. Sliders e caixas de seleção funcionam, mas você pode fazer melhor. Essas caixas de seleção são muito pequenas para um clique do mouse.

Veja como você recebe dois recursos de experiência do usuário para conectar seus rótulos e as entradas deles.
O primeiro recurso é ter opções para interagir, e o rótulo é muito mais fácil de segmentar com um mouse do que um pequeno quadrado.
O segundo recurso é saber exatamente para qual entrada um rótulo é destinado. Sem CSS, é muito difícil determinar qual rótulo corresponde a qual caixa de seleção, a menos que você forneça alguns atributos.
Essa conexão explícita também melhora a experiência dos leitores de tela, que serão abordados na próxima seção.
Não associado:não há atributos conectando os elementos.
<input type="checkbox">
<label>...</label>
Associados:atributos que conectam os elementos
<input type="checkbox" id="voice-notifications" name="voice-notifications">
<label for="voice-notifications">...</label>
O HTML fornecido já atribuiu todas as entradas e rótulos. Se esse for um conceito novo para você, vale a pena investigar mais.
O que testar
- Passe o cursor sobre um rótulo e observe o destaque da caixa de seleção.
- Investigue um elemento de rótulo com as Ferramentas para desenvolvedores do Chrome para visualizar a área de superfície clicável que pode selecionar a caixa de seleção.
Interação com leitores de tela
A tecnologia adaptativa pode interagir com esse formulário e, com alguns atributos HTML, tornar a experiência do usuário mais tranquila.

Para usuários que navegam no formulário atual com um leitor de tela no Chrome, há uma parada desnecessária no elemento <picture> (não específico do Chrome). Um usuário com um leitor de tela provavelmente está usando o recurso por causa de uma deficiência visual. Portanto, parar em uma imagem não é útil. É possível ocultar elementos dos leitores de tela com um atributo.
index.html
<picture aria-hidden="true">
Agora, os leitores de tela ignoram o elemento puramente visual.

O elemento de controle deslizante input[type="range"] tem um atributo ARIA especial: aria-labelledby="media-volume". Isso fornece instruções especiais para o leitor de tela usar e melhorar a experiência do usuário.
O que testar
- Use a tecnologia de leitor de tela do sistema operacional para mover o foco pelo formulário.
- Baixe e teste alguns softwares de leitor de tela no formulário.
4. Layouts adaptáveis
Ramificação do Git : layouts
Ao final desta seção, a página de configurações vai:
- Crie um sistema de espaçamento com propriedades personalizadas e unidades relativas do usuário.
- Escreva grade CSS para alinhamento e espaçamento flexíveis e responsivos
- Use propriedades lógicas para layouts adaptáveis internacionalmente
- Escreva consultas de mídia para adaptar layouts compactos e espaçosos

Espaçamento
Uma chave para um layout agradável é uma paleta limitada de opções de espaçamento. Isso ajuda o conteúdo a encontrar alinhamentos e harmonias naturais.
Propriedades personalizadas
Este workshop se baseia em um conjunto de sete tamanhos de propriedades personalizadas.
- Coloque estes elementos na parte de cima de
style.css:
style.css
:root {
--space-xxs: .25rem;
--space-xs: .5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
--space-xxl: 6rem;
}
A nomenclatura está próxima da linguagem que as pessoas usariam entre si para descrever o espaço. Você também usa unidades rem exclusivamente para dimensionamento legível de unidades inteiras que se adaptam e consideram a preferência do usuário.
Estilos de página
Em seguida, defina alguns estilos de documento, remova as margens dos elementos e defina a fonte como uma boa sans-serif.
- Adicione o seguinte a
style.css:
style.css
* {
box-sizing: border-box;
margin: 0;
}
html {
block-size: 100%;
}
body {
min-block-size: 100%;
padding-block-start: var(--space-xs);
padding-block-end: var(--space-xs);
}
Essa é a primeira vez que você usa as propriedades personalizadas de espaçamento. Sua jornada no espaço começa agora.
Tipografia
A fonte desse layout é adaptativa. A palavra-chave system-ui usa a fonte de interface que o sistema operacional do usuário considera ideal.
body {
font-family: system-ui, sans-serif;
}
h1,h2,h3 {
font-weight: 500;
}
small {
line-height: 1.5;
}
Os estilos para h1, h2 e h3 são pequenos e estilísticos. No entanto, o elemento small precisa do line-height adicional para quando o texto é quebrado. Caso contrário, ele vai ficar muito amontoado.
Propriedades lógicas
Observe que o padding em body está usando propriedades lógicas (block-start, block-end) para especificar o lado. As propriedades lógicas serão usadas extensivamente no restante do codelab. Assim como uma unidade rem, eles se adaptam a um usuário. Esse layout pode ser traduzido para outro idioma e definido para a escrita natural e as direções de documentos a que o usuário está acostumado no idioma nativo. As propriedades lógicas desbloqueiam o suporte para isso com apenas uma definição de espaço, direção ou alinhamento.

Grid e flexbox já são relativos ao fluxo, ou seja, os estilos escritos para um idioma serão contextuais e aplicados adequadamente a outros. Direcionalidade adaptativa: o conteúdo flui de acordo com a direcionalidade do documento.
Com as propriedades lógicas, você alcança mais usuários com menos estilos para escrever.
Layouts de grade CSS
A propriedade CSS grid é uma ferramenta de layout poderosa com muitos recursos para lidar com tarefas complexas. Você vai criar alguns layouts de grade simples e um layout complexo. Você também vai trabalhar de fora para dentro, de layouts macro a micro. Suas propriedades personalizadas de espaçamento vão se tornar essenciais, não apenas como valores de padding ou margem, mas também como tamanhos de coluna, raios de borda e muito mais.
Esta é uma captura de tela do Chrome DevTools sobrepondo cada layout de grade CSS de uma vez:

- Adicione cada um dos seguintes estilos a
style.css:
<main>
main {
display: grid;
gap: var(--space-xl);
place-content: center;
padding: var(--space-sm);
}
Por padrão, a grade coloca cada elemento filho em uma linha própria, o que é ótimo para empilhar elementos. Ele também tem o benefício adicional de usar gap. Antes, você definiu margin: 0 em todos os elementos com o seletor *, o que agora é importante ao usar gap para o espaçamento. O Gap não é apenas um lugar para gerenciar o espaço em um contêiner, mas também o fluxo relativo.
<form>
form {
max-width: 89vw;
display: grid;
gap: var(--space-xl) var(--space-xxl);
align-items: flex-start;
grid-template-columns:
repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
}
Esse é o layout de grade mais complicado do design, mas representa o aspecto responsivo mais interessante:
max-widthfornece um valor para o algoritmo de layout usar ao decidir o tamanho que ele pode ter.- O
gapestá usando propriedades personalizadas e transmitindo umrow-gapdiferente decolumn-gap. align-itemsé definido comoflex-startpara não esticar as alturas dos itens.grid-template-columnstem uma sintaxe complexa, mas o objetivo é simples: mantenha as colunas com35chde largura e nunca menos que10ch. Coloque as coisas em colunas se houver espaço. Caso contrário, as linhas são boas.
- Teste redimensionar o navegador. Assista enquanto o formulário se recolhe em linhas em uma pequena janela de visualização, mas flui em novas colunas se houver espaço, adaptando-se sem consultas de mídia. Essa estratégia de estilos responsivos sem consultas de mídia é particularmente útil para componentes ou layouts centrados no conteúdo.
<section>
section {
display: grid;
gap: var(--space-md);
}
Cada seção precisa ser uma grade de linhas com espaço médio entre os elementos filhos.
<header>
header {
display: grid;
gap: var(--space-xxs);
}
Cada cabeçalho precisa ser uma grade de linhas com espaço extra extra pequeno entre os elementos filhos.
<fieldset>
fieldset {
padding: 0;
display: grid;
gap: 1px;
border-radius: var(--space-sm);
overflow: hidden;
}
Esse layout é responsável por criar uma aparência semelhante a um card e agrupar as entradas. overflow: hidden e gap: 1px ficam claros quando você adiciona cor na próxima seção.
.fieldset-item
.fieldset-item {
display: grid;
grid-template-columns: var(--space-lg) 1fr;
gap: var(--space-md);
padding: var(--space-sm) var(--space-md);
}
Esse layout é responsável por centralizar o ícone e a caixa de seleção com os rótulos e controles associados. A primeira coluna do modelo de grade, var(--space-lg), cria uma coluna mais larga que o ícone, para que um elemento filho tenha onde ser centralizado.
Este layout demonstra quantas decisões de design já foram tomadas nas propriedades personalizadas. O padding, os gaps e uma coluna foram dimensionados dentro da harmonia do sistema usando valores que você já definiu.
.fieldset-item <picture>
.fieldset-item > picture {
block-size: var(--space-xl);
inline-size: var(--space-xl);
clip-path: circle(50%);
display: inline-grid;
place-content: center;
}
Esse layout é responsável pelas configurações, pelo tamanho do círculo do ícone, pela criação de um formato circular e pela centralização de uma imagem dentro dele.
<picture> & [checkbox] alinhamento
.fieldset-item > :is(picture, input[type="checkbox"]) {
place-self: center;
}
Esse layout isola o centralização para elementos de imagem e caixa de seleção usando o :is pseudoseletor.
- Substitua o seletor
picture > svgpor.fieldset-item svgdesta forma:
.fieldset-item <svg>
.fieldset-item svg {
block-size: var(--space-md);
}
Isso define o tamanho do ícone SVG como um valor do sistema de tamanho.
.sm-stack
.sm-stack {
display: grid;
gap: var(--space-xs);
}
Essa classe utilitária é para os elementos de rótulo da caixa de seleção espaçarem o texto de ajuda da caixa de seleção.
input[type="checkbox"]
input[type="checkbox"] {
inline-size: var(--space-sm);
block-size: var(--space-sm);
}
Esses estilos aumentam o tamanho de uma caixa de seleção usando valores do nosso conjunto de espaçamento.
O que testar
- Abra as Ferramentas para desenvolvedores do Chrome e encontre os selos de grade no HTML do painel Elementos. Clique neles para ativar as ferramentas de depuração.
- Abra as Ferramentas para desenvolvedores do Chrome e passe o cursor sobre uma lacuna no painel Estilos.
- Abra as Ferramentas para desenvolvedores do Chrome, acesse o painel Estilos e mude de Estilos para Layouts. Explore essa área alternando as configurações e ativando os layouts.
Consultas de mídia
O CSS a seguir adapta os estilos com base no tamanho e na orientação da janela de visualização com a intenção de ajustar o espaçamento ou a disposição para que sejam ideais considerando o contexto da janela de visualização.
<main>
@media (min-width: 540px) {
main {
padding: var(--space-lg);
}
}
@media (min-width: 800px) {
main {
padding: var(--space-xl);
}
}
Essas duas consultas de mídia dão mais padding a main à medida que mais espaço de viewport fica disponível. Isso significa que ele começa com um padding compacto e pequeno, mas fica cada vez mais espaçoso à medida que mais espaço fica disponível.
<form>
form {
--repeat: auto-fit;
grid-template-columns:
repeat(var(--repeat), minmax(min(10ch, 100%), 35ch));
}
@media (orientation: landscape) and (min-width: 640px) {
form {
--repeat: 2;
}
}
O formulário já era responsivo ao tamanho da janela de visualização com auto-fit, mas, ao testar em um dispositivo móvel, girar o dispositivo para a orientação paisagem não coloca os dois grupos de formulários lado a lado. Adapte a esse contexto de paisagem com uma consulta de mídia orientation e uma verificação da largura da janela de visualização. Agora, se o dispositivo estiver no modo paisagem e tiver pelo menos 640 pixels de largura, force duas colunas trocando a propriedade personalizada --repeat por um número em vez da palavra-chave auto-fit.
.fieldset-item
@media (min-width: 540px) {
.fieldset-item {
grid-template-columns: var(--space-xxl) 1fr;
gap: var(--space-xs);
padding: var(--space-md) var(--space-xl) var(--space-md) 0;
}
}
Essa consulta de mídia é outra expansão de espaçamento quando há mais espaço de janela de visualização disponível. O modelo de grade expande a primeira coluna usando uma propriedade personalizada maior (var(--space-xxl)) no modelo. O padding também é aumentado para propriedades personalizadas maiores.
O que testar
- Expanda e contraia o navegador e observe como o espaço se ajusta.
- Visualizar em um dispositivo móvel
- Visualizar em um dispositivo móvel no modo paisagem
5. Cor adaptativa
Ramificação do Git : colors
Ao final desta seção, o formulário de configurações vai:
- Adaptar às preferências de cores claras e escuras
- Ter um esquema de cores derivado de um hexadecimal da marca
- Ter cores acessíveis

HSL
Na próxima seção, você vai criar um sistema de cores com HSL para ajudar a criar um tema claro e tema escuro. Ele é criado com base neste conceito principal do CSS: calc().
HSL significa matiz, saturação e brilho. A tonalidade é um ângulo, como um ponto em um relógio, enquanto a saturação e a luminosidade são porcentagens. O calc() consegue fazer cálculos com porcentagens e ângulos. É possível fazer cálculos de luminosidade e saturação nessas porcentagens em CSS. Combine cálculos de canais de cores com propriedades personalizadas para ter um esquema de cores moderno e dinâmico em que as variantes são calculadas com base em uma cor primária, ajudando você a evitar o gerenciamento de várias cores no código.

Propriedades personalizadas
Nesta seção, você vai criar um conjunto de propriedades personalizadas para usar no restante dos seus estilos. Semelhante ao conjunto de espaçamento que você fez antes na tag :root, você vai adicionar cores.
Suponha que a cor da marca do seu app seja #0af. Sua primeira tarefa é converter esse valor de cor hexadecimal em um valor de cor HSL: hsl(200 100% 50%). Essa conversão revela os canais de cores da sua marca em HSL, que você pode usar calc() para calcular várias cores de suporte da marca.
Cada um dos blocos de código a seguir nesta seção precisa ser adicionado ao mesmo seletor :root.
Brand channels
:root {
--hue: 200;
--saturation: 100%;
--lightness: 50%;
}
Os três canais HSL foram extraídos e colocados em propriedades personalizadas próprias.
- Use as três propriedades no estado em que se encontra e recrie a cor da marca.
Marca
:root {
--brand: hsl(
var(--hue)
calc(var(--saturation) / 2)
var(--lightness)
);
}
Como o esquema de cores é escuro por padrão, é recomendável dessaturar as cores para uso em superfícies escuras. Caso contrário, elas podem vibrar aos olhos ou ficar inacessíveis. Para dessaturar a cor da sua marca, use a tonalidade e a luminosidade como estão, mas corte a saturação pela metade com alguma divisão: calc(var(--saturation) / 2). Agora a cor da sua marca está no tema, mas dessaturada para uso.
Texto
:root {
--text1: hsl(var(--hue) 15% 85%);
--text2: hsl(var(--hue) 15% 65%);
}
Para o texto de leitura no tema escuro, use o matiz da marca como base, mas crie cores quase brancas com ele. Muitos usuários vão achar que o texto é branco, mas ele é azul-claro. Manter-se dentro da tonalidade é uma ótima maneira de criar harmonia no design. --text1 é 85% branco e --text2 é 65% branco, e ambos têm pouca saturação.
- Depois de adicionar o código ao projeto, abra as Ferramentas para desenvolvedores do Chrome e mude os valores do canal. Sinta como o HSL e os canais dele interagem entre si. Talvez você queira mais ou menos saturação.
Superfície
:root {
--surface1: hsl(var(--hue) 10% 10%);
--surface2: hsl(var(--hue) 10% 15%);
--surface3: hsl(var(--hue) 5% 20%);
--surface4: hsl(var(--hue) 5% 25%);
}
O texto é muito claro porque as superfícies ficam escuras no modo escuro. Quando as cores do texto usavam valores de luminosidade altos (85% ou mais), as superfícies usam valores mais baixos (30% ou menos). Ter um intervalo saudável entre os intervalos de luminosidade entre a superfície e o texto ajuda a garantir cores acessíveis para os usuários lerem.
- Observe como as cores começam no cinza mais escuro com 10% de luminosidade e 10% de saturação e depois ficam menos saturadas à medida que ficam mais claras. Cada nova superfície é 5% mais clara que a anterior. A saturação também é reduzida um pouco nas superfícies mais claras. Tente colocar todas as superfícies com 10% de saturação. Você gosta mais ou menos?
Tema claro
Com um conjunto adequado de cores de texto e superfície especificando o tema escuro, é hora de se adaptar a uma preferência de tema claro atualizando as propriedades personalizadas de cor em uma consulta de mídia prefers-color-scheme.
Você vai usar a mesma técnica de manter uma grande diferença nos valores de luminosidade entre as superfícies e as cores do texto para manter um bom contraste entre as cores.
Marca
@media (prefers-color-scheme: light) {
:root {
--brand: hsl(
var(--hue)
var(--saturation)
var(--lightness)
);
}
}
Primeiro, a cor da marca. É necessário restaurar a saturação para a potência máxima.
Texto
@media (prefers-color-scheme: light) {
:root {
--text1: hsl(
var(--hue)
var(--saturation)
10%
);
--text2: hsl(
var(--hue)
calc(var(--saturation) / 2)
30%
);
}
}
Assim como o tema escuro tinha cores de texto azul-claro, no tema claro as cores de texto são azul-escuro. Ver 10% e 30% como valores de luminosidade para a cor HSL indica que essas cores são escuras.
Surface
@media (prefers-color-scheme: light) {
:root {
--surface1: hsl(var(--hue) 20% 90%);
--surface2: hsl(var(--hue) 10% 99%);
--surface3: hsl(var(--hue) 10% 96%);
--surface4: hsl(var(--hue) 10% 85%);
}
}
Essas cores de superfície são as primeiras a quebrar padrões. O que parecia razoável e linear até agora está quebrado. O bom é que você pode brincar com as combinações de cores do tema claro HSL aqui mesmo no código e ajustar o brilho e a saturação para criar um esquema de cores claro que não seja muito frio ou azul.
Usar o sistema de cores
Agora que as cores estão definidas, é hora de usá-las. Você tem uma cor de marca de destaque que chama a atenção, duas cores de texto e quatro cores de superfície.
- Para as seções de código a seguir, encontre o seletor correspondente e adicione o CSS de cor ao bloco de código atual.
<body>
body {
background: var(--surface1);
color: var(--text1);
}
As cores primárias da página são as primeiras cores de superfície e texto que você criou, o que também coloca a quantidade padrão de contraste no máximo. O alternância entre claro e escuro pode começar a ser testada!
<fieldset>
fieldset {
border: 1px solid var(--surface4);
background: var(--surface4);
}
Esse é o elemento semelhante a um card do seu design. A borda de 1 pixel e a lacuna de 1 pixel têm a mesma cor e representam a superfície atrás de cada .fieldset-item. Isso cria uma boa harmonia visual e é fácil de manter.
.fieldset-item
.fieldset-item {
background: var(--surface3);
}
Cada entrada de formulário está em uma superfície própria. Esperamos que você esteja entendendo como eles se juntam e como as variações de luminosidade se sobrepõem.
.fieldset-item > picture
.fieldset-item > picture {
background: var(--surface4);
}
Essa é uma escolha estilística para mostrar o formato circular ao redor do ícone. Isso vai ficar mais claro quando você adicionar interações na próxima seção.
.fieldset-item svg
.fieldset-item svg {
fill: var(--text2);
}
Os ícones no formulário estão definidos para usar o texto alternativo --text2. Designs em que os ícones preenchidos são um pouco mais claros do que o texto evitam que eles pareçam muito pesados.
.fieldset-item:focus-within svg
.fieldset-item:focus-within svg {
fill: var(--brand);
}
Esse seletor corresponde ao elemento de contêiner de entrada quando uma das entradas internas está sendo interagida e segmenta o SVG para destacar com a cor de destaque da sua marca. Isso fornece um feedback de UX agradável do formulário, em que a interação com as entradas destaca a iconografia relevante.
<small>
small {
color: var(--text2);
}
É um texto pequeno. Ele precisa ser um pouco mais discreto em comparação com cabeçalhos e parágrafos (conteúdo principal).
Controles de formulário escuros
:root {
color-scheme: dark light;
}
Esse toque final informa ao navegador que a página é compatível com temas claros e escuros. O navegador nos recompensa com controles de formulário escuros.
6. Animação adaptativa
Ramificação do Git : animations
Ao final desta seção, a página de configurações vai:
- Adaptar às preferências de movimento do usuário
- Responder à interação do usuário

Movimento reduzido x sem movimento
A preferência do usuário encontrada no sistema operacional para movimento não oferece um valor de nenhuma animação. A opção é reduzir o movimento. Animações de transição gradual, transições de cor e muito mais ainda são desejáveis para usuários que preferem movimento reduzido.
Nessa página de configurações, não há muito movimento na tela. O movimento é mais um efeito de escala, como se o elemento estivesse viajando em direção ao usuário. É tão trivial ajustar o código CSS para acomodar o movimento reduzido que você reduz as transições de escalonamento.
Estilos de interação
<fieldset>
fieldset {
transition: box-shadow .3s ease;
}
fieldset:focus-within {
box-shadow: 0 5px 20px -10px hsl(0 0% 0% / 50%);
}
Quando um usuário interage com as entradas de um dos elementos que parecem um card <fieldset>, isso adiciona um efeito de elevação. A interface está empurrando um elemento para frente, ajudando o usuário a se concentrar enquanto o grupo de formulários contextuais é trazido para o usuário.
.fieldset-item
.fieldset-item {
transition: background .2s ease;
}
.fieldset-item:focus-within {
background: var(--surface2);
}
Quando o usuário interage com uma entrada, o plano de fundo da camada do item específico muda para uma cor de superfície destacada, outro recurso de interface útil para ajudar a chamar a atenção do usuário e sinalizar que a entrada está sendo recebida. Na maioria dos casos, não é necessário reduzir as transições de cores.
.fieldset-item > picture
@media (prefers-reduced-motion: no-preference) {
.fieldset-item > picture {
clip-path: circle(40%);
transition: clip-path .3s ease;
}
.fieldset-item:focus-within picture {
clip-path: circle(50%);
}
}
Confira uma animação clip-path que só é usada se o usuário não tiver preferências em relação à redução de movimento. O primeiro seletor e os estilos restringem o caminho de recorte circular em 10% e definem alguns parâmetros de transição. O segundo seletor e estilo aguardam a interação dos usuários com uma entrada e escalonam verticalmente o círculo do ícone. Um efeito sutil, mas elegante, quando está tudo bem.
7. Parabéns
Ramificação do Git : complete
Parabéns! Você criou uma interface adaptável ao usuário.
Agora você sabe as principais etapas necessárias para criar interfaces que se adaptam a vários cenários e configurações de usuários.