# Estilização de formulários com CSS puro (avançado)

> Estilize formulários HTML com CSS puro de forma avançada e profissional. Técnicas e seletores pouco conhecidos para forms modernos. Sem JavaScript!

URL: https://dpw.dev/css/estilizar-formulario-css-puro/  
Publicado em: 2024-05-10  
Categoria: css  
Autor: Tárcio Zemel

**Estilizar formulários HTML** sempre foi notoriamente difícil (e chato) de se fazer com CSS, mas existem vários seletores pouco usados ​​que ajudam de maneira significativa para **estilizar formulários com CSS puro**.

> Artigo baseado em [Advanced CSS-Only HTML Form Styling](https://www.jonathan-harrell.com/blog/advanced-css-only-form-styling/).

## :placeholder-shown

![Estilizar formulário com CSS puro: estilização feita com :placeholder-shown.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-placeholder-show.webp)

`:placeholder-shown` é relativamente novo e permite detectar se um placeholder está atualmente visível para o usuário. Isso pode ser útil em situações como ocultar e mostrar dinamicamente o label associado ao input.

Neste exemplo, o label é ocultado até que o usuário comece a digitar alguma coisa, ocultando assim o placeholder.

```html
<div class="form-group">
  <input type="text" id="dynamic-label-input" placeholder="Enter some text">
  <label for="dynamic-label-input">Enter some text</label>
</div>
```

```css
.form-group {
  padding-top: 1.5rem;
  position: relative;
}

label {
  opacity: 1;
  position: absolute;
  top: 0;
  transform: translateY(0);
  transition: all 0.2s ease-out;
}

input:placeholder-shown + label {
  opacity: 0;
  transform: translateY(1rem);
}
```

Observe que, para que este técnica funcione, o label deve vir _depois_ do input. Mas também seria possível inverter a ordem com o input e fazer a estilização com `:has()` da seguinte forma:

```css
:has(input:placeholder-shown) label {
  opacity: 0;
  transform: translateY(1rem);
}
```

Se ainda não conhece o seletor `:has()`, confira nosso vídeo:

[Vídeo no YouTube](https://www.youtube.com/watch?v=Ia_4XdisCGQ)

## :required

![Estilizar formulário com CSS puro: estilização feita com :required.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-required.webp)

O seletor `:required` para indicar que um input possui o atributo `required` (obrigatório).

Comumente, isso seria feito com JavaScript, mas este exemplo demonstra uma abordagem de estilização de formulário com CSS puro.

```html
<label for="required-input">Required input</label>
<input type="text" id="required-input" required>
<span class="help-text"></span>
```

```css
input:required + .help-text::before {
  content: '* Required';
}
```

## :optional

![Estilizar formulário com CSS puro: estilização feita com :optional.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-optional.webp)

O seletor `:optional` faz o oposto de `:required`, servindo para estilizar inputs de formulário que não sejam obrigatórios.

Imaginando uma estrutura HTML semelhante à do exemplo anterior, o CSS ficaria:

```css
input:optional + .help-text::before {
  content: '* Optional';
}
```

## :disabled

![Estilizar formulário com CSS puro: estilização feita com :disabled.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-disabled.webp)

Como a maioria deve saber, `:disabled` é essencial para mostrar se um input está desabilitado ou não.

Ele é familiar para a maioria dos devs, mas, ainda assim, é importante ser citado em um artigo sobre estilização de formulários com CSS puro.

```css
input:disabled {
  background-color: var(--gray-lightest);
  border-color: var(--gray-lighter);
  color: var(--gray-light);
}
```

## :read-only

![Estilizar formulário com CSS puro: estilização feita com :read-only.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-read-only.webp)

Um input com o atributo `readonly` deve transmitir um significado ligeiramente diferente (portanto, uma estilização diferente) de um input desabilitado. Felizmente, existe o seletor `:read-only` para ajudar com isso.

```html
<input type="text" value="Read-only value" readonly>
```

```css
input:read-only {
  border-color: var(--gray-lighter);
  color: var(--gray);
  cursor: not-allowed;
}
```

## :valid

![Estilizar formulário com CSS puro: estilização feita com :valid.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-valid.webp)

Embora grande parte da validação de formulários seja feita com JavaScript, é possível aproveitar as vantagens da validação de formulário nativas de HTML e estilizar com CSS puro.

O seletor `:valid` oferece a oportunidade de se estilizar qualquer input que passou pelas regras de validação nativas do navegador.

Por exemplo, é possível usar `background-image` para exibir uma imagem de check, indicando que um campo passou pela validação.

```css
input:valid {
  background-image: url('data:image/svg+xml,...');
  border-color: var(--color-primary);
}
```

## :invalid

![Estilizar formulário com CSS puro: estilização feita com :invalid.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-invalid.webp)

Este seletor `:invalid` verifica se uma entrada não está passando pelas regras de validação nativas do navegador (por exemplo, se uma entrada de e-mail não contém um e-mail real).

É possível exibir uma imagem, como no exemplo anterior:

```css
input:invalid {
  background-image: url('data:image/svg+xml,...');
  border-color: var(--color-error);
}
```

Ou personalizar algumas mensagens de validação para cada tipo de input usando marcação auxiliar e pseudo-elementos.

```html
<label for="invalid-email">Invalid input</label>
<input type="email" id="invalid-email" value="notanemail">
<span class="help-text"></span>
```

```css
input[type='email']:invalid + .help-text::before {
  content: 'You must enter a valid email.'
}
```

## :in-range/:out-of-range

![Estilizar formulário com CSS puro: estilização feita com :in-range e :out-of-range.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-in-range-out-of-range.webp)

Os seletores `:in-range` e `:out-of-range` detectam se o valor de um input numérico está dentro dos valores `min` e `max` especificados ou não.

```html
<label for="out-of-range-input">Out-of-range input</label>
<input
  type="number"
  id="out-of-range-input"
  min="1"
  max="10"
  value="12"
>
<span class="help-text">(value must be between 1 and 10)</span>
```

```css
input:out-of-range + .help-text::before {
  content: 'Out of range';
}
```

## :checked

![Estilizar formulário com CSS puro: estilização feita com :checked.](/images/blog/estilizar-formulario-css-puro/estilizar-formularios-css-checked.webp)

A maioria dos devs está familiarizada com o seletor `:checked`, que permite aplicar estilos personalizados a checkboxes e radios quando marcados.

Ele torna possível realizar estilização de formulários com CSS puro de muitas maneiras: com elementos auxiliares, usando seletores avançados, `:has()` etc.

```html
<div class="checkbox">
  <input type="checkbox"/>
  <label>Option</label>
</div>
```

```css
&:checked + label::before {
  background-color: var(--color-primary);
}

&:checked + label::after {
  border: solid white;
  border-width: 0 2px 2px 0;
  content: '';
  display: block;
  height: 0.5rem;
  left: 0.375rem;
  position: absolute;
  top: 0.2rem;
  transform: rotate(45deg);
  width: 0.25rem;
}
```

## Aproveite recursos nativos para estilizar formulários com CSS puro

A **estilização de formulários com CSS puro** é conhecida e aproveitada por muitos devs. Aliás, é altamente indicado que você também faça uso desses recursos.

Afinal, o próprio HTML e CSS evoluíram (e evoluem) para fornecerem recursos para que interações e estilizações nativos possam ser usados da melhor maneira possível.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
