Índice

Introdução

Hey Hey pessoal! Para não perder o ritmo de carnaval, vamos a mais um post! Como alguns reclamaram que não teve playlist no post antigo, já vou deixando aqui a playlist que estou ouvindo agora Trabalhando até Tarde, e nossa, que playlist foda demais! Várias músicas mesclando um eletro, chill, house, etc.

O post de hoje vai ser relacionado a uma metodologia CSS que eu não conhecia e passei a conhecer lá na HUGE. Confesso que a primeira, segunda, terceira e até a quarta vez que eu vi, achei bem ruinzinha. Mas há uns dias eu peguei para ler, fazer uns testes e até assistir uns vídeos e bom, fui convertido!

Resolvi fazer esse post por alguns motivos e eles foram:

O post será fortemente baseado na ÓTIMA documentação do RSCSS, se você não gostar da forma com que escrevo ou quiser simplesmente partir para o original, só clicar ali =)

Eu irei escrever os exemplos em SCSS, porém eles podem ser portados para qualquer pre-processador e até mesmo CSS puro tem maluco para tudo.

O que vem a ser o RSCSS?

Quanto maior o projeto vai ficando, mais elementos são criados e mais CSS é criado. Isso pode acarretar em linhas e mais linhas de CSS, que se não forem bem cuidadas, poderão causar várias confusões. Você já se pegou fazendo as seguintes perguntas:

O RSCSS é uma tentativa de fazer essas coisas terem sentido. Ele não é um framework, é simplesmente um conjunto de ideias para orientar o seu processo de construção de CSS sustentável para qualquer site ou aplicação.

Por que usar metodologias?

O CSS pode parecer complicado, principalmente quando você escreve de qualquer maneira. Mas ele não precisa ser assim. Se você cria um padrão de escrita, que pode ser passado a outros do time e que você mesmo entenda como funciona, todo o resto acaba se tornando bem simples.

Existem várias metodologias de escrita, temos a metodologia BEM que é bastante famosa, temos também o OSCSS, SMACSS, SuitCSS, dentre outras…

Escrevendo CSS

O CSS de hoje em dia nos permite componentizar tudo muito facilmente, ainda mais com os Pre-processadores nos ajudando bastante ali por trás. O problema é que da mesma forma que os pre-processadores nos ajudam, eles também podem nos atrapalhar bastante.

Atire a primeira pedra quem nunca fez um grande uso de nesting como:

.nav {
    ul {
        li {
            a { 
                ...
            }
        }
    }
}

O problema de se fazer isso ali, é que quando temos um grande número de propriedades, a leitura já começa a ficar dificultada, como:

.nav {
    width: 100%;
    padding: 10px 25px;
    position: fixed;

    ul {
        max-width: 940px;
        li {
            display: inline-block;
            border: 1px solid #ccc;
            padding: 10px 50px;

            a { 
                color: #333;

                &:hover {
                    text-decoration: none;
                }
            }
        }
    }
}

Sem contar a dificuldade de leitura daquilo ali, ainda estamos gerando um código assim:

.nav ul li a { ... }

Isso é horrível, pois aumenta bastante a especificidade e se eu num futuro quiser mudar um pouco das propriedades, vou ter que criar algo para sobrescrever isso, o que vai acabar sujando ainda mais o meu código.

Outro problema de se utilizar tags diretas como ul, li, a, é que podemos acabar sem querer modificando a aparência desse elemento em algum outro lugar que cumpra as mesmas regras.

Pensando no exemplo de um card, usando esse tipo de abordagem de nesting, acabaríamos criando algo mais ou menos assim:

Abordagem de nesting na criação de um card

Tentando melhorar...

Tentando evitar esse tipo de coisa, vieram metodologias em que são utilizadas classes para todos os elementos do css, que é o caso do BEM. Onde você escreve o CSS na forma Block, Element, Modifier. Para o mesmo exemplo do card, teríamos algo assim:

Abordagem utilizando BEM

O problema dessa abordagem, é que apesar de no CSS evitar muitos problemas, ela suja e muito o HTML. Essa abordagem tem outro side-effect bem ruim, se vamos escrever classes gigantescas tanto do lado do css, quanto do lado do html, acabamos aumentando o tamanho final dos arquivos, que é algo que não queremos também.

Dirty HTML usando BEM

Olhando a abordagem inicial de css nativo (nesting) e essa abordagem do BEM, podemos ter um gráfico assim:

Gráfico mostrando como funciona com BEM e CSS puro

Se temos o markup limpo, colocando só classes base e usando nesting, acabamos tendo um css sujo e difícil de ler. Porém se escrevemos um CSS mais organizado, tendo classes para cada elemento, acabamos tendo um html sujo.

E se existisse uma maneira de ter os dois limpos?

Dessa forma nasceu o RSCSS! A ideia principal dele é criar um componente pai, que irá governar os elementos internos a partir do child selector >, também chamado de seletor filho ou descendente. Se você não conhece esse seletor, aconselho ler esse post seletores css importantes para aprender, que eu fiz no ano passado.

O mesmo exemplo do card usando essa metodologia ficaria:

Abordagem do RSCSS

Trabalhando com RSCSS

1. Tudo é um componente

A primeira coisa que você deve fazer é pensar em tudo como se fossem componentes. Considere cada pedaço de sua interface como um componente individual. Segue exemplo de um form dentro de uma navbar:

Search Form dentro de uma navbar

1.1 Nomeando Componentes

Os componentes deverão ter pelo menos duas palavras, separadas por um traço. Exemplos:

2. Elementos

Elementos são coisas dentro do seu componente:

Elementos dentro do search-form

2.1 Nomeando elementos

Cada componente deve ter elementos. E eles devem ter classes com somente uma palavra.

