Arquitetura OOCSS / BEM / SMACSS

8

Eu estive trabalhando neste artigo para organizar meu código de front-end. Ele faz referência a artigos no BEM / SMACSS, que por sua vez fazem referência a outros artigos.

Estou realmente tentando entender quais são as melhores práticas ... Tenho alguns dias para estabelecer esse "padrão" e, em seguida, tenho que gravar um projeto de cronograma de alta prioridade / alta visibilidade / tempo limitado. Como tal, gostaria de garantir que estou começando com uma base que será dimensionada como meu aplicativo.

Dado um componente chamado segment... Estou criando páginas que terão ~ 10 segmentspor página. Cada segmentum compartilhará a mesma classe base. No entanto, alguns segmentsterão modificadores (cores de fundo diferentes). Além disso, os elementos dentro de cada bloco (na abordagem BEM) também terão modificadores. Para demonstrar, aqui está uma implementação simples (com apenas um elemento arrow, enquanto meu site completo terá 4-5 elementos em cada segment):

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow--orange {
    @extend .segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--white {
    @extend .segment__arrow;
    background-image: url('/images/arrow_white.png');
}

Portanto, esta é a abordagem de classe única:

<div class="segment__arrow--white"> ... </div>

Como alternativa, eu poderia usar a abordagem de várias classes:

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow--orange {
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--white {
    background-image: url('/images/arrow_white.png');
}

Onde minha marcação seria:

<div class="segment__arrow segment__arrow--white"> ... </div>

Terceiro, eu poderia fazer:

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow.orange {
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow.white {
    background-image: url('/images/arrow_white.png');
}

E então minha classe def seria

<div class="segment__arrow orange"> ... </div>

Talvez até namespacing orange com algo parecido sa_orangecom evitar seletores soltos.

O resultado final que estou procurando é menos código / mais fácil de manter (o que provavelmente exclui a abordagem de classe única (opção 1), conforme descrito neste ótimo artigo sobre arquitetura escalável. A abordagem de várias classes (opção 2) resulta em muita verbosidade (especialmente no meu HTML), mas é extremamente explícita.O terceiro usa uma abordagem de várias classes, mas não usa modificadores no namespace (como .segment__arrow), por isso é um pouco menos detalhado (mas também menos explícito e superior) potencial de colisões).

Alguém com experiência no mundo real com esse material tem algum feedback sobre a melhor maneira de abordar isso?

Scott Silvi
fonte
Desacoplar os modificadores dos elementos vai contra esses princípios, certo? .orangenão tem significado apenas como modificador. Não vejo um grande problema em usar .segment__arrow--orangejunto com sua abordagem multiclasse. Obviamente, em projetos maiores, seu HTML pode ficar um pouco fora de controle (muitas classes).
kleinfreund
Fora de férias. Obrigado pela resposta. Sim, é por isso que estive pensando na terceira opção. Você está correto, isso contraria esses princípios, mas, à medida que o projeto é dimensionado, estou imaginando uma classe = "segmento__ segmento estreito - segmento laranja - segmento laranja - é segmento visível - estreito - outra coisa" ... e isso apenas começa a ficar um código pouco malcheiroso para mim ...
Scott Silvi
Verdade. Não se deve dirigir esse ônibus BEM inteiro longe demais. Nem tudo precisa ser BEMificado.
precisa saber é o seguinte

Respostas:

8

Há muito tempo que uso e recomendo a abordagem explícita de várias classes (o segundo exemplo), pois é a mais universal, sustentável e coerente. Aqui vou tentar apoiar esta reivindicação.

Classe única

Essa abordagem tem um grande problema quando existem duas ou mais categorias de modificadores. Por exemplo, um botão. Com modificadores pequeno , grande , enorme para tamanho e primário , sucesso , informações e aviso para "cor". Além das 7 (= 3 + 4) classes usuais, também é necessário criar todas as 12 combinações:

.button--small--primary
.button--small--success
.button--small--info

Até agora, um pouco inconveniente, mas não um desastre.

Outro aborrecimento - um maior - é que a ordem correta "tamanho primeiro, cor segundo" deve ser usada e, portanto, lembrada (e bem documentada).

O pior é quando o JavaScript está envolvido. Deseja alterar a "cor" deste botão, mas mantém o tamanho atual? Analise o atributo da classe! Deseja apenas remover o modificador de sucesso ? Analise o atributo da classe!

Conte que, por exemplo, o Bootstrap possui 7 "cores", 4 tamanhos e estados ativo / desativado; para o qual 119 (= 13 + [7 * 4 + 7 * 2 + 4 * 2] + 7 * 4 * 2) classes devem ser declaradas para manter a abordagem de classe única! Esse é o grande problema.

A multi-classe explícita exigiria apenas 13 classes (uma para cada modificador). A ordem seria arbitrária. Por fim, adicionar, remover e alterar um enquanto preserva outros seria no jQuery parecido com:

$('#login-button').removeClass('button--primary').addClass('button--success');

Atalho multi-classe

Em primeiro lugar, como você mencionou, há um potencial de colisões - uma coisa ruim por si só.

Em segundo lugar, o que isso também significa é que ele .segment__arrow.orangetem uma especificidade mais alta e não pode ser substituído por um único seletor de classe. Isso geralmente ocorre quando um elemento é, por exemplo, não apenas um botão grande, mas também um botão de login . Seu código seria semelhante a:

<a href="#" class="button large primary login__button">Log in</a>

Pode-se ter um preenchimento esquerdo e direito maior no botão de login, mas preservar a altura do tamanho grande . Isso resultaria em seletores cada vez mais específicos, que nos levariam ao inferno da especificidade - um lugar em que o OOCSS deveria nos salvar.

É evidente que isso não aconteceria na abordagem explícita de várias classes .

Multi-classe explícita

O único problema (até onde sei) disso é que existem algumas classes às vezes bastante longas na marcação. Eu admito isso.

Permitam-me observar que isso é apenas uma questão de gosto do desenvolvedor, pois tem um efeito desprezível (para nada) no desempenho. A compactação padrão cuidará disso.

Dito isto, usar um bom IDE ajudará a escrevê-los (sim, eu sei, ainda parecerá um pouco ridículo).

Por um lado, eu diria que ver classes tão longas obriga a pensar mais sobre a estrutura; por exemplo, se não seria melhor introduzir um novo componente (reutilizável) em vez de aninhar-o em outra coisa.

Robin Pokorny
fonte
0

Estou debatendo com meus colegas de equipe sobre esses problemas de classe única / múltipla agora

Aqui estão algumas das minhas opiniões pessoais com base nas melhores práticas

Melhores práticas

  • html declara elementos
  • Controles CSS renderizados

A aula única está sempre seguindo as melhores práticas

com benefícios extras de manutenção, com bons nomes ele pode alcançar

  • mudança de estilo não requer atualização html * (consulte a demonstração)

  • estilo de bloqueio em html (você terá o estilo certo ou nada)

Demo

@mixin segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}

.segment__arrow--type1 {
    @include segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--type2 {
    @include segment__arrow;
    background-image: url('/images/arrow_white.png');
}

@mixin include é melhor que @extend

  1. ter controle da ordem do código no css final
  2. tamanho menor na versão gzip

e mesmo que @extend, pode ser reutilizado e pode substituir várias classes em HTML

com o @mixin, você ganhará flexibilidade extra

@mixin segment__arrow--type1 {
    @include segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
@mixin segment__arrow--type2 {
    @include segment__arrow;
    background-image: url('/images/arrow_white.png');
}
.segment__margic-arrow {
    @include screen(mobile) {
       @include segment__arrow--type1
    }
    @include screen(desktop) {
       @include segment__arrow--type2
    }
}

Para uso de javascript

regras estaduais de smacss

Desvantagem da Classe Única

primeira e única:

maior tamanho de arquivos CSS, mas você sempre pode otimizar facilmente o CSS com base nas seções ou componentes do site na página

Liang
fonte