Fácil de aprender, difícil de dominar. Não é porque tá funcionando que tá bom” –Raphael Fabeni sobre CSS
Dando continuidade a série sobre minha organização e fluxo de trabalho atual, vou contar um pouco sobre como tenho trabalhado o CSS.
“CSS é muito fácil!”. Será?
Durante anos escrevemos CSS como se não houvesse amanhã e tínhamos como maiores problemas as diferenças de renderização no IE(ca). E já não era simples.
Mas nos últimos tempos, tivemos que começar a fazer projetos que funcionassem em diferentes resoluções, diferentes navegadores, diferentes dispositivos e que tivessem performance, acessibilidade, fossem bonitos e escaláveis.
Além disso, o CSS começou a ser usado para animações (inclusive em SVG), controlar estados e até mesmo criar comportamentos que só eram feitos através de JavaScript.
Um CSS sem planejamento e mal construído pode arruinar um projeto, que a longo prazo vai virar um monstro, cheio de “janelas quebradas”.
O tal do Atomic Design
Junto com a necessidade de organizar o CSS, surgiram vários termos e metodologias que visam melhorar nosso controle sobre o código.
No último Meetup CSS, o Rafael Rinaldi deu uma verdadeira aula sobre diferentes tipos de Arquitetura CSS. Vocês podem assistir o vídeo e dar uma estudada nos slides.
Dentro dessas metodologias, a que mais me agradou foi o conceito de Atomic Design, proposta pelo Brad Frost, que deu origem ao Pattern Lab. Ela me agradou de cara, e ia de encontro com tudo que pensava sobre o desenvolvimento de CSS. Em 2013 eu já estava usando um conceito parecido e incorporei várias ideias no meu workflow.
Mas foi apenas no segundo semestre de 2014 que me aproximei de vez do Atomic Design e cheguei a uma estrutura muito parecida com a que foi proposta inicialmente.
Metodologias não precisam ser seguidas à risca e servem mais para nortear o trabalho. Portanto, considerem o que vou explicar abaixo uma livre interpretação do conceito original.
Organização dos arquivos CSS
Segue um esquema de organização com alguns exemplos de arquivos, mas lembre-se: são apenas exemplos e podem variar conforme o projeto.
Como sempre explico, estou dando um exemplo de estrutura em LESS, mas ela serve para QUALQUER pré-processador. Dentro das (), adicionei uma pequena descrição de cada pasta principal.
less/ ├── _core/ (Configurações básicas do projeto) │ ├── mixins/ │ |── colors │ ├── fonts │ ├── grid │ ├── margins │ ├── media-queries │ ├── mixins │ ├── normalize │ ├── type | ├── atoms/ (Classes individuais e elementos pequenos e reutilizáveis) │ ├── global/ │ | ├── scaffolding (html, body) │ | ├── utilies (.hidden, .show, .sr-only) | | │ ├── buttons/ │ | ├── btn │ | ├── btn-link | | │ ├── text/ │ | ├── headings (h1, h1, h3, h4, h5, h6) │ | ├── paragraph (p) │ | ├── blockquote │ | ├── code │ | ├── link (a) │ | ├── hr │ | ├── date (.date) │ | ├── inline (b, i, strong, em, u, stroke, cite ...) | | │ ├── list/ │ | ├── unordered │ | ├── ordered │ | ├── definition | | │ ├── images/ │ | ├── icons │ | ├── img │ | ├── logo | | │ ├── forms/ │ | ├── label │ | ├── input │ | ├── input-file │ | ├── select │ | ├── radio │ | ├── checkbox | | │ ├── tables/ │ ├── tables | ├── molecules/ (Cria um elemento 'pai' para modificar os atomos) │ ├── blocks/ │ | ├── toolbar │ | ├── filterbar | | │ ├── media/ │ | ├── banner │ | ├── media | | │ ├── forms/ │ | ├── search │ | ├── form-group | | │ ├── navigation/ │ | ├── navbar │ | ├── breadcrumbs │ | ├── pagination │ | ├── tabs | | │ ├── text/ │ | ├── address │ | ├── page-header │ | ├── author │ | ├── article-text │ | ├── captions | | │ ├── components/ (Componentes que usam JavaScript) │ ├── carousel │ ├── collapse │ ├── tooltip │ ├── popover │ ├── modal | ├── organisms/ (Estruturas maiores do projeto, que podem modificar átomos e móleculas) │ ├── header │ ├── footer │ ├── main │ ├── wrap │ ├── content │ ├── comments | ├── templates/ (Sistemas de grids e alinhamentos de templates) │ ├── grids │ ├── container │ ├── thumbnails | ├── pages/ (Estiliza páginas individualmente) │ ├── home | ├── vendor/ (Estiliza dependencias externas)
Exemplos práticos
Core
_core/margins: // // Margins // -------------------------------------------------- @space: 20px; // Regular space margin @space-xs: (@space / 4); // Extra small space margin @space-sm: (@space / 2); // Small space margin @space-md: (@space * 2); // Medium space margin @space-lg: (@space * 3); // Large space margin _core/type: // // Typography // -------------------------------------------------- #type { // Headings // -------------------------------------------------- .h1() { .font(36, 700); margin-bottom: @space; } // Paragraphs // -------------------------------------------------- .p1() { .font(16); } }
Observem que defino alguns mixins e configurações reaproveitáveis em todo o projeto.
Atoms
Atoms/headings:
// // Headings // -------------------------------------------------- h1 { margin: 0; } h1 { #type > .h1(); } atoms/paragraph: // // Paragraph // -------------------------------------------------- p { #type > .p1(); margin: 0 0 @space; &:last-child { margin: 0; } }
São definidas classes ou elementos bases, que serão utilizadas e modificadas conforme a necessidade das ‘molecules’, ‘organisms’ ou ‘pages’.
Os elementos devem ser únicos, nunca aninhados.
Molecules
Molecules/page-header:
// // Page Header // -------------------------------------------------- .page-header { text-align: center; h1 { border-bottom: @gray-lighter solid 1px; color: @gray-light; padding-bottom: @space-sm; } p { color: @gray; } }
Modifica os átomos para a criação de um componente específico.
Organisms
Organisms/header:
// // Header // -------------------------------------------------- .header { // Page Header // -------------------------------------------------- .page-header { text-align: center; } }
Modifica os átomos e moléculas para a criação de uma sessão do projeto.
Pages
Pages/home:
// // Home // -------------------------------------------------- .home { // Header // -------------------------------------------------- .header { position: fixed; top: 0; right: 0; left: 0; } // Page Header // -------------------------------------------------- .page-header { padding: @space @space-lg; } }
Modifica os átomos, moléculas e organismos para a criação de uma página específica do projeto.
Dicas rápidas
- Não se prenda à metodologia. Abra espaço para implementar mudanças que vão melhorar a utilização, seja para uso próprio ou para um escopo especifico;
- A organização das pastas é muito importante. Você precisa se sentir confortável com a estrutura para não ficar pensando aonde está determinado arquivo;
- Não faça aninhamentos maiores do que três níveis – geralmente você não vai precisar passar do segundo nível. Quando chegar ao terceiro, ligue o sinal de alerta e confirme se realmente faz sentido;
- Lembre-se que seu workflow não é definitivo. Sempre surgirão ideias e ferramentas para agregar ao seu trabalho. Esteja de cabeça aberta para mudanças. Porém não faça alterações drásticas antes de amadurecer a ideia.
Um plus sobre ‘Media Queries’
No começo do ano eu escrevi um artigo sobre CSS Modular com Mobile First e agora essa ideia fica ainda mais aplicável.
Não precisa mais ter um arquivo específico para ajustar media-queries. Nessa organização de CSS, cada elemento pode ter sua própria customização aplicada seguindo a ideia do Mobile First.
Como?
Vamos imaginar que o .header
precise ser absoluto em resoluções médias, fixo em resoluções grandes e tenha o background branco em telas menores:
organisms/header: // // Header // -------------------------------------------------- .header { padding: @space; // Padrão para todas as resoluções @media (max-width: @screen-xs-max) { background: #fff; } @media (min-width: @screen-sm-min) { position: absolute; top: 0; right: 0; left: 0; } @media (min-width: @screen-lg-min) { position: fixed; // O top, right e left está escalando na resolução 'sm', não precisa repetir :) } }
Se tiverem alguma dúvida ou quiserem debater sobre o assunto, saiba que o Disqus escala e podem usar os comentários sem medo.
Abraços!