.search-form {
    > .field {...}
    > .action {...}
}

2.2 Elementos seletores

Prefira usar o seletor filho > sempre que possível. Isso previne que a propriedade passe para componentes internos indesejados, e também performa melhor que seletores descendentes.

.article-card {
    .title { /* bom */ }
    > .author { /* melhor ainda */ }
}

2.3 Múltiplas palavras

Para aqueles elementos que precisam de uma ou mais palavras, concatene elas sem traços ou underscore.

.profile-box {
  > .firstname { /* ... */ }
  > .lastname { /* ... */ }
  > .avatar { /* ... */ }
}

2.4 Evite usar tags como seletores

Use classe sempre que possível. Tags são ok, mas podem vir com uma pequena perda de performance por não serem muito específicas e também podem não ser tão descritivas.

.article-card {
  > h3    { /* ✗ evite */ }
  > .name { /* ✓ melhor */ }
}

3. Variações

Componentes podem ter variações, assim como os elementos também.

Exemplo de variações

3.1 Nomeando variações

As classes de variações devem ser prefixadas por um traço. É legal pensar nisso como forma de comandos no terminal, onde a gente tem o comando principal e podemos passar opções sempre como -algumaCoisa.

.like-button {
  &.-wide { /* ... */ }
  &.-short { /* ... */ }
  &.-disabled { /* ... */ }
}

3.2 Variações nos elementos

Assim como os componentes, podemos querer variar os elementos. Preste atenção, essa variação é específica daquele elemento (classe), portanto, não há problemas em colocá-lo adjacente, como mostrado abaixo.

.shopping-card {
  > .title { /* ... */ }
  > .title.-small { /* ... */ }
}

3.3 Por que usar prefixos com traço?

Alguns dos motivos de se usar são:

4. Componentes aninhados (nested)

Componentes aninhados

<div class='article-link'>
  <div class='vote-box'>
    ...
  </div>
  <h3 class='title'>...</h3>
  <p class='meta'>...</p>
</div>

Algumas vezes precisamos ter componentes dentro de componentes. Aqui vão algumas dicas de como se fazer:

4.1 Variações

Evite modificar o componente interno através do commponente principal.

.article-header {
  > .vote-box > .up { /* ✗ evite isso */ }
}

Ao invés disso, prefira adicionar uma variação ao componente interno e aplicar a partir dele.

<div class='article-header'>
  <div class='vote-box -highlight'>
    ...
  </div>
  ...
</div>
.vote-box {
  &.-highlight > .up { /* ... */ }
}

4.2 Simplifique componentes internos

As vezes, quando usando componentes aninhados, seu markup pode ficar um pouco sujo:

<div class='search-form'>
  <input class='input' type='text'>
  <button class='search-button -red -large'></button>
</div>

Você pode simplificar isso, utilizando a propriedade de @extend de seu pre-processador:

<div class='search-form'>
  <input class='input' type='text'>
  <button class='submit'></button>
</div>
.search-form {
  > .submit {
    @extend .search-button;
    @extend .search-button.-red;
    @extend .search-button.-large;
  }
}

Assim, seu elemento .submit irá receber todas as propriedades que precisa, de uma forma que não fique com um markup sujo.

5. Layouts

Exemplo de cards em layouts

5.1 Evite propriedades de posicionamento

Componentes devem ser criados de uma forma que possam ser reutilizados em diferentes contextos. Evite colocar essas propriedades nos componentes:

5.2 Defina posicionamento nos pais

Se você realmente precisa definir algum tipo de posicionamento no componente, faça isso no componente pai que irá contê-lo. No exemplo abaixo, note que a largura e float são aplicadas no contexto do componente list, não no componente em si.

.article-list {
  & {
    @include clearfix;
  }

  > .article-card {
    width: 33.3%;
    float: left;
  }
}

.article-card {
  & { /* ... */ }
  > .image { /* ... */ }
  > .title { /* ... */ }
  > .category { /* ... */ }
}

6. Helpers

Essas classes tem como uso principal, sobrescrever valores, coloque-as em arquivos separados e as nomeie com underscore. Essas classes, em geral, são marcadas com !important. Portanto, use com muita cautela e as evite o máximo possível.

._unmargin { margin: 0 !important; }
._center { text-align: center !important; }
._pull-left { float: left !important; }
._pull-right { float: right !important; }

7. Estrutura CSS

O RSCSS não tem uma premissa forte para estrutura não, tendo somente como único conselho, colocar um componente por arquivo.

/* css/components/search-form.scss */
.search-form {
  > .button { /* ... */ }
  > .field { /* ... */ }
  > .label { /* ... */ }

  // variants
  &.-small { /* ... */ }
  &.-wide { /* ... */ }
}

E, então chamar esses componentes usando o glob matching:

@import 'components/*';

Exemplo

Para quem gosta de aprender com exemplo, segue abaixo o exemplo de um card implementado seguindo a metodologia do RSCSS:

See the Pen A simple use case of RSCSS by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

Repare que o nesting de só até dois elementos foi respeitado, que o componente principal tem duas palavras (photo-card) e que os elementos possuem somente um nome.

Conclusão

Bom galera, sei que o post ficou grandinho, eu mesmo não esperava fazer tão grande, acabou que eu basicamente traduzi toda a documentação e falei um pouquinho mais até. Entenda que assim como toda metodologia, ela pode funcionar ou não para você, a ideia aqui é passar mais uma opção para que você escolha a que melhor se adaptar. Eu não gostei muito quando vi, hoje já estou achando bastante simples e eficiente. Outro ponto importante é, se você trabalha com uma equipe, não saia mudando tudo sem avisar, comunique a todos, mostre os pontos e, caso tenha um consenso, sigam todos o mesmo padrão.