CSS

23 set, 2015

Falando em organização… – Parte 02

Publicidade

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!