Arquitectura frontend con BEM y SASS

Post on 18-Nov-2014

902 views 0 download

description

Expongo un método para estructurar nuestros proyectos con BEM y SASS.

Transcript of Arquitectura frontend con BEM y SASS

@rlucha

Arquitectura front-end CSS para proyectos a gran escala

¿Qué es un proyecto a gran escala?Media o larga duración / Requisitos indefinidos / Recursos indefinidos

Cambiar el enfoqueFacilidad de mantenimiento

Absorber nuevos requisitos minimizando el impactoIncorporar nuevos recursos al equipo lo más rápidamente posible

ModularizaciónSeparar un gran proyecto en pequeñas partes discretas

Independencia de las partes / encapsulamientoReutilización de código / DRY

... similar a la programación OO

OOCSSUn objeto CSS es una estructura repetitiva independiente del contexto

Principio de responsabilidad únicaPrincipio open/closed (fácil de extender, difícil de modificar)

SMACSSMódulo

ComponenteSubmódulo

Guía de prácticasJerarquía por capas

Es una metodologíaElimina la especificidad

BEMBloque

ElementoModificador

Colisión de especificidadLa cascada tiene muchísima potencia pero es difícil de controlar

Una colisión afecta a partes dispares del proyecto

Ejemplo

<div class=”contentHolder”>

<ul class=”movieList”>

<li> Item 1</li>

<li> Item 2</li>

<li class=”fav”> Item 3</li>

<li> Item 4</li>

</ul>

</div>

...

<span class=”fav”>

Añadir a favoritos

</span>

· item 1

· item 2

· item 3

· item 4

Añadir a favoritos

.contentHolder .movieList li {

font-size: 10pt;

}

.movieList .fav {

font-weight: 600;

color: #F00;

font-size: 12pt;

}

.fav {

font-size: 14pt;

color: #0F0;

text-decoration: underline;

}

Consecuencias inesperadas

BEMBloque

movieList

- --Elementoitem

Modificadorfav

<div class=”contentholder”>

<ul class=”movieList”>

<li class=”movieList-item”> Item 1</li>

<li class=”movieList-item”> Item 2</li>

<li class=”movieList-item movieList-item--fav”> Item 3</li>

<li class=”movieList-item”> Item 4</li>

</ul>

</div>

...

<span class=”fav”>

Añadir a favoritos

</span>

.movieList-item {

font-size: 10pt;

}

.movieList-item--fav {

font-weight: 600;

color: #F00;

font-size: 12pt;

}

.fav {

font-size: 14pt;

color: #0F0;

text-decoration: underline;

}

BEM es modular y pseudoespecíficoCreando namespaces locales por módulo/bloque solucionamos los dos

principales problemas de un proyecto a gran escala.

Identificación de las partes y control de la especificidad.

BEM + SASS

Podemos utilizar la sintaxis BEM con la anidación de SASS utilizando el operador “&” en conjunción con la directiva @at-root

· & es una referencia al contexto superior· #{&} interpola el nombre del contexto· @at-root crea la regla en el root del documento compilado sin tener en cuenta el nesting

.movieList {

@at-root #{&}-item {

font-size: 10pt;

@at-root #{&}--fav {

font-weight: 600;

color: #F00;

font-size: 12pt;

}

}

}

BEM + SASS

&

referencia al contexto superior

#{&}

interpolacióna string

@at-root

añade la regla al root sin nesting

Mixins

El uso de mixins abstrae la necesidad deconocer la nomenclatura exacta en SASS

Permite a gente que no conoce SASS extender el proyecto sin curva de aprendizaje

Reduce los errores de sintaxis

No usamos selectores CSS

@include block(movieList) {

@include element(item) {

font-size: 10pt;

@include modifier(fav) {

font-weight: 600;

color: #F00;

font-size: 12pt;

}

}

}

Herencia (aka Submódulos)

Al controlar con SASS cómo se interpolan los nombres de clase podemos controlar el contexto en el que se crean las propiedades.

El mixin extendBlock crea la clase .movieList--horizontal .movieList-itemy le aplica inline-block manteniendo el resto de propiedades intactas. Con esta sobrecarga tenemos un control total de la especificidad.

@include block(movieList) {

@include element(item) {

font-size: 10pt;

@include modifier(fav) {

...

}

}

}

@include extendBlock(movieList,horizontal) {

@include element(item) {

display: inline-block;

}

}

.movieList--horizontal .movieList-item

BEM.scss

$extend: false;$blockExtended: "";

@mixin block($name) {

@at-root .#{$name} { @content; }

}

@mixin modifier($name) {

@at-root #{&}--#{$name} { @content; }

}

@mixin element($name) {

@if $extend == true {

@at-root #{&} .#{$blockExtended}-#{$name} {

@content;

}

}

@else {

@at-root #{&}-#{$name} {

@content;

}

}

}

@mixin extendBlock($blockExtended,$name) {

$extend: true !global;

$blockExtended: $blockExtended !global;

@at-root .#{$blockExtended}--#{$name} {

@content;

}

$extend: false !global;

}

BEM dentro del proyecto

Un archivo scss por bloqueUn archivo template por bloque

Los bloques son específicos del proyecto

/public

/css

/scss/

/vendor

/framework

_base.scss

_variables.scss

_app.scss

/blocks

_movieList.scss

_topNavigation.scss

...

/partials/

movieList.hbs

Combinando FMWs

Hacer la transición de frameworks de soluciones a frameworks de componentes.Ofrecen componentes abstraídos de presentación con los que podemos dotar a nuestros bloques de funcionalidades comunes.

· inuit.css· suit.css

/public

/css

/scss/

/vendor

/framework

_base.scss

_variables.scss

_app.scss

/blocks

_movieList.scss

_topNavigation.scss

...

/partials/

movieList.hbs

inuit.css

GRID responsiveHeadersSpritesButtons

ListsMedia Object

Pagination...

Usando la directiva @extend podemos extender la funcionalidad de nuestros bloques con las abstracciones del framework de componentes

Reutilizamos abstracciones comunes a todos los proyectos

Extendiendo el proyecto

@extend %placeholders

@include block(movieList) {

@extend %framework-blockList;

@include element(item) {

@extend %framework-blockList-item;

font-size: 10pt;

@include modifier(fav) {

font-weight: 600;

color: #F00;

font-size: 12pt;

}

}

}

%framework-blockList {

margin: 0;

padding: 0;

list-style: none;

}

%framework-blockList-item {

padding: $fmw-block-list-padding;

}

open/close por capas

Scaffolding ( normalize.css, animate.css, ... )

Theme ( pink.scss, ocean.scss, ... )

Blocks ( movieLIst.scss, mainMenu.scss, ... )

@extend

override

@import

Framework ( inuit.scss, suit.scss, ... )

Resumenseparar en módulos / identificarlos / encapsularlos / reutilizarlos

scaffolding / extender FMW / integrar módulos / customizar temas

Y después...

Testing

.movieList-item {

@extend %error;

}

.movieList .movieList-item {

@extend %success;

}

Partir de un estado de error que sólo se resuelve si se usa en el contexto apropiado

Inyectar CSS desde el navegador con extensiones

Generadores estáticosAssemble / Jekyll / DocPad

En el futuro...Preprocesadores customizables

Interpolaciones arbitrarias de selectoresNuevas reglas y relaciones

ReWorkShadow DOM

Directivas

@mixin extendBlock($blockExtended,$name) {

$extend: true !global;

$blockExtended: $blockExtended !global;

@at-root .#{$blockExtended}--#{$name} {

@content;

}

$extend: false !global;

}

@rlucha

¡Muchas gracias!