CSS: as partes ruins inevitáveis
(matklad.github.io)- Para estilizar páginas web simples, como um blog ou uma GUI básica, basta aprender um pequeno subconjunto, mas armadilhas como os padrões do navegador e layout podem virar dias de depuração
- Se você usar primeiro tags HTML5 semânticas e reduzir wrappers, fica mais fácil fazer o CSS funcionar em cima do markup existente
- Não existe um único algoritmo universal para layout em CSS; é preciso entender que tipos de disposição cada sistema permite
box-sizing,margin,font-size,line-heighteword-breakfuncionam de forma diferente do que a intuição sugere, e pequenas mudanças podem se espalhar para problemas de layout ou legibilidade- Para páginas simples, CSS reset, CSS sem classes, flexbox e regras responsivas sem exagero podem ser um ponto de partida prático
Escopo do aprendizado de CSS e perspectiva básica
- CSS, HTML e Web API são enormes e exigem especialização, mas para tarefas como um blog de programação ou uma GUI simples, um subconjunto razoável da web moderna já basta
- O autor não encontrou material que ensine apenas o subconjunto necessário para tarefas simples, mas dá para entender bastante coisa seguindo o MDN
- O problema é que armadilhas cuja existência você nem imaginava podem quebrar a página, e encontrar a causa pode levar dias
- O estilo deste site é composto por cerca de 200 linhas de CSS legível
As partes boas: HTML semântico e CSS sem classes
-
Tags semânticas do HTML5
- Vale a pena dar uma olhada no Elements Reference do MDN, e a quantidade de elementos HTML nem é tão grande
- Tags como
main,article,navekbdpodem facilitar a estruturação da página ulpode ser usado para todo tipo de lista, como as seções do site dentro deheader > navdetailspode ser usado para sumário, e dá para conferir o código-fonte do MDNdledtpodem ser usados para listas em pares
-
Uma abordagem com menos wrappers
- Ao olhar o código-fonte de sites reais, há muitos elementos wrapper em camadas, o que pode dar a impressão de que problemas de layout são resolvidos com wrappers
- Sem entrar no mérito da experiência com CSS de produção, foi mais fácil de entender limitar-se a usar apenas tags semânticas significativas e depois encontrar um CSS que se encaixasse nesse markup
-
CSS sem classes
- Não dá para redefinir estilo para um estado totalmente neutro de “nada”; texto branco ou transparente ainda é estilo
- Depois do reset, é possível estilizar diretamente os elementos HTML comuns
- Se você usar tags
main,header,footerenav, dá para configurar o layout geral da página sem usar muitos seletores CSS - Essa abordagem faz o CSS assumir a estrutura do HTML, mas se o HTML e o CSS forem seus, você pode mudar quando não gostar do resultado
As partes ruins: layout, padrões do navegador e seletores
-
Layout
- Problemas de layout não são exclusivos da web; são difíceis em vários frameworks de GUI
- Há várias formas de dispor dentro de um retângulo na tela uma imagem raster de tamanho fixo e um parágrafo de texto explicando essa imagem
- Uma GUI comum é uma hierarquia de caixas com muita “liberdade de layout”
- O layout de cada caixa afeta o layout de todas as outras, e normalmente todas as caixas precisam se encaixar exatamente, sem espaços nem sobreposição
- Não existe um único algoritmo universal de layout; sistemas usam heurísticas diferentes, de RectCut a constraint solvers, passando por áreas intermediárias
- Em vez de pensar “como faço este layout neste sistema?”, é melhor pensar “que layouts esse sistema permite?”
-
Padrões do navegador e CSS reset
- Mesmo HTML semântico sem CSS recebe estilos padrão no navegador: cor, fonte, tamanho, títulos grandes, links sublinhados etc.
- Os estilos padrão ajudam, mas variam entre navegadores, e depender de padrões que você não escreveu pode produzir resultados diferentes em outro navegador
- A solução comum é um CSS reset ou normalização, ou seja, sobrescrever os padrões com regras explícitas no começo do CSS
- O problema não é os padrões em si, mas a falta de consistência entre eles
- Na prática, vale mais comparar vários CSS resets existentes para entender quais regras sobrescrever
-
Devemos estilizar páginas web?
- Na plataforma web coexistem a visão de um meio visual flexível e adaptável e a visão de que o foco deve ser entregar conteúdo e deixar o usuário customizar a apresentação
- Uma página sem estilo por padrão tem baixa usabilidade e não fica bonita
- Seria melhor viver num mundo em que páginas sem CSS já fossem fáceis de ler, mas no ambiente atual aplicar estilo ao conteúdo ajuda
- É bom permitir que usuários avançados tragam seu próprio CSS
- O markup HTML deve ser razoável, não deve ser superajustado ao CSS, e a página deve funcionar no reader mode
-
Seletores CSS
- O CSS básico funciona como uma herança poderosa, e cada elemento visual da página sofre influência de várias regras
- Você pode “monkey patch” qualquer elemento existente a qualquer momento simplesmente acrescentando coisas ao arquivo CSS
- O autor vê os seletores CSS como uma abstração que aumenta o poder no eixo errado, e por isso considera viável usar CSS sem classes e estilo inline
- Ferramentas como Tailwind reduzem a inconveniência de escrever inline, e JSX ou engines de template com suporte a composição reduzem repetição no HTML
- Com CSS nesting, dá para reduzir seletores que se estendem longe e estilizar por componente
Modelo de caixa e disposição: box-sizing, margin, flow padrão e flexbox
-
box-sizing- Interfaces são retângulos recursivos, e layout é o processo de decidir onde cada retângulo vai ficar
- No padrão do HTML,
widtheheightde um elemento não incluem borda nem padding, o que não é intuitivo - Se você aumentar o padding em um ponto, um layout inteiro que parecia perfeito pode se deslocar de forma inesperada
* { box-sizing: border-box; }merece ser a primeira linha de um CSS reset, pois transforma adicionar borda numa mudança local
-
margin collapsing
- Se você quer um espaçamento de
8pxao redor de um elemento e usa padding, o espaço entre dois elementos adjacentes pode virar16px marginfunciona combinando as margens de dois vizinhos pormax, não por soma- O margin collapsing é muito útil, mas pode gerar comportamentos surpreendentes
- O autor entende que a margem de um filho pode escapar para fora do pai, mas admite que sua intuição sobre margin ainda não é suficiente
- O texto de Julia Evans, Moving away from Tailwind, and learning to structure my CSS, fala da abordagem com owl selector, em que o pai controla o espaçamento entre os filhos em vez de dar margin ao próprio elemento
- A ideia de adicionar margin a todos os filhos de uma
section, exceto o primeiro, é entendida como uma forma de reduzir problemas com margin - É incômodo que esse tipo de conhecimento seja difícil de aprender sem virar um desenvolvedor web profissional ou fazer engenharia reversa de outros frameworks CSS
- Se você quer um espaçamento de
-
Layout flow padrão
- O algoritmo de layout padrão parece estar ligado à origem do HTML como linguagem de documentos e a casos de uso voltados à produção de documentos em papel, centrados em texto e imagens
- Para texto corrido, o flow padrão de fato se comporta próximo do desejado
- Para controlar diretamente a disposição espacial dos elementos da página, é preciso algo diferente do flow padrão
-
flexbox
- flexbox é um layout para organizar uma sequência de elementos vertical ou horizontalmente, adaptando-os ao espaço disponível
- No passado, até mesmo posicionamentos como “isto à esquerda, isto à direita” exigiam conhecimento profundo de CSS ou um framework CSS opaco
- flexbox é bastante complexo e ainda exige consultar o MDN com frequência, mas na maior parte do tempo permite concluir o que você quer fazer
-
Design responsivo
- O CSS moderno consegue consultar o tamanho da tela e implementar lógica condicional de acordo com restrições do user agent
- O HTML é inerentemente responsivo; ao contrário de PostScript ou PDF, ele refaz automaticamente o fluxo dos parágrafos quando o tamanho da janela muda
- É melhor evitar regras responsivas explícitas e deixar o layout se comportar de forma razoável por conta própria
- Este blog parece aceitável em celular, tablet e desktop sem nenhuma query
@mediaexplícita - Basta definir um
max-widthincondicional para a coluna principal do texto
Tamanho e texto: pixels, fonte, altura de linha e quebra de linha
-
Pixels
1pxfaz o que você espera, mas não significa um pixel físico da tela- Em CSS,
1pxé uma unidade de ângulo visual, projetada para parecer perceptivamente parecida em qualquer tela - Ele se converte em quantidades diferentes de pixels físicos dependendo do tamanho da tela, da densidade de pixels e da distância típica de visualização
- Por isso, você pode especificar todos os tamanhos em pixels sem precisar pensar separadamente na densidade de pixels de diferentes telas
- Até unidades “reais” do CSS, como centímetros e polegadas, são definidas com base em pixels e por isso também funcionam como ângulos
-
font-size- Em
font-size: 16px,16pxnão é o tamanho de um glifo específico, mas o tamanho de uma caixa virtual ao redor dos glifos - Essa caixa não se ajusta exatamente aos glifos, e o tamanho real deles varia conforme a fonte
font-size-adjustpode tornarfont-sizemais consistente entre fontes- Hoje,
font-size-adjustparece um recurso muito de nicho; pessoalmente, o autor gostaria de colocarfont-size-adjust: ex-height 0.53;ao lado debox-sizing, mas poucas páginas fazem isso - O valor padrão de
font-sizeé relativamente consistente entre navegadores, com16pxdominando amplamente - Dependendo da fonte,
16pxpode parecer pequeno, e algumas fontes padrão são especialmente pequenas - Na Apple,
font-family: serifparece muito menor quesans-serife, em16px, quase desconfortável para leitura - Definir
font-sizeno CSS desativa a forma como o navegador altera o tamanho de fonte padrão - Não assuma que o texto será legível por padrão; teste em outras configurações
- Se você reduzir a liberdade com
font-size-adjuste fixar o significado defont-size, então, se estiver bom com a fonte padrão em16px, está resolvido - Caso contrário, defina
font-sizecom um número maior e depois verifique se continua legível também no reader mode
- Em
-
line-height- Apesar do nome,
line-heightnão define a altura de uma linha line-heighté a altura de um conjunto de glifos configurados com a mesma fonte- Quando todo o texto usa a mesma fonte, a altura da linha e a altura desse conjunto coincidem
- Se algumas palavras estiverem em fonte
monospace, o resultado pode sair diferente do esperado font-size-adjustcorrige o tamanho dos glifos dentro da caixa, mas não define sua posição relativa- Quando conjuntos de texto em fontes diferentes são alinhados verticalmente para compartilhar a mesma baseline, suas line boxes de
line-heightficam desalinhadas entre si - A altura total da linha pode então ser formada como uma união e acabar maior do que o esperado
- Esse efeito é explorado em detalhe em Deep dive CSS: font metrics, line-height and vertical-align
- Apesar do nome,
-
Ritmo vertical
- Ritmo vertical é a ideia de manter as linhas entre parágrafos na mesma posição relativa, mesmo com títulos, imagens etc.
- Isso é explicado como se houvesse um caderno pautado invisível por trás da página web
- O autor considera que isso não é útil em layouts de coluna única
- Em layouts de duas colunas, talvez você queira alinhar as linhas dos dois lados
- Em uma coluna única, não faz sentido gastar muito esforço com isso
-
word-break- Uma vantagem do layout flow é seu comportamento dinâmico elegante quando a janela fica estreita e o texto se divide em linhas
- As linhas só podem quebrar em espaços em branco ou pontos onde hífens podem ser inseridos
- Trechos longos como
inline codeou URLs podem não quebrar - Em dispositivos móveis, isso causa overflow horizontal, algo que normalmente só é percebido depois da publicação
- Não existe um truque único para corrigir isso, mas há algumas dicas em Against Horizontal Scroll
Conclusão prática
- Para criar um blog simples, faz falta um material que explique de forma breve apenas a parte suficiente de HTML e CSS
- O texto termina com um pedido por um livro curto, de umas 100 páginas, que explique HTML e CSS o bastante para criar um blog simples sem desmoronar diante de problemas como margin collapsing
1 comentários
Opiniões no Lobste.rs
É uma observação pequena, mas a definição de design responsivo é “garantir usabilidade e satisfação ao renderizar bem em diversos dispositivos e tamanhos de janela/tela”
Media queries e container queries são apenas uma das ferramentas para implementar isso, e design responsivo está mais próximo de uma forma de pensar do que de “vamos usar media queries para tudo”
Então, parece mais correto dizer que o “ruim” não é o design responsivo em si, mas o uso de media queries ou o abuso de breakpoints
A parte sobre “Browser defaults” induz bastante a erro. Reset stylesheets e normalize stylesheets têm objetivos e comportamentos muito diferentes, e o texto mistura os dois
O reset, mais do que eliminar diferenças entre navegadores, apaga diferenças padrão entre elementos, removendo coisas como
padding-inline-startdeolou a aparência padrão debutton, e permite criar estilos partindo de uma folha em branco, em vez de por cima da user agent stylesheetA normalização é uma abordagem que tenta cooperar com a user agent stylesheet, e mistura partes que alinham diferenças entre navegadores com partes que trocam valores padrão por opções consideradas “mais razoáveis”
Hoje em dia, não há muitos casos em que os padrões dos navegadores difiram de forma significativa, então quem escreve conteúdo web comum pode praticamente ignorar isso. Como exceções, ainda restam o
border-colordetableestá errado no Chromium, o WebKit corrigiu o deles há 1 ano e meio, diferenças de margem/tamanho em alguns elementos de formulário,appearancee o styling de::markerem<summary>no WebKitTambém sou contra
box-sizing: border-box.border-boxé centrado em layout, enquantocontent-boxé centrado em conteúdo; por isso, considero melhor que o pai cuide do layout e que o design seja feito com base no conteúdo. Ao lidar com proporções,content-boxé necessário, e o único caso em queborder-boxrealmente é útil é algo como fazer obodypreencher a viewportTambém sou cético quanto a
font-size-adjust. Isso troca um problema amplamente conhecido por outro menos validado; para algumas pessoas pode ficar um pouco melhor e para outras um pouco pior. Não resolve o problema fundamental e acaba fazendo suposições sem base sobre as proporções e métricas de fonte do usuárioA expressão “mesma fonte” em relação a
line-heighttambém não é rigorosa. Na prática, tamanho da fonte, mudança de idioma,font-family: monospace,vertical-align,<sup>,<sub>e métricas de fonte se entrelaçam, então é difícil tratar isso simplesmente como um problema de usar a mesma fonteColapso de margens é mais complexo do que o texto sugere, mas também é bastante prático. Se você usar
flexougridem conteúdo comum, tende a ficar ajustandogapou margens o tempo todo, deixando tudo mais frágil. Comdisplay: flow-root, dá para impedir que a margem dos filhos colapse com a margem do paiEmbora eu não concorde com a visão geral apresentada sobre design responsivo, a direção de reduzir media queries desnecessárias e de não brigar com o navegador está certa. Se for possível expressar mudanças de layout com base no conteúdo, em geral isso é melhor
Recentemente tenho usado muito interpolação linear com clamp usando unidades de viewport:
margin-inline: --vw-lerp(1rem at 20rem, 2.5rem at 60rem);, expandido paramargin-inline: clamp(1rem,1rem + ((2.5 - 1)/(60 - 20)*(100vw - 20rem)),2.5rem);No ano passado implementei isso como um visitor do LightningCSS, e o resultado é 1rem quando a viewport está em 20rem ou menos, cresce suavemente até 2.5rem em 60rem e então para, sem breakpoints, além de responder ao tamanho de fonte do usuário, o que dá uma sensação bem boa
font-size-adjustfunciona exatamente assim. O nome confunde, mas entendo quefont-sizealtera o tamanho da caixa em, enquantofont-size-adjustaltera o tamanho do glifo dentro da caixa emEntão
emerempermanecem iguais, echmuda. Maschjá depende da fonte por natureza, então faz sentido que mudeGostaria que alguém escrevesse sobre
font-size-adjust. Não sou especialista, então meu grau de certeza é baixo, mas até agora isso me parece algo quase desconhecido e, ainda assim, uma melhoria enorme. Não dá para alinhar automaticamente quaisquer duas fontes em todos os contextos, mas só de igualar o tamanho dox, em vez da caixa em, já cobre 90% dos casos de fonte/contextoA intenção do texto é boa, e a perspectiva de pessoas que não estão totalmente imersas em HTML/CSS também é importante, mas muitos dos “aspectos ruins” podem ser bons dependendo do contexto
Seletores CSS são fáceis de abusar, mas não são ruins por natureza. Em vez de concluir em A ou B, dá para definir regras/seletores gerais e, quando necessário, espalhar classes de exceção ou classes utilitárias
O próprio texto tem um bom exemplo de seletor:
Media queries também podem ser desnecessárias se o problema puder ser resolvido com container queries
CSS pode parecer ter uma superfície enorme, mas, justamente por ser amplamente usado e conseguir fazer tanta coisa, também gera muitos conflitos de opinião. Ainda assim, é preciso observar o quanto o CSS evoluiu e o que dá para fazer com relativamente pouco código depois que você assimila os conceitos
Se quiser aprender mais, https://every-layout.dev/ foi bem útil para eu entender como vários elementos se encaixam no CSS
O momento em que comecei a entender layout web foi quando percebi que bons sites são, basicamente, projetados na vertical. Os elementos devem, por padrão, se empilhar de cima para baixo, e você projeta primeiro para a tela móvel; em telas grandes, expandir isso vira um bônus
É difícil concordar com essa afirmação. Aninhamento de CSS é só açúcar sintático e não ajuda de forma significativa a evitar o problema de seletores excessivamente específicos
Há 15 anos já se usava muito aninhamento de seletores com Sass, e aos poucos todo mundo acabou chegando à conclusão de que isso amarrava demais os seletores CSS à estrutura do HTML e acabava sendo um tiro no próprio pé
A armadilha do aninhamento não aparece muito no começo do projeto. Na fase greenfield, quando você está principalmente criando funcionalidades novas, escrever CSS assim parece ótimo
Alguns meses depois, quando começam grandes mudanças de layout e reformulações de design, os elementos wrapper mudam de lugar no HTML, e adaptar o CSS a isso passa a parecer resolver um Cubo de Rubik sob efeito de LSD
Eu diria que o auge do gerenciamento de especificidade de seletores foi manter a maior parte em seletores simples, ou seja, baixos, com uma única classe, e usar só um pequeno número de seletores compostos e combinados como
a:hover. É a linha de BEM, OOCSS etc., e depois disso o foco migrou rapidamente para ferramentas centradas em JSTexto interessante, mas parece que o autor está usando seletores aninhados em uma posição onde não produzem efeito algum
&e, por isso, sempre o usa. Acho uma posição bastante razoávelPessoalmente, ainda estou dividido. No início achei que fosse um erro, mas em situações em que você já escreveu um monte de estilos e depois só envolve tudo com
header { … }para restringir o escopo, isso é bem conveniente. Também seria bom se regras at não baseadas em seletores, como@keyframes, pudessem ser usadas ali dentroIsso, sinceramente, é um conselho muito ruim. Gosto dos textos do Maklad, mas isso claramente parece ter sido escrito por alguém que nunca usou CSS profissionalmente
Quase tudo aí são más práticas amadoras que se evitam ao escrever CSS de forma profissional
Ao estilizar isso sem classes, acabam também estilizando
<main>e<nav>sem classesJá em ambiente profissional, gasta-se pouquíssimo tempo projetando a caixa de conteúdo. Ela é criada uma vez no começo do projeto e depois, no máximo, recebe pequenas correções de bug ao longo do tempo
A maior parte do tempo vai para criar componentes customizados ou reutilizáveis. Componentes reutilizáveis são mais difíceis e, na prática, você acaba fazendo um clone do Bootstrap específico do site
Componentes customizados são fáceis, mas geram muito código, e é preciso alguma estratégia para evitar interferência não intencional com outros componentes, como BEM, OOCSS ou classes utilitárias como as do Tailwind
A conclusão é que cada técnica serve para uma escala diferente. Se a forma profissional de escrever CSS parece inútil para você, provavelmente é porque você está resolvendo um problema de outra escala
Ainda assim, concordo com
Bad: Wrappers. Já vi especialista em CSS escrever o site inteiro em um ou dois arquivos, e também já vi gente que usa CSS em enorme quantidadeO segundo caminho tende a acabar levando a abordagens equivocadas como BEM para conseguir administrar tanto CSS
Parece haver conselhos conflitantes no texto
Good: Classless CSSeBad: CSS selectorsaparecem juntos, mas, para usar CSS sem classes, você acaba dependendo ainda mais de seletores CSSReferência: https://www.keithcirkel.co.uk/css-classes-considered-harmful/
Esse ritmo vertical, de “como se houvesse um caderno pautado invisível atrás da página”, é perfeitamente possível usando valores em EM
Se você misturar fontes diferentes, pode haver uma pequena oscilação por causa das diferenças de métricas, mas mesmo assim dá para usar
align-items: baselinedo flex