Atualize o estado do componente quando uma escolha precisar manter controles, texto e comportamento consistentes. Substitua o CSS quando quiser alterar apenas a apresentação. Este guia usa uma prévia local de blocos no Safari no Mac para mostrar como escolher e verificar as duas abordagens.
A tarefa do leitor é específica: modificar uma pequena página web que você criou para que os controles de forma permaneçam sincronizados enquanto a estilização decorativa continue fácil de editar. Aqui, estado do componente significa um objeto JavaScript gerenciado pela própria função de atualização da página. Não se pressupõe nenhum framework ou recurso de edição específico de um produto.
Quais alterações pertencem ao estado do componente?
Comece perguntando o que precisa permanecer em concordância após a alteração. Se selecionar um bloco redondo precisar atualizar uma caixa de seleção, a prévia e uma descrição escrita, atribua a essa escolha um único lugar responsável no estado. Em seguida, derive as três saídas dela. Esta é uma recomendação de implementação: ela explicita a relação entre uma escolha e os resultados exibidos.
Uma propriedade personalizada de CSS, como --tile-size, tem outra função. Ela fornece um valor às declarações que a referenciam com var(). As propriedades personalizadas participam da cascata e normalmente são herdadas; seu comportamento segue as regras de CSS mesmo quando o JavaScript as define. A especificação de propriedades personalizadas de CSS define esse contrato.
Use este guia de decisão antes de editar:
| Alteração solicitada | Local preferencial | Motivo neste exemplo |
|---|---|---|
| O leitor seleciona um bloco redondo ou quadrado | Estado do componente | A caixa de seleção, a descrição e a forma precisam concordar |
| O leitor escolhe o tamanho do bloco | Estado do componente, aplicado ao CSS | O controle deslizante, a descrição e as dimensões compartilham um valor |
| Cada bloco deve usar uma cor decorativa diferente | Declaração na folha de estilos | Nenhum valor selecionado ou texto precisa ser atualizado |
| A prévia precisa de mais espaço ao redor | Declaração na folha de estilos | Isso altera o layout ao redor do bloco |
| É necessária uma dimensão temporária durante a inspeção | Substituição local de CSS | É um experimento visual a ser removido depois |
A distinção depende da tarefa. Nesta prévia, a cor pertence ao CSS porque é uma decoração fixa. Se você adicionar depois um seletor de cor e uma descrição da cor selecionada, trate essa seleção como estado e aplique seu efeito visual. Evite criar dois valores editáveis de forma independente para a mesma escolha.
Os controles nativos também têm seu próprio estado. Para uma caixa de seleção, leia sua propriedade atual checked. O atributo HTML checked especifica seu estado marcado padrão e não acompanha as alterações feitas depois pelo usuário. Essa distinção está documentada na referência da propriedade de caixa de seleção do MDN.
Crie uma prévia autossuficiente no seu Mac
Use um editor de texto simples para salvar o documento completo abaixo como tile-preview.html e, em seguida, abra-o no Safari. Mantenha a extensão .html. O exemplo inclui seu CSS e JavaScript, usa fontes do sistema e desenha um bloco geométrico simples sem recursos externos.
A folha de estilos fica no cabeçalho do documento. O HTML define o elemento style como uma forma de incorporar CSS e distingue estilos internos autossuficientes de folhas de estilos que fazem referência a recursos adicionais. Manter este exemplo autossuficiente deixa explícitos os parâmetros de estilo. Consulte as seções sobre estilo e scripts do padrão HTML.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tile preview</title>
<style>
body {
font-family: system-ui, sans-serif;
margin: 2rem;
color: #222;
background: #fff;
}
label { display: block; margin-block: 1rem; }
.preview { padding: 24px; background: #eee; }
.tile {
width: 80px;
height: 80px;
border-radius: 0;
width: var(--tile-size, 80px);
height: var(--tile-size, 80px);
border-radius: var(--tile-radius, 0);
background-color: #547899;
}
</style>
</head>
<body>
<h1>Tile preview</h1>
<label>
<input id="round" type="checkbox"> Round tile
</label>
<label>
Tile size
<input id="size" type="range" min="40" max="160"
step="1" value="80">
</label>
<button id="reset" type="button">Reset choices</button>
<p id="summary"></p>
<div class="preview">
<div id="tile" class="tile" aria-hidden="true"></div>
</div>
<script>
const state = { rounded: false, size: 80 };
const round = document.getElementById('round');
const size = document.getElementById('size');
const summary = document.getElementById('summary');
const tile = document.getElementById('tile');
const reset = document.getElementById('reset');
function render() {
round.checked = state.rounded;
size.value = String(state.size);
tile.style.setProperty('--tile-size', `${state.size}px`);
tile.style.setProperty('--tile-radius', state.rounded ? '50%' : '0');
summary.textContent = `Tile A: ${state.rounded ? 'round' : 'square'}, ${state.size}px.`;
}
function update(patch) {
const next = { ...state, ...patch };
if (typeof next.rounded !== 'boolean' ||
!Number.isInteger(next.size) ||
next.size < 40 || next.size > 160) {
throw new RangeError('Use a boolean and a size from 40 to 160.');
}
Object.assign(state, next);
render();
}
round.addEventListener('change', () => {
update({ rounded: round.checked });
});
size.addEventListener('input', () => {
update({ size: Number(size.value) });
});
reset.addEventListener('click', () => {
update({ rounded: false, size: 80 });
});
render();
</script>
</body>
</html>
A interface de estilo usada aqui está documentada: element.style.setProperty() grava uma declaração em linha, incluindo uma propriedade personalizada. Os nomes das propriedades usam a grafia CSS, como --tile-size. Consulte a referência de setProperty do MDN.
Experimente selecionar Round tile, mover Tile size para outro valor e escolher Reset choices. As duas primeiras ações devem atualizar tanto a forma quanto a descrição; a redefinição deve restaurar um quadrado de 80 pixels. Neste programa, atribuir um campo em state por si só não chama render(). Encaminhe as alterações por update() para que a validação e a renderização ocorram juntas.
A lógica de atualização e renderização foi verificada no Node com controles simulados e um objeto de estilo simulado para valores iniciais, valores alterados, tamanhos inválidos e redefinição. Essas verificações foram aprovadas; elas não comprovam a renderização no navegador. Use as verificações visuais acima para validar o arquivo no Safari.
Quando você deve substituir uma declaração de CSS?
Para uma alteração decorativa duradoura, edite a folha de estilos salva. Por exemplo, altere background-color de .tile para outra cor CSS ou ajuste o preenchimento de .preview. Nenhuma das alterações exige um novo campo de estado neste programa, pois nenhuma representa uma escolha selecionada.
Para um experimento temporário, ative o inspetor do Safari em Safari → Settings… → Advanced → Show features for web developers. Abra Develop → Show Web Inspector ou pressione Option-Command-I. Essas são as etapas documentadas para Mac no guia do inspetor do WebKit.
Com o exemplo aberto, o trecho completo a seguir, executado no console, altera temporariamente a cor do bloco e depois fornece uma função que remove essa substituição:
const previewTile = document.getElementById('tile');
if (!previewTile) throw new Error('Open tile-preview.html first.');
previewTile.style.setProperty('background-color', '#8069a6');
function restoreTileColor() {
previewTile.style.removeProperty('background-color');
}
// Run restoreTileColor() when finished comparing colors.
Ao remover essa declaração em linha, a cascata restante volta a determinar a cor. Isso não exclui a declaração de cor da folha de estilos. O método de remoção está definido na referência de removeProperty do MDN. Para manter uma cor escolhida após recarregar este exemplo, edite e salve o código-fonte CSS.
Mantenha as substituições temporárias longe dos valores controlados pelo renderizador. Se você alterar manualmente --tile-size, a descrição continuará informando o valor do estado, e a próxima chamada de render() substituirá seu experimento. Altere o tamanho pelo controle ou pela função de atualização quando quiser que todo o componente concorde.
Por que uma substituição pode parecer não fazer nada?
Investigue o caminho do valor antes de aumentar a especificidade do seletor. Uma declaração pode ser válida e ainda assim perder na cascata, ou pode ter como alvo uma propriedade personalizada que a declaração vencedora já não usa.
- Confira o alvo. Confirme que selecionou o elemento que exibe a forma.
- Confira o valor de entrada. No exemplo, o tamanho precisa ser um número inteiro entre 40 e 160. Atualizações inválidas geram um erro antes de alterar o estado.
- Confira onde o valor é usado. As dimensões do bloco usam
var(--tile-size). Uma declaraçãowidthdireta e vencedora pode contornar esse valor para a largura, enquanto a altura continua a usá-lo. - Confira a precedência. Compare as declarações aplicáveis, a importância, as camadas e a especificidade.
- Confira a interação seguinte. Se a alteração desaparecer depois de mover um controle, verifique o que
render()grava.
Declarações em linha normais têm precedência sobre regras normais da folha de estilos do autor. No entanto, a importância, as animações e as transições afetam a ordem mais ampla. Uma declaração posterior não vence automaticamente, e um seletor mais específico não resolve todos os conflitos. O guia da cascata do MDN documenta essas condições.
Além disso, diferencie os valores em linha dos valores resolvidos. element.style expõe a estilização em linha; portanto, um valor em linha vazio não significa que o elemento não tenha estilo. getComputedStyle() lê os valores resolvidos depois da aplicação das folhas de estilos ativas. Consulte a referência de style do MDN e a referência de getComputedStyle.
Execute este trecho completo de diagnóstico no console da página de exemplo:
const inspectedTile = document.getElementById('tile');
if (!inspectedTile) throw new Error('Open tile-preview.html first.');
console.table({
inlineSizeToken: inspectedTile.style.getPropertyValue('--tile-size'),
inlineWidth: inspectedTile.style.getPropertyValue('width'),
resolvedWidth: getComputedStyle(inspectedTile).width,
resolvedHeight: getComputedStyle(inspectedTile).height
});
Logo após abrir o exemplo sem modificações, os valores esperados são um token de tamanho em linha de 80px, uma largura em linha vazia e dimensões resolvidas de 80px. Isso ilustra como uma propriedade personalizada em linha pode fornecer um valor a uma declaração da folha de estilos sem criar uma declaração em linha de width.
Quais limitações de navegador e recursos são relevantes?
O MDN indica que as propriedades personalizadas de CSS têm amplo suporte nos navegadores desde abril de 2017. Isso não comprova suporte em todos os navegadores mais antigos. O exemplo inclui declarações comuns de dimensão antes das declarações var(), para que o bloco mantenha uma aparência estática quando as propriedades personalizadas não estiverem disponíveis. Consulte a referência de propriedades personalizadas do MDN.
O fallback dentro de var(--tile-size, 80px) não oferece compatibilidade com um navegador incapaz de interpretar propriedades personalizadas. Tampouco valida todos os tokens fornecidos: um valor definido, como blue, não se torna uma largura válida apenas porque há um fallback. Essas limitações são explicadas no guia de propriedades personalizadas do MDN.
Se um navegador mais antigo visado não oferecer suporte a propriedades personalizadas, a alternativa compatível é alterar o renderizador para gravar declarações em linha comuns de width, height e border-radius com setProperty(). Mantenha a mesma validação de estado e sincronização dos controles. Isso altera o contrato de renderização, então remova gravações conflitantes do renderizador e verifique o navegador visado, em vez de presumir suporte idêntico.
Para esta prévia local, a escolha prática é clara: use o estado para as seleções de forma e tamanho, aplique essas escolhas por meio de um pequeno conjunto de parâmetros CSS e mantenha a decoração na folha de estilos. Após qualquer alteração, teste a interação com um controle e a redefinição. A prévia, os controles e a descrição devem continuar representando os mesmos valores selecionados.
Fontes
- CSS Custom Properties for Cascading Variables Module Level 1 — Grupo de Trabalho de CSS do W3C
- HTML Standard: The style element — WHATWG
- HTMLInputElement: checked property — MDN Web Docs
- CSSStyleDeclaration: setProperty() method — MDN Web Docs
- Enabling Web Inspector — WebKit
- CSSStyleDeclaration: removeProperty() method — MDN Web Docs
- Introduction to the CSS cascade — MDN Web Docs
- HTMLElement: style property — MDN Web Docs
- Window: getComputedStyle() method — MDN Web Docs
- Custom properties (--*): CSS variables — MDN Web Docs
- Using CSS custom properties (variables) — MDN Web Docs