Tutorial de layout CSS: das abordagens clássicas às técnicas mais recentes

Publicados: 2022-03-11

Dominar o layout da web sem dominar o CSS é tão viável quanto aprender a nadar em terra firme. Mas, diferentemente da natação – que, uma vez dominada, é uma habilidade que permanece com você por toda a vida – dominar CSS é um processo que nunca termina, pois o próprio CSS está em constante evolução.

O desafio é agravado pelas diferenças na implementação e suporte de CSS em diferentes navegadores (e até mesmo em diferentes versões do mesmo navegador), bem como diferentes taxas de adoção de recomendações de CSS. Por mais de uma década, web designers e desenvolvedores têm lidado com rajadas esporádicas e inconsistentes de recursos CSS3 adicionais sendo suportados em cada nova versão do navegador.

Mas seja como for, dominar CSS é uma necessidade absoluta para qualquer web designer ou desenvolvedor sólido. Este artigo irá guiá-lo através de alguns princípios fundamentais de layout CSS, desde técnicas clássicas de CSS2 até as mais recentes abordagens de layout em CSS3.

NOTA: Todos os exemplos de código neste artigo usam elementos HTML5 e sintaxe Sass. O código de trabalho completo pode ser clonado em https://github.com/laureanoarcanio/css-layout-examples.

Caso de uso

Uma das melhores maneiras de aprender uma tecnologia é ter um caso de uso específico que você está tentando dar suporte ou um problema específico que está tentando resolver. Para esse fim, vamos nos concentrar em um caso de uso com um conjunto específico de requisitos.

Nosso caso de uso consiste em um layout de aplicativo Web com algum comportamento dinâmico. Ele terá elementos fixos na página, como cabeçalho, rodapé, menu de navegação e sub-navegação, além de uma seção de conteúdo rolável. Aqui estão os requisitos de layout específicos:

  • Esquema Básico
    • Cabeçalho, rodapé, menu de navegação e sub-navegação permanecem fixos na rolagem
    • Elementos de navegação e sub-navegação ocupam todo o espaço livre vertical
    • A seção de conteúdo usa todo o espaço livre restante na página e tem uma área de rolagem
  • Comportamento Dinâmico
    • O menu de navegação mostra apenas ícones por padrão, mas também pode ser expandido para exibir texto (e pode ser recolhido para mostrar novamente apenas ícones)
  • Variações de layout
    • Algumas páginas possuem sub-navegação ao lado do menu de navegação e outras não

Tutorial de CSS usando técnicas clássicas de CSS2

Tutorial de CSS

Para começar, aqui está a marcação HTML5 que usaremos com nossa implementação de exemplo usando CSS clássico:

 <body class="layout-classic"> <header></header> <nav></nav> <aside></aside> <main></main> <footer></footer> </body>

Posicionamento Fixo

Em CSS2, podemos obter os elementos fixos na página (cabeçalho, rodapé, etc.) empregando um modelo de layout posicionado que usa posicionamento fixo.

Além disso, usaremos a propriedade CSS z-index para garantir que nossos elementos fixos permaneçam “sobre” o outro conteúdo da página. A propriedade z-index especifica a ordem de pilha de um elemento, onde um elemento com maior ordem de pilha está sempre “no topo” de um elemento com menor ordem de pilha. Observe que a propriedade z-index só funciona com elementos posicionados . Para nosso exemplo, usaremos arbitrariamente um valor z-index de 20 (que é maior que o padrão) para garantir que nossos elementos fixos permaneçam visualmente em primeiro plano.

Além disso, definiremos a propriedade width como 100%, que instrui o navegador a usar todo o espaço disponível horizontalmente para o elemento.

 #header, #footer { position: fixed; width: 100%; z-index: 20; } #header { top: 0; height: 5em; } #footer { bottom: 0; height: 3em; }

OK, então esse é o cabeçalho e o rodapé. Mas e o #nav e o #subnav ?

Expansão CSS

Para o #nav e o #subnav , usaremos uma técnica um pouco mais sofisticada conhecida como CSS Expansion , que pode ser usada ao posicionar elementos como fixos (ou seja, em uma posição fixa na página) ou absolutos (ou seja, em um posição especificada em relação ao seu ancestral posicionado mais próximo ou ao bloco que o contém).

