Você não precisa de JavaScript para isso
(htmhell.dev)- Ao implementar recursos na web, é melhor considerar primeiro as tecnologias menos poderosas na ordem HTML, CSS e JavaScript, pois isso ajuda a reduzir falhas de carregamento e problemas de acessibilidade
- O JavaScript permite controlar diretamente o comportamento do navegador, mas, por exigir recursos extras e trazer possibilidade de erros, tende a excluir com mais facilidade usuários de teclado e de tecnologias assistivas
- Recursos que antes exigiam JavaScript, como switches com checkbox,
datalist,input type="color",details/summaryedialog, agora podem em grande parte ser feitos com funcionalidades nativas de HTML/CSS - Os recursos declarativos de HTML e CSS permitem que o navegador cuide do comportamento nativo, das preferências do usuário e da acessibilidade, oferecendo padrões melhores
- Mesmo que implementações familiares em JavaScript ainda funcionem, vale revisar periodicamente as alternativas modernas em HTML/CSS e, ao trocar, fazer também testes de acessibilidade
Regra do menor privilégio
- A regra do menor privilégio é um princípio de desenvolvimento web que diz para escolher a linguagem menos poderosa capaz de cumprir o objetivo
- Na web, isso normalmente é aplicado considerando primeiro HTML antes de CSS, e CSS antes de JavaScript
- JavaScript é a mais versátil das três tecnologias, mas também a mais custosa
- Pode quebrar
- Pode falhar ao carregar
- Exige recursos extras para download, parsing e execução
- Pode excluir com facilidade usuários de teclado e de tecnologias assistivas
- HTML e CSS funcionam de forma declarativa, ao contrário do JavaScript imperativo
- O desenvolvedor diz ao navegador o que quer, e o navegador escolhe como implementar
- O navegador pode escolher uma forma de processamento mais eficiente
- Quando o navegador lida com recursos de HTML/CSS, isso pode ser vantajoso em desempenho, comportamento nativo, respeito às preferências do usuário e acessibilidade
- Ainda assim, acessibilidade nem sempre é garantida automaticamente
Recursos que antes exigiam JavaScript
- Fabricantes de navegadores e autores de especificações vêm migrando para CSS e HTML recursos que até poucos anos atrás exigiam JavaScript
- A web mantém compatibilidade retroativa, então uma forma de implementação aprendida uma vez tende a permanecer na caixa de ferramentas e ser reutilizada
- Mesmo que você ache que certo recurso precisa de JavaScript, vale conferir de tempos em tempos se isso ainda é verdade para criar sites melhores
Switch customizado com checkbox
- Um switch customizado pode ser implementado com um checkbox nativo e CSS, em vez de
div, manipuladoronclicke estado interno - Ao colocar
<input type="checkbox">dentro de um<label>, o navegador associa os dois- Clicar em qualquer parte do rótulo alterna o checkbox
- Não é preciso um manipulador
onclickseparado
appearance: nonefaz o navegador parar de renderizar o controle de formulário padrão, permitindo estilização manual- Dá para estilizar o próprio
inputcomo fundo do switch ::beforepode ser usado como o ponto interno que alterna
- Dá para estilizar o próprio
- A pseudo-classe
:checkedpermite mudar a cor de fundo e a posição do::beforeconforme o estado marcado - Para usuários de teclado, é preciso indicação de foco
- Esconder o foco com
outline: nonenão é uma boa prática :focus-visiblepermite mostrar um anel de foco bonito apenas em interações por teclado- Com
outline-offset, dá para ajustar o contorno de foco para fora ou para dentro do elemento
- Esconder o foco com
input:focus { outline-color: transparent; }pode deixar o contorno transparente em situações normais e, em modo de alto contraste, fazê-lo reaparecer na cor escolhida pelo usuário- Você pode ver mais sobre modo de cores forçadas em forced colors explained
Autocompletar nativo com datalist
datalisté um recurso nativo do navegador de sugestão automática que mostra uma lista de opções enquanto o usuário digita- A estrutura é simples
- Coloque um
ide váriosoptiondentro do elementodatalist - Conecte-o ao
inputpelo atributolist
- Coloque um
- Quando o usuário digita, o navegador mostra um dropdown e filtra automaticamente as opções de acordo com o conteúdo inserido
- Como é um campo de entrada comum, também é possível digitar diretamente um valor que não esteja na lista
- Depois de selecionar o campo, o usuário pode navegar pela lista com as setas ou clicar no ícone de dropdown adicionado pelo navegador para ver todas as opções
Seletor de cores nativo com input type="color"
- Com apenas uma linha,
<input type="color">permite usar o seletor de cores nativo do navegador - Isso pode substituir muitas interfaces em canvas e sliders feitos com JavaScript
- O seletor de cores nativo dos navegadores Chromium permite escolher cores não só dentro do site, mas em qualquer lugar da tela
- Como nem todos os usuários conseguem usar o seletor de cores do navegador, é melhor oferecer junto outra forma de escolher a cor, como uma entrada de texto comum
Acordeão com details e summary
- Os elementos
detailsesummaryoferecem um acordeão nativo do navegador para recolher e expandir conteúdo - O comportamento padrão é simples
- O conteúdo dentro de
details, excetosummary, fica oculto - Quando o usuário clica em
summary, o restante do conteúdo é exibido
- O conteúdo dentro de
- O atributo
opendefine o estado inicial aberto- Ele não é um valor fixo após a interação do usuário; o estado muda conforme o usuário abre e fecha
summary::markerpermite estilizar o marcador triangular padrão- Dá para trocar o conteúdo por emoji etc.
- Dá para ajustar cor de fundo, imagem de fundo, tamanho da fonte etc.
- Muitas propriedades CSS não funcionam, e há limitações para estilizações como posicioná-lo em um lugar completamente diferente
- No Safari, é necessário o pseudo-elemento
::-webkit-details-marker - Alterar o conteúdo do marcador pode afetar a forma como tecnologias assistivas anunciam o acordeão, então vale consultar details/summary inconsistencies
summaryé clicável, mas por padrão não mostra cursor de ponteiro como um link nem parece um botão, então é preciso adicionar estados de hover e focus para deixar claro que pode ser clicado
Modal com dialog
alert(),prompt()econfirm()podem avisar ou pedir confirmação ao usuário, mas bloqueiam a thread principal e são difíceis de estilizar para combinar com o design- Criar um diálogo manualmente torna a acessibilidade mais complexa
- É preciso manter o foco dentro do diálogo
- É preciso informar que ele é modal
- É preciso impedir que o usuário saia dele por engano
- Pode haver conflito com widgets que usam
z-indexmuito alto
- O elemento
dialogdo navegador fornece um diálogo nativo - Atualmente, ainda é preciso JavaScript para abrir o diálogo
- Já existem mudanças em andamento para abrir sem JavaScript, mas isso ainda não foi totalmente especificado nem implementado
- É possível abrir o diálogo com a função
showModal()
dialogabre na top layer- A top layer é uma nova camada separada do HTML
- Elementos nessa camada sempre aparecem por cima, independentemente de
z-indexe do aninhamento de contextos de empilhamento - Para entender o conceito, consulte Top layer na MDN
dialognão fornece interface de fechamento por padrão, então é preciso adicionar a sua própria- Quando um
form method="dialog"é enviado, o navegador fecha o diálogo - Se você der
valuediferentes a dois botões de envio, poderá usá-lo como um diálogo de confirmação - No evento
close, é possível lerdialog.returnValuepara saber o valor do botão pressionado pelo usuário - Dados adicionais do formulário podem ser lidos com FormData
- Quando um
dialog::backdropé a camada entre o diálogo e o restante da página- Dá para escurecer ou desfocar o fundo e direcionar a atenção do usuário ao diálogo
- Como o navegador faz o posicionamento, não é preciso lidar manualmente com rolagem, elementos fixos nem redimensionamento da janela
Recursos possíveis com menos JavaScript
- Há mais recursos em que é possível reduzir o uso de JavaScript
- Rolagem suave nativa com
scroll-behavior: smooth- Com a condição de usar isso apenas quando
prefers-reduced-motion: no preferencefor verdadeiro
- Com a condição de usar isso apenas quando
- Carrossel nativo com
scroll-snap - Elementos “in-view” com
position: sticky - Container queries
- Rolagem suave nativa com
- Também há recursos que ainda vão chegar
- Animações baseadas em scroll
- Layout Masonry com
grid-template-rows: masonry, semmasonry.js - Um
selecttotalmente estilável com o novo elementoselectlist - O seletor
:has(), que pode reduzir uma categoria de código JavaScript de seleção
- Você pode ver mais no vídeo da apresentação Stop Using JavaScript for That: Moving Features from JS to CSS and HTML.
- Ao trocar uma implementação já comprovada por uma abordagem nova, é especialmente importante testar a acessibilidade para não excluir ninguém
1 comentários
Comentários no Hacker News
O que este texto deixa de fora é que a razão para usar JavaScript nesses casos é a melhor compatibilidade
JavaScript novo pode ser transpilado, mas é muito mais difícil — e, em alguns casos, impossível — aplicar polyfills para recursos ausentes de CSS ou HTML. Além disso, esses polyfills acabam usando JavaScript
Mesmo no MDN, há muitos avisos para testar cuidadosamente
appearance, até mesmoappearance: none. Se você só precisa dar suporte a navegadores modernos, isso pode ser menos importante, mas versões antigas do Safari continuam por aí por mais tempo do que se imaginadatalistnão faz nada no Firefox Android e, para mim, aparece apenas como um campo de entrada sem sequer sugestõesO seletor de cores é legal, mas é extremamente não padronizado, o que é fatal para a maioria dos negócios. Não são só os designers que reclamam: o suporte ao cliente passa a ter dificuldade para ajudar os usuários. O Chromium até oferece a opção de capturar uma cor da página ou escolher uma cor arbitrária, mas o Firefox Android só dá algo como arco-íris, cinza e preto e branco
O próprio texto também reconhece as inconsistências de
detailsedialog. Espero que um dia navegadores que não dão suporte a esses recursos, ou que não os suportam de forma consistente entre si, deixem de ser usados, mas por enquanto esses elementos parecem úteis apenas em projetos paralelos nos quais você consegue controlar totalmente os navegadores suportadosNo iPhone, ao tocar no botão, aparece o seletor de cores nativo real do sistema. É aquele mesmo controle fornecido pelo SO e visto em vários apps, e eu o prefiro muito mais do que algo feito sob medida
Prefiro muito mais uma web sem JavaScript, e isso afeta a bateria do notebook em horas. Alguns sites não são compatíveis com isso e renderizam apenas uma página em branco, ou reclamam que precisam de JavaScript para mostrar texto
Por outro lado, a Amazon também tem uma réplica do site de e-commerce sem JavaScript, mostrando que até algo enorme assim é possível sem JavaScript
dialogagora tem uma cobertura de suporte bastante ampla, e os polyfills para os poucos por cento de usuários que usam Firefox ou Safari da época de 2021 são bons o suficienteSe você estiver criando um modal, recomendo muito; as melhorias de acessibilidade são excelentes
No meu emprego anterior discutimos ativamente esse problema e decidimos usar uma implementação em JS em vez de algo como
datalist. Em especial, tentamosdatalist, mas os resultados eram tão inconsistentes que tivemos de abandonarNo fim, por causa das inconsistências entre navegadores, também acabamos deixando de dar suporte a tudo que não fosse Chrome
Nos exemplos em HTML, o visual pode ficar errado em navegadores antigos, mas o conteúdo real continua lá. Com JS, simplesmente não há nada. Isso quebra totalmente a acessibilidade
Com HTML, um leitor de tela pelo menos consegue ler, mas conteúdo gerado por JS impede isso. Quando o JS não consegue executar JS, nenhum polyfill nem outro JS pode salvar o JS. Ele precisa “funcionar” desde o começo para ser aceitável em acessibilidade e, nesse caso, o argumento original perde o sentido
Eu não conhecia
Datalist, mas pelo menos no Chrome Android ele não parece funcionar direitoAs opções aparecem na área do teclado onde surgem as sugestões de preenchimento automático: https://imgur.com/a/Ecb4503
Nunca vi esse tipo de comportamento em controles de formulário de UI web móvel, exceto quando apps de preenchimento automático de senha usam o mesmo espaço
Não é ruim. É muito melhor do que rolar desajeitadamente por um dropdown JS customizado malfeito, mas não tenho confiança de que um usuário comum vá descobrir como usar isso. Por isso, no mobile, considero praticamente sem futuro
No Firefox Android, não há suporte nenhum: https://caniuse.com/?search=datalist
datalist?Referência: https://adrianroselli.com/2023/06/under-engineered-comboboxe...
JavaScript é bastante bem padronizado, mas HTML e CSS são relativamente menos
autocomplete="off"ao elementoinputmuda o comportamentoDe qualquer forma, isso é necessário para usar
datalistcorretamente. Caso contrário, o histórico de valores selecionados é anexado à lista do dropdown. Observei isso no ChromiumAlém disso, em certas situações, como quando há um valor padrão definido,
datalistainda precisa de JS. Documentei as soluções de contorno e observações sobre comportamentos específicos de navegadores no código do novo site do LibreOffice: https://git.libreoffice.org/infra/libreofficeorg/+/835a5cc59...A boa notícia é que um desenvolvedor do Firefox planeja analisar melhorias no comportamento de
datalist, o que talvez permita exibir a lista com apenas um cliqueNo meu caso, as opções aparecem na área acima do teclado onde normalmente são mostradas sugestões de palavras
datalistaparecerem dentro do teclado é uma mudança que surgiu nos últimos mesesAntes era “normal”, mas parece que alguém quis mudar só por mudar
Usar rolagem suave nativa com
scroll-behavior: smoothdeve, por favor, ser feito apenas de forma limitadaNa maioria dos usos, é uma ideia pior do que parece e costuma ter efeitos colaterais indesejados
Dizem que dá para criar um carrossel nativo com
scroll-snap, mas carrosséis continuam sendo uma má ideia, então o escopo legítimo de uso descroll-snapé extremamente limitadoPáginas que usam animações baseadas em rolagem geralmente ficam melhores quando isso é removido
A rolagem suave é um bom exemplo. A API nativa permite que o usuário interrompa a qualquer momento. A maioria das implementações em JS é terrivelmente engasgada e faz o usuário sofrer
Dá para criticar escolhas de design à vontade, mas, se você não apresentar motivos reais para “carrosséis continuam sendo ruins”, é difícil esperar que alguém dê ouvidos
Mas a homepage da Amazon usa carrosséis de forma bem visível, e pelo que sei a Amazon faz testes A/B implacáveis em variações da homepage. Então é possível que os carrosséis tenham se saído bem nos testes, e fica meio ambíguo dizer que eles são realmente “ruins” em algum sentido universal e objetivo
Normalmente, eu pelo menos a adiciono logo depois de implementar âncoras no estilo sumário
É surpreendente que, em 2023, ainda estejamos brigando por causa de formulários e da UX comum em que o usuário insere dados
Basta ver os comentários sobre
dataliste seletores de cor; não entendo por que isso ainda não é uma área resolvidaAntigamente houve uma tentativa de resolver tudo isso de uma vez com XForms, mas ela não foi implementada nos navegadores
Em vez disso, praticamente todo framework de componentes CSS/JS oferece seu próprio conjunto limitado de elementos de formulário com semânticas diferentes
Parece que vamos passar a vida inteira implementando controles básicos de UI por conta própria
A impressão de que “não está resolvido” só existe porque algumas pessoas têm uma obsessão estranha em evitar JavaScript e tentam enfiar alternativas meio cruas à força
Se você vai ficar em tecnologias básicas e sem graça, já está resolvido. Mas, se insistir em resolver de novo com React, depois resolver mais uma vez com React hooks e continuar resolvendo de novo para sempre, então passa a não estar resolvido
Intenção não é algo que possa ser determinado por programa, então, em certas situações, não dá para ter recursos legais
No último formulário complexo em que trabalhei, tive que fazer com que um evento de clique causasse o envio do formulário de maneira bem direta para que o navegador permitisse
Eu nunca pedi um jeito de enviar cores por uma página web
Se você usar
detailsem vez de JavaScript, o Ctrl+F consegue pesquisar dentro dele e abri-loUm acordeão em JavaScript não consegue abrir assim
hidden="until-found", isso também passa a ser possível em acordeões baseados em JS ou em outros conteúdos ocultos, mas infelizmente por enquanto só existe em navegadores baseados em Chromium: https://developer.chrome.com/articles/hidden-until-found/Concordo com a maior parte, mas não usei
dialogo bastante para ter uma opinião, e acho quedatalistnão é uma opção válida a menos que seja para ferramentas internasÉ feio, limitado no que permite fazer e também não dá para estilizar. Esse é o problema da maioria dos argumentos de “use simplesmente o que já vem embutido”. O mesmo vale para
date pickerO padrão não é apenas ruim; mesmo que você queira mudá-lo, não consegue. Quando você bate em uma das inúmeras paredes ao tentar mudar o estilo ou o comportamento, por exemplo querendo que a semana comece na segunda-feira, não dá. Aí a opção geralmente é uma biblioteca de substituição completa usando JS
Sou a favor de usar opções mais leves e também concordo com a hierarquia HTML > CSS > JS, mas, para ter uma UI bonita e todos os recursos desejados, às vezes JS é a única resposta
datalistpoderia ajudarFuncionou bem até o momento em que passei a querer exibir opções que não começam estritamente com o texto digitado. Por exemplo, se houver um erro de digitação na entrada, as opções não aparecem
Como não havia como forçar a exibição de todos os itens, acabei optando por uma lista ordenada
Quando comecei no desenvolvimento web, mudanças levavam até 10 anos. O IE6 também segurava todos nós, mas o w3c também era bem fraco naquela época. Hoje as mudanças são rápidas
No ano que vem, talvez seja possível estilizar
datalistsem prefixos nos três principais navegadores, mas, se você estiver preso a uma solução JS personalizada, o negócio não vai pagar o custo de reconstruçãoSe você estender recursos nativos com JS, poderá remover o JS a baixo custo quando o suporte for suficiente. Use controles nativos agora onde forem aceitáveis e aplique JS como se fosse um polyfill
input[type=date]é melhor que o desenvolvedor não controle mesmoO calendário adequado a exibir deve ser dependente da localidade. A plataforma do usuário já tem a capacidade de configurar e exibir isso da forma que o usuário tem mais probabilidade de usar com eficiência
O seletor de data da plataforma é melhor do que alguma coisa estranha feita à mão
Aquele botão de alternância é realmente ótimo
Parece que os desenvolvedores de memes de frontend estão ficando irritados com este texto, mas o ponto central está correto. Por que tantos sites idiotas são feitos com JS? Se as pessoas seguissem apenas um padrão, como HTML, tudo poderia ser consistente, e coisas como acessibilidade ou tradução também poderiam ser atendidas facilmente
Hoje em dia, quando você entra em um site, até o botão de voltar não funciona, porque tudo é carregado dinamicamente em uma única página
E ainda existe o problema de “esperar as pessoas atualizarem”, em que, depois que um novo recurso é introduzido, pode levar anos até que ele tenha suporte amplo o suficiente para ser útil
No geral, concordo que há muitas implementações ruins e engenhocas complexas em JavaScript. Existem várias soluções padronizadas para manter a funcionalidade de voltar mesmo com conteúdo dinâmico, e, pelo que sei, frameworks web populares oferecem suporte a isso por padrão
Li os comentários no topo, mas não vi muita coisa que eu chamaria de indignação; só pessoas levantando pontos válidos sobre suporte dos navegadores
É um passo na direção certa, mas CSS também é outra ferramenta que os “artistes” de Philip Greenspun abusam para criar páginas difíceis de ler
Não sou defensor do Gemini, mas basicamente todos os aspectos de layout e tipografia deveriam voltar para o navegador e ficar sob controle do usuário. Designers já demonstraram infinitas vezes que não dá para confiar isso a eles
Gosto da intenção, o switch é bacana, e
summary/detailstambém são úteis às vezesMas o elemento
datalistquase nunca é uma opção realista para usos além de brinquedos ou protótiposAs coisas que eu gosto de fazer “só com CSS, sem JS” são drawers de barra lateral e carrosséis
A DaisyUI, uma biblioteca de componentes TailwindCSS, também tem componentes prontos para uso
https://daisyui.com/components/drawer/
https://daisyui.com/components/carousel/
O drawer e outros conteúdos que aparecem na página precisam ser anunciados, e deve haver um estado
aria-expandedao lado do controleAinda é uma pergunta de verdade. Talvez exista um jeito, ou talvez os desenvolvedores coletivamente achem que isso não é importante. Auditores não concordariam
Acho que os autores desses frameworks subestimam muito a quantidade de testes necessária para fazer tudo realmente funcionar entre navegadores
Com tantos componentes e, além disso, a possibilidade de temas, é difícil garantir que será possível corrigir sem quebrar temas e aplicações existentes
components/carousel/Afinal, o que é snap e como isso funciona? Minha tela não reage a cliques com o dedo
Acho que um modo de interação desconhecido não é uma boa razão para recomendar uma biblioteca de elementos de UI