A expansão vertical é obtida definindo as propriedades top e bottom de um elemento para um valor fixo, para que o elemento se expanda verticalmente para usar o espaço vertical restante de acordo. Basicamente, o que você está fazendo é amarrar a parte superior do elemento a uma distância específica da parte superior da página e a parte inferior do elemento a uma distância específica da parte inferior da página, para que o elemento se expanda para preencher todo o espaço vertical entre esses dois pontos.

Da mesma forma, a expansão horizontal é obtida definindo as propriedades left e right de um elemento para um valor fixo, para que o elemento se expanda horizontalmente para usar o espaço horizontal restante adequadamente.

Para nosso caso de uso, precisamos usar a expansão vertical.

 #nav, #subnav { position: fixed; top: 6em; /* leave 1em margin below header */ bottom: 4em; /* leave 1em margin above footer */ z-index: 20; } #nav { left: 0; width: 5em; } #subnav { left: 6em; /* leave 1em margin to right of nav */ width: 13em; }

Posicionamento padrão (estático)

A área de conteúdo rolável principal pode simplesmente contar com o posicionamento padrão (estático), em que os elementos são renderizados na ordem em que aparecem no fluxo do documento. Como todo o resto da nossa página está em uma posição fixa, esse elemento é o único que está no fluxo de documentos. Como resultado, tudo o que precisamos fazer para posicioná-lo corretamente é especificar sua propriedade margin para evitar qualquer sobreposição com o cabeçalho, rodapé e nav/subnav fixos:

 #main { margin: 6em 0 4em 20em; }

E com isso, atendemos aos requisitos básicos de layout do nosso caso de uso usando CSS2, mas ainda precisamos atender aos requisitos adicionais para funcionalidade dinâmica.

Comportamento Dinâmico Usando Técnicas Clássicas de CSS2

Os requisitos afirmavam que nosso menu de navegação, por padrão, mostraria apenas ícones, mas também poderia ser expandido para exibir texto (e poderia ser recolhido para mostrar novamente apenas ícones).

Curso CSS2 e CSS3

Vamos começar simplesmente adicionando 5em à largura do menu de navegação quando ele for expandido. Faremos isso criando uma classe CSS “expandida” que podemos adicionar ou remover dinamicamente do elemento do menu de navegação:

 #nav { left: 0; width: 5em; &.expanded { /* Sass notation */ width: 10em; } }

Aqui está um exemplo do código JavaScript (neste exemplo, usamos jQuery) que pode ser usado para alternar dinamicamente o menu de navegação entre o modo expandido e recolhido, com base no usuário clicando no ícone de alternância de navegação:

 $('.layout-classic #nav').on('click', 'li.nav-toggle', function() { $('#nav'').toggleClass('expanded'); });

E com isso, nosso menu de navegação agora pode ser expandido ou recolhido dinamicamente. Excelente.

Bem, meio que ótimo, mas não exatamente. Embora o menu de navegação agora possa expandir e contrair, ele não funciona bem com o resto da página. O menu de navegação expandido agora se sobrepõe ao subnav, o que definitivamente não é o comportamento desejado.

Isso revela uma das principais limitações do CSS2; ou seja, há muito que precisa ser codificado com valores de posição fixos. Como resultado, para os outros elementos na página que precisam ser reposicionados para acomodar o menu de navegação expandido, precisamos definir classes CSS “expandidas” adicionais com valores de posição ainda mais fixos.

 #subnav { left: 6em; width: 13em; &.expanded { left: 11em; /* move it on over */ } } #main { margin: 6em 0 4em 20; z-index: 10; &.expanded { margin-left: 25em; /* move it on over */ } }

Em seguida, precisamos estender nosso código JavaScript para adicionar ajuste dinâmico desses outros elementos também quando a alternância de navegação é clicada pelo usuário:

 $('.layout-classic #nav').on('click', 'li.nav-toggle', function() { $('#nav, #subnav, #main').toggleClass('expanded'); });

OK, isso funciona melhor.

Variações de layout usando técnicas clássicas de CSS2

Agora vamos abordar o requisito de ter algumas páginas que ocultam o menu de navegação secundária. Especificamente, queremos que o menu de navegação secundária fique oculto quando o usuário clicar no ícone "usuários" na área de navegação principal.

Curso de layout CSS

Então, primeiro, vamos criar uma nova classe “hidden” que aplica display: none :

 .hidden { display: none; }

E novamente, usaremos JavaScript (jQuery) para aplicar a classe CSS “oculta” ao elemento #subnav quando o usuário clicar no ícone de usuários:

 $('#nav.fa-user').on('click', function() { $('#subnav').toggleClass('hidden'); });

Com essa adição, o elemento #subnav fica devidamente oculto quando o usuário clica no ícone “users”, mas o espaço que ele ocupava permanece sem uso , em vez de os outros elementos se expandirem para usar o espaço desocupado pelo elemento #subnav .

Para obter o comportamento desejado quando ocultamos o elemento #subnav , empregaremos um dos seletores CSS menos conhecidos, mas altamente úteis, conhecido como seletor irmão adjacente .

Seletor CSS irmão adjacente

O seletor irmão adjacente permite especificar dois elementos, selecionando apenas as instâncias do segundo elemento que seguem imediatamente o primeiro elemento especificado.

Por exemplo, o seguinte selecionará apenas os elementos com o ID main que seguem imediatamente um elemento com o ID subnav :

 #subnav + #main { margin-left: 20em; }

O trecho de CSS acima define a margem esquerda de #main para 20em se e somente se seguir imediatamente um #subnav exibido.

No entanto, se #nav for expandido (o que faz com que a classe expanded também seja adicionada a #main , com base em nosso código anterior), movemos a margem esquerda de #main para 25em.

 #subnav + #main.expanded { margin-left: 25em; }

E, se #subnav estiver oculto, movemos a margem esquerda de #main até 6em para ficar ao lado de #nav :

 #subnav.hidden + #main { margin-left: 6em; }

(Observação: uma desvantagem de usar o seletor irmão adjacente é que ele nos força a sempre ter #subnav presente no DOM, independentemente de estar ou não sendo exibido.)

Finalmente, se #subnav estiver oculto e #nav estiver expandido, definimos a margem esquerda de #main em 11em :

 #subnav.hidden + #main.expanded { margin-left: 11em; }

Isso nos permite conectar as coisas sem nenhum código JavaScript pesado, mas também podemos ver como esse código pode se tornar complicado se adicionarmos mais elementos à página. Vemos mais uma vez que, com CSS2, é necessária muita codificação de valores de posição para que as coisas funcionem corretamente.

Aproveitando CSS3

CSS3 oferece funcionalidade significativamente aprimorada e técnicas de layout que o tornam muito mais fácil de usar e muito menos dependente de valores codificados. CSS3 é inerentemente projetado para suportar um comportamento mais dinâmico e é, nesse sentido, mais “programável”. Vamos examinar alguns desses novos recursos relacionados ao nosso caso de uso.

Função CSS3 calc()

A nova função CSS3 calc() pode ser usada para calcular valores de propriedades CSS dinamicamente (observe, porém, que o suporte varia entre os navegadores). A expressão fornecida para a função calc() pode ser qualquer expressão simples que combine os operadores aritméticos básicos ( + , - , * , / ) usando regras de precedência de operador padrão.

O uso da função calc() pode ajudar a evitar grande parte da codificação de valores exigida pelo CSS2. No nosso caso, isso nos permite alcançar a expansão CSS de forma mais dinâmica. Por exemplo:

 #nav, #subnav { position: fixed; height: calc(100% - 10em); /* replaces */ z-index: 20; }

Com a especificação de height acima usando a função calc() , alcançamos o mesmo resultado que fizemos em CSS2 com top:6em e bottom:4em , mas de uma maneira muito mais flexível e adaptável, e sem precisar codificar a posição top e bottom valores.

Layout do Flexbox CSS3

Flexbox é um novo layout introduzido no CSS3 (o suporte varia entre os navegadores). O layout flexbox simplifica a organização de elementos em uma página de maneira que se comporte de maneira previsível em diferentes tamanhos de tela, resoluções e dispositivos. Portanto, é particularmente útil no contexto de web design responsivo.

Os principais recursos incluem:

  • Posicionar elementos filho é muito mais fácil e layouts complexos podem ser obtidos de forma mais simples e com código mais limpo.
  • Os elementos filhos podem ser dispostos em qualquer direção e podem ter dimensões flexíveis para se adaptar ao espaço de exibição.
  • Os elementos filhos expandem automaticamente o contrato para se adaptarem ao espaço livre disponível.

Flexbox apresenta seu próprio conjunto exclusivo de termos e conceitos. Alguns deles incluem:

  • Recipiente flexível. Um elemento com sua propriedade de display definida como flex ou inline-flex que serve como elemento de contêiner para itens flex.
  • Artigo flexível. Qualquer elemento dentro de um contêiner flexível. (Observação: o texto contido diretamente em um contêiner flexível é encapsulado em um item flexível anônimo.)
  • Eixos . Cada layout flexbox tem uma flex-directio que designa o eixo principal ao longo do qual os itens flexíveis são dispostos. O eixo transversal é então o eixo perpendicular ao eixo principal.
  • Linhas. Os itens flexíveis podem ser dispostos em uma única linha ou em várias linhas de acordo com a propriedade flex-wrap .
  • Dimensões. Os equivalentes de altura e largura do flexbox são main size e cross size , que especificam os tamanhos do eixo principal e do eixo cruzado do contêiner flex, respectivamente.

OK, então com essa breve introdução, aqui está a marcação alternativa que podemos usar se estivermos usando um layout flexbox:

 <body class="layout-flexbox"> <header></header> <div class="content-area"> <nav></nav> <aside></aside> <main></main> </div> <footer></footer> </body>

Para nosso caso de uso de exemplo, nosso layout principal (cabeçalho, conteúdo, rodapé) é vertical, então configuraremos nosso flexbox para usar um layout de coluna:

 .layout-flexbox { display: flex; flex-direction: column; }

Embora nosso layout principal seja vertical, os elementos em nossa área de conteúdo (nav, subnav, main) são dispostos horizontalmente. Cada contêiner flexível pode definir apenas uma direção (ou seja, seu layout deve ser horizontal ou vertical). Portanto, quando o layout exige mais do que isso (um caso comum é para um layout de aplicativo), podemos aninhar vários contêineres um dentro do outro, cada um com um layout direcional diferente.

É por isso que adicionamos um contêiner extra (que chamei de content-area ) envolvendo #nav , #subnav e #main . Dessa forma, o layout geral pode ser vertical, enquanto o conteúdo da área de conteúdo pode ser disposto horizontalmente.

Agora para posicionar nossos itens flex vamos usar a propriedade flex que é um atalho para flex: <flex-grow> <flex-shrink> <flex-basis>; . Essas três propriedades flexíveis são as que determinam como nossos itens flexíveis distribuem qualquer espaço livre restante entre eles na direção do fluxo, como segue:

  • flex-grow: especifica quanto um item pode crescer em relação ao resto dos itens flexíveis dentro do mesmo container
  • flex-shrink: especifica como um item pode encolher em relação ao restante dos itens flexíveis dentro do mesmo contêiner
  • flex-basis: especifica o tamanho inicial de um item (ou seja, antes de diminuir ou aumentar)

Contêineres flex CSS: Cross vs main

Definir flex-grow e flex-shrink ambos para zero significa que o tamanho do item é fixo e não aumentará ou diminuirá para acomodar mais ou menos espaço livre disponível. Isto é o que fazemos para nosso cabeçalho e rodapé, pois eles têm um tamanho fixo:

 #header { flex: 0 0 5em; } #footer { flex: 0 0 3em; }

Para que um item ocupe todo o espaço livre disponível, defina seus valores flex-grow e flex-shrink como 1 e defina seu valor flex-basis como auto . Isso é o que fazemos para a área de conteúdo, pois queremos que ela ocupe todo o espaço livre disponível.

E como dissemos antes, queremos que os itens dentro content-area dispostos na direção da linha, então adicionaremos display: flex ; e flex-direction: row; . Isso torna a área de conteúdo um novo contêiner flexível para #nav , #subnav e `#main.

Então, aqui está o que acabamos com o CSS para content-area :

 .content-area { display: flex; flex-direction: row; flex: 1 1 auto; /* take up all available space */ margin: 1em 0; min-height: 0; /* fixes FF issue with minimum height */ }

Na área de conteúdo, #nav e #subnav têm tamanhos fixos, então apenas definimos a propriedade flex de acordo:

 #nav { flex: 0 0 5em; margin-right: 1em; overflow-y: auto; } #subnav { flex: 0 0 13em; overflow-y: auto; margin-right: 1em; }

(Observe que eu adicionei overflow-y: hidden a essas especificações CSS para superar o conteúdo que excede e transborda a altura do contêiner. Na verdade, o Chrome não precisa disso, mas o FireFox sim.)

#main ocupará o restante do espaço livre:

 #main { flex: 1 1 auto; overflow-y: auto; }

Tudo isso parece bom, então agora vamos adicionar nosso comportamento dinâmico a isso e ver como isso acontece.

O JavaScript é idêntico ao que tínhamos antes (exceto aqui, a classe de contêiner do elemento CSS que estamos especificando é layout-flexbox enquanto antes era layout-classic ):

 $('.layout-flexbox #nav').on('click', 'li.nav-toggle', function() { $('#nav').toggleClass('expanded'); });

Adicionamos a classe expanded ao CSS da seguinte forma:

 #nav { flex: 0 0 5em; /* collapsed size */ margin-right: 1em; overflow-y: auto; &.expanded { flex: 0 0 10em; /* expanded size */ } }

E voilá!

Observe que desta vez não precisamos informar outros itens sobre a mudança de largura, já que o layout flexbox trata de tudo isso para nós.

A única coisa que resta então é esconder o sub nav. E adivinha? Isso “simplesmente funciona” também, sem nenhuma alteração adicional, usando o mesmo código JavaScript de antes. O Flexbox conhece o espaço livre e automaticamente faz nosso layout funcionar sem código extra. Muito legal.

O Flexbox também fornece algumas maneiras interessantes de centralizar elementos verticais e horizontais. Percebemos aqui o quão importante é para uma linguagem de apresentação incluir a noção de espaço livre e quão escalável nosso código pode se tornar usando esses tipos de técnicas. Por outro lado, os conceitos e notação aqui podem demorar um pouco mais para dominar do que o CSS clássico.

Layout de grade CSS3

Se o Flexbox Layout está na ponta do CSS3, então o Grid Layout pode ser dito estar no seu limite. A especificação W3C ainda está em um estado de rascunho e ainda tem suporte a navegadores bastante limitado. (Ele é ativado no Chrome por meio do sinalizador “recursos experimentais da plataforma da Web” em chrome://flags).

Dito isto, eu pessoalmente não considero este projecto revolucionário. Em vez disso, como afirmam os princípios de design do HTML5: “Quando uma prática já é difundida entre os autores, considere adotá-la em vez de proibi-la ou inventar algo novo”.

Assim, grades baseadas em marcação são usadas há muito tempo, então agora o CSS Grid Layout está realmente seguindo esse mesmo paradigma, oferecendo todos os seus benefícios e muito mais na camada de apresentação sem requisitos de marcação.

A ideia geral é ter um layout de grade predefinido, fixo ou flexível onde possamos posicionar nossos elementos. Assim como o flexbox, ele também funciona com o princípio do espaço livre e permite definir “direções” verticais e horizontais no mesmo elemento, o que traz vantagens em tamanho de código e flexibilidade.

O layout de grade apresenta 2 tipos de grades; ou seja, explícito e implícito . Para simplificar, vamos nos concentrar em grades explícitas neste.

Assim como o flexbox, o layout Grid apresenta seu próprio conjunto exclusivo de termos e conceitos. Alguns deles incluem:

  • Recipiente de grade. Um elemento com sua propriedade de display definida como “grid” ou “inline-grid” no qual os elementos contidos são dispostos posicionando e alinhando a uma grade predefinida (modo explícito). A grade é um conjunto de linhas de grade horizontais e verticais que dividem o espaço do contêiner de grade em células de grade. Existem dois conjuntos de linhas de grade; uma para definir as colunas e uma ortogonal a ela para definir as linhas.
  • Trilha da grade. O espaço entre duas linhas de grade adjacentes. Cada faixa de grade é atribuída a uma função de dimensionamento, que controla a largura ou a altura da coluna ou linha e, portanto, a distância entre suas linhas de grade delimitadoras.
  • Célula de grade. O espaço entre duas linhas adjacentes e duas linhas de grade de colunas adjacentes. É a menor unidade da grade que pode ser referenciada ao posicionar itens da grade.
  • Comprimento flexível. Uma dimensão especificada com a unidade fr , que representa uma fração do espaço livre no contêiner de grade.

Esboço de layout de grade CSS

Aqui está a marcação alternativa que podemos usar se estivermos usando um layout de grade:

 <body class="layout-grid"> <header></header> <nav></nav> <aside></aside> <main></main> <footer></footer> </body>

Observe que com este layout, não precisamos de um wrapper extra para a área de conteúdo como fizemos para o flexbox, pois esse tipo de layout nos permite definir a designação do espaço do elemento em ambas as direções no mesmo contêiner de grade.

Vamos nos aprofundar no CSS agora:

 .layout-grid { display: grid; grid-template-columns: auto 0 auto 1em 1fr; grid-template-rows: 5em 1em 1fr 1em 3em; }

Definimos display: grid; em nosso recipiente. As propriedades grid-template-columns e grid-template-rows são especificadas como uma lista de espaços entre as faixas de grade. Em outras palavras, esses valores não são a posição das linhas de grade; em vez disso, eles representam a quantidade de espaço entre duas faixas.

Observe que as unidades de medida podem ser especificadas como:

  • um comprimento
  • uma porcentagem do tamanho do contêiner de grade
  • uma medição do conteúdo que ocupa a coluna ou linha, ou
  • uma fração do espaço livre na grade

Assim, com grid-template-columns: auto 0 auto 1em 1fr; nós teremos:

  • 1 trilha definindo 2 colunas de largura auto ( #nav space)
  • 1 medianiz de 0 (a margem para #subnav está no nível do elemento, pois pode estar presente ou não, assim evitamos ter dupla medianiz)
  • 1 trilha definindo 2 colunas de largura auto (espaço #subnav )
  • 1 calha de 1em
  • 1 faixa usando 1fr para #main (ocupará todo o espaço restante)

Aqui usamos muito o valor auto para a faixa, o que nos permite ter colunas dinâmicas onde a posição e o tamanho das linhas são definidos pelo seu conteúdo máximo. (Portanto, precisaremos especificar os tamanhos dos elementos #nav e #subnav , o que faremos em breve.)

Da mesma forma, para as linhas de linha temos grid-template-rows: 5em 1em 1fr 1em 3em; que define que nosso #header e #footer sejam corrigidos e todos os elementos entre eles usem o espaço livre restante enquanto usam calhas de 1em .

Agora vamos ver como colocamos os elementos reais a serem posicionados em nossa grade definida:

 #header { grid-column: 1 / 6; grid-row: 1 / 2; } #footer { grid-column: 1 / 6; grid-row: 5 / 6; } #main { grid-column: 5 / 6; grid-row: 3 / 4; overflow-y: auto; }

Isso especifica que queremos que nosso cabeçalho fique entre as linhas de grade 1 e 6 (largura total) e entre as linhas de grade 1 e 2 para nossas linhas. O mesmo para o rodapé, mas entre as duas últimas linhas (em vez das duas primeiras). E a área principal está configurada adequadamente para o espaço que deve ocupar.

Observe que as propriedades grid-column e grid-row são abreviações para especificar grid-column-start / grid-column-end e grid-row-start / grid-row-end , respectivamente.

OK, então volte para o #nav e o #subnav . Como anteriormente colocamos #nav e #subnav na faixa com valores automáticos, precisamos especificar a largura desses elementos (o mesmo para o modo expandido, apenas alteramos sua largura e o Grid Layout cuida do resto).

 #nav { width: 5em; grid-column: 1 / 2; grid-row: 3 / 4; &.expanded { width: 10em; } } #subnav { grid-column: 3 / 4; grid-row: 3 / 4; width: 13em; /* track has gutter of 0, so add margin here */ margin-left: 1em; }

Então agora podemos alternar nosso #nav e também ocultar/remover o #subnav e tudo funciona perfeitamente! O layout de grade também nos permite usar aliases para nossas linhas, de modo que, eventualmente, alterar as grades não quebrará o código, pois ele é mapeado para um nome e não para uma linha de grade. Definitivamente ansioso para que isso seja mais amplamente suportado por mais navegadores.

Conclusão

Mesmo com as técnicas clássicas de CSS, há muito mais que pode ser realizado do que muitos desenvolvedores da Web imaginam ou aproveitam. Dito isto, muito disso pode ser bastante tedioso e pode envolver a codificação de valores repetidamente em uma folha de estilo.

CSS3 começou a fornecer técnicas de layout muito mais sofisticadas e flexíveis que são significativamente mais fáceis de programar e que evitam muito do tédio das especificações CSS anteriores.

Dominar essas técnicas e paradigmas – tanto para CSS2 quanto CSS3 – é essencial para aproveitar tudo o que o CSS tem a oferecer para otimizar tanto a experiência do usuário quanto a qualidade do seu código. Este artigo realmente representa apenas a ponta do iceberg de tudo o que há para aprender e tudo o que pode ser realizado com o poder e a flexibilidade do CSS. Têm-no!

Relacionado: *Explorando o SMACSS: arquitetura escalável e modular para CSS*