Dressing ITCSS

vestir, condimentar, alinear

inverted triangle css architecture

Puedes ver esta charla en video aquí

ITCSS

by Harry Roberts

@csswizardry

@danifornells

Especificidad CSS

Cómo se resuelve?

0|0|0|1

elemento {}

::pseudo-elemento {}

0|0|1|0

.clase {}

[atributo] {}

:pseudo-clase {}

0|1|0|0

#identificador {} 💩

1|0|0|0

propiedad: !important; 🔞

style="propiedad: en-linea;" 🐀

0|0|0|0

>, +, *, ~, :not()

@media

00010 < 00013

0|0|1|0 > 0|0|0|13

En caso de empate ...

el último en llegar VENCE

ITCSS

Qué es y qué no?

ITCSS no es

  • Un template CSS
  • Una librería de componentes
  • Un pre-procesador de CSS
  • Tampoco un post-procesador de CSS
  • Un reemplazo de Bootstrap

ITCSS es

  • Otra propuesta de arquitectura CSS
  • Una solución más a la batalla de especificidad
  • Organizar las hojas de estilos para el navegador
  • Una capa de abstracción jerárquica sobre OOCSS

01 ITCSS settings 🌱

  • Configuración del núcleo
    • Root font size
    • Espaciado
  • Variables
    • Tipos
    • Colores
    • Breakpoints
    • ...

02 ITCSS tools 🍴

  • Funciones globales
    • Conversion unidades
    • ...
  • Mixins globales
    • Media Queries
    • Ratios
    • Clearfix
    • ...

03 ITCSS generic 🚿

  • Normalización de navegadores
  • Modelo de caja
  • Inicialización de comportamiento
  • Espaciado y ritmo vertical

04 ITCSS elements 🐣

  • Apariencia de los elementos HTML

05 ITCSS objects 📐😍

  • Patrones repetibles de diseño
  • Propiedades asociadas a la distribución
  • Heredables por los componentes

06 ITCSS components 👕👖👙👚

  • Componentes visuales reusables
  • Semántica asociada a su apariencia, no a su función ni contenido
  • Con o sin jerarquía entre ellos

99 ITCSS utilities ❗💅

  • Diseñadas para las excepciones
  • Una sola propiedad, !important

ITCSS 💖 BEM

Una historia de amor

BEM

.block__element--modifier

        
.site-search {}         /* Block */
.site-search__field {}  /* Element */
.site-search--xmas {}   /* Modifier */
        
    

ITCSS BEM

BEMIT 💎

BEMIT namespaces 🃏

        
.c-site-search {}         /* Component */
.c-site-search__field {}  /* Component Part */
.c-site-search--xmas {}   /* Component Modifier */
        
    
        
// BEMIT: Namespaces everywhere

// 01-Settings: core-variables
$s-core__font-size:         16px !default;
$s-color-primary:           #247ba0 !default;
$s-breakpoints: (
        "xs":               480px,
        "md":               960px,
        "lg":               1280px,
) !default;

// 01-Settings: core-functions
@function s-strip-units($value) {
  @return $value / ($value * 0 + 1);
}

@function s-px-to-rem($value, $root-font-size: $s-core__font-size) {
  @return s-strip-units($value) / s-strip-units($root-font-size) * 1rem;
}

// 02-Tools: MQ
@mixin t-mq-min($breakpoint) {
  @media (min-width: map-get($s-breakpoints, $breakpoint)) {
    @content;
  }
}

// 04-Elements: HTML
html {
  font-size: $s-core__font-size;
}

// 06-Components: Site Search
$c-site-search__font-size:  12px !default;
$c-site-search__btn-color:  $s-color-primary !default;
$c-site-search__stack-bp:   "md" !default;

.c-site-search {
  font-size: s-px-to-rem($c-site-search__font-size);
}

.c-site-search__btn {
  background-color: $c-site-search__btn-color;
  @include t-mq-min($c-site-search__stack-bp){
    display: block;
  }
}
        
    

BEMIT suffixes 🙀

        
.u-visible\@md {} // Toggle visibility
.u-visible\@lg {}
.u-visible\@xl {}
        
    
        
// Site Search Component
.c-site-search__field, .c-site-search__btn {
  display: inline;
}

.c-site-search--stacked\@xl {
  @include t-mq-min("xl"){
    .c-site-search__field, .c-site-search__btn {
      display: block;
} } }
        
    
        

        
    

Más claro que el agua

Por dónde empezar pues?

INUITCSS

Otro ego más de Harry Roberts

👀 en desarrollo

ITCSS utilities

Principio de única responsabilidad

Principio de inmutabilidad

Una regla por utilitdad

        
.u-color-primary {
  color: $s-color-primary;
}
        
    

Valor específico

        
.u-color-primary {
  color: $s-color-primary !important;
}
        
    

Aplicable a excepciones

        



        
    
        



        
    

Ejemplo: alineaciones

        
.u-align-left {
  text-align: left !important;
}

.u-align-center {
  text-align: center !important;
}

.u-align-right {
  text-align: right !important;
}
        
    

Ejemplo: colores

        
$s-colors-brand: (
  first:   #ec1b2d,
  second:  #f9eb2d,
  third:   #20a0de,
) !default;

@each $name, $color in $s-colors-brand {
  .u-color-#{$name} {
    color: $color !important;
  }
}
        
    

Ejemplo: anchuras

        
// Utilidad de anchuras, en fracciones: .u-1/3

$u-widths-fractions:  1 2 3 4 5 !default;

@each $denominator in $u-widths-fractions {
  @for $numerator from 1 through $denominator {
    .u-#{$numerator}\/#{$denominator} {
      width: ($numerator / $denominator) * 100% !important;
} } }
        
    

Ejemplo: anchuras responsivas

        
// Utilidad de anchuras, en fracciones: .u-1/3@md

$u-widths-fractions:  1 2 3 4 5 !default;

@each $bp-name, $bp-value in $s-breakpoints {
  @include t-mq($from: $bp-name) {
    @each $denominator in $u-widths-fractions {
      @for $numerator from 1 through $denominator {
        .u-#{$numerator}\/#{$denominator}\@#{$breakpoint} {
          width: ($numerator / $denominator) * 100% !important;
} } } } }
        
    

No son poca cosa

.u-hidden-until\@xs{display:none!important}}@media (max-width:42.84714em){.u-hidden-until\@sm{display:none!important}}@media (max-width:59.99em){.u-hidden-until\@sml{display:none!important}}@media (max-width:68.56143em){.u-hidden-until\@md{display:none!important}}@media (max-width:91.41857em){.u-hidden-until\@lg{display:none!important}}@media (max-width:102.84714em){.u-hidden-until\@xl{display:none!important}}@media (max-width:114.27571em){.u-hidden-until\@xxl{display:none!important}}@media (max-width:137.13286em){.u-hidden-until\@xxxl{display:none!important}}.u-1\/1{width:100%!important}.u-1\/2{width:50%!important}.u-1\/3{width:33.33333%!important}.u-2\/3{width:66.66667%!important}.u-1\/4{width:25%!important}.u-2\/4{width:50%!important}.u-3\/4{width:75%!important}.u-1\/5{width:20%!important}.u-2\/5{width:40%!important}.u-3\/5{width:60%!important}.u-4\/5{width:80%!important}@media (min-width:42.85714em){.o-wrapper--from\@xs{max-width:520px}.o-wrapper--from\@sm{max-width:520px}.u-hidden-from\@sm{display:none!important}.u-1\/1\@sm{width:100%!important}.u-1\/2\@sm{width:50%!important}.u-1\/3\@sm{width:33.33333%!important}.u-2\/3\@sm{width:66.66667%!important}.u-1\/4\@sm{width:25%!important}.u-2\/4\@sm{width:50%!important}.u-3\/4\@sm{width:75%!important}.u-1\/5\@sm{width:20%!important}.u-2\/5\@sm{width:40%!important}.u-3\/5\@sm{width:60%!important}.u-4\/5\@sm{width:80%!important}}@media (min-width:60em){.o-wrapper--from\@xs{max-width:760px}.o-wrapper--from\@sm{max-width:760px}.o-wrapper--from\@sml{max-width:760px}.o-wrapper--to\@sm{max-width:520px}.u-hidden-from\@sml{display:none!important}.u-1\/1\@sml{width:100%!important}.u-1\/2\@sml{width:50%!important}.u-1\/3\@sml{width:33.33333%!important}.u-2\/3\@sml{width:66.66667%!important}.u-1\/4\@sml{width:25%!important}.u-2\/4\@sml{width:50%!important}.u-3\/4\@sml{width:75%!important}.u-1\/5\@sml{width:20%!important}.u-2\/5\@sml{width:40%!important}.u-3\/5\@sml{width:60%!important}.u-4\/5\@sml{width:80%!important}}@media (min-width:68.57143em){.o-wrapper--from\@xs{max-width:880px}.o-wrapper--from\@sm{max-width:880px}.o-wrapper--from\@sml{max-width:880px}.o-wrapper--from\@md{max-width:880px}.o-wrapper--to\@sm{max-width:520px}.o-wrapper--to\@sml{max-width:760px}.u-hidden-from\@md{display:none!important}.u-1\/1\@md{width:100%!important}.u-1\/2\@md{width:50%!important}.u-1\/3\@md{width:33.33333%!important}.u-2\/3\@md{width:66.66667%!important}.u-1\/4\@md{width:25%!important}.u-2\/4\@md{width:50%!important}.u-3\/4\@md{width:75%!important}.u-1\/5\@md{width:20%!important}.u-2\/5\@md{width:40%!important}.u-3\/5\@md{width:60%!important}.u-4\/5\@md{width:80%!important}}@media (min-width:91.42857em){.o-wrapper--from\@xs{max-width:1200px}.o-wrapper--from\@sm{max-width:1200px}.o-wrapper--from\@sml{max-width:1200px}.o-wrapper--from\@md{max-width:1200px}.o-wrapper--from\@lg{max-width:1200px}.o-wrapper--to\@sm{max-width:520px}.o-wrapper--to\@sml{max-width:760px}.o-wrapper--to\@md{max-width:880px}.u-hidden-from\@lg{display:none!important}.u-1\/1\@lg{width:100%!important}.u-1\/2\@lg{width:50%!important}.u-1\/3\@lg{width:33.33333%!important}.u-2\/3\@lg{width:66.66667%!important}.u-1\/4\@lg{width:25%!important}.u-2\/4\@lg{width:50%!important}.u-3\/4\@lg{width:75%!important}.u-1\/5\@lg{width:20%!important}.u-2\/5\@lg{width:40%!important}.u-3\/5\@lg{width:60%!important}.u-4\/5\@lg{width:80%!important}}@media (min-width:102.85714em){.o-wrapper--from\@xs{max-width:1360px}.o-wrapper--from\@sm{max-width:1360px}.o-wrapper--from\@sml{max-width:1360px}.o-wrapper--from\@md{max-width:1360px}.o-wrapper--from\@lg{max-width:1360px}.o-wrapper--from\@xl{max-width:1360px}.o-wrapper--to\@sm{max-width:520px}.o-wrapper--to\@sml{max-width:760px}.o-wrapper--to\@md{max-width:880px}.o-wrapper--to\@lg{max-width:1200px}.u-hidden-from\@xl{display:none!important}.u-1\/1\@xl{width:100%!important}.u-1\/2\@xl{width:50%!important}.u-1\/3\@xl{width:33.33333%!important}.u-2\/3\@xl{width:66.66667%!important}.u-1\/4\@xl{width:25%!important}.u-2\/4\@xl{width:50%!important}.u-3\/4\@xl{width:75%!important}.u-1\/5\@xl{width:20%!important}.u-2\/5\@xl{width:40%!important}.u-3\/5\@xl{width:60%!important}.u-4\/5\@xl{width:80%!important}}@media (min-width:114.28571em){.o-wrapper--from\@xs{max-width:1520px}.o-wrapper--from\@sm{max-width:1520px}.o-wrapper--from\@sml{max-width:1520px}.o-wrapper--from\@md{max-width:1520px}.o-wrapper--from\@lg{max-width:1520px}.o-wrapper--from\@xl{max-width:1520px}.o-wrapper--from\@xxl{max-width:1520px}.o-wrapper--to\@sm{max-width:520px}.o-wrapper--to\@sml{max-width:760px}.o-wrapper--to\@md{max-width:880px}.o-wrapper--to\@lg{max-width:1200px}.o-wrapper--to\@xl{max-width:1360px}.u-hidden-from\@xxl{display:none!important}.u-1\/1\@xxl{width:100%!important}.u-1\/2\@xxl{width:50%!important}.u-1\/3\@xxl{width:33.33333%!important}.u-2\/3\@xxl{width:66.66667%!important}.u-1\/4\@xxl{width:25%!important}.u-2\/4\@xxl{width:50%!important}.u-3\/4\@xxl{width:75%!important}.u-1\/5\@xxl{width:20%!important}.u-2\/5\@xxl{width:40%!important}.u-3\/5\@xxl{width:60%!important}.u-4\/5\@xxl{width:80%!important}}@media (min-width:137.14286em){.o-wrapper--from\@xs{max-width:1840px}.o-wrapper--from\@sm{max-width:1840px}.o-wrapper--from\@sml{max-width:1840px}.o-wrapper--from\@md{max-width:1840px}.o-wrapper--from\@lg{max-width:1840px}.o-wrapper--from\@xl{max-width:1840px}.o-wrapper--from\@xxl{max-width:1840px}.o-wrapper--to\@sm{max-width:520px}.o-wrapper--to\@sml{max-width:760px}.o-wrapper--to\@md{max-width:880px}.o-wrapper--to\@lg{max-width:1200px}.o-wrapper--to\@xl{max-width:1360px}.o-wrapper--to\@xxl{max-width:1520px}.u-hidden-from\@xxxl{display:none!important}.u-1\/1\@xxxl{width:100%!important}.u-1\/2\@xxxl{width:50%!important}.u-1\/3\@xxxl{width:33.33333%!important}.u-2\/3\@xxxl{width:66.66667%!important}.u-1\/4\@xxxl{width:25%!important}.u-2\/4\@xxxl{width:50%!important}.u-3\/4\@xxxl{width:75%!important}.u-1\/5\@xxxl{width:20%!important}.u-2\/5\@xxxl{width:40%!important}.u-3\/5\@xxxl{width:60%!important}.u-4\/5\@xxxl{width:80%!important}}.u-color-brand-red{color:#ec1b2d!important}.u-color-brand-yellow{color:#f9eb2d!important}.u-color-brand-blue{color:#20a0de!important}.u-color-brand-first{color:#ec1b2d!important}.u-color-brand-second{color:#f9eb2d!important}.u-color-brand-third{color:#20a0de!important}.u-bg-color-brand-red{background-color:#ec1b2d!important}.u-bg-color-brand-yellow{background-color:#f9eb2d!important}.u-bg-color-brand-blue{background-color:#20a0de!important}.u-bg-color-brand-first{background-color:#ec1b2d!important}.u-bg-color-brand-second{background-color:#f9eb2d!important}.u-bg-color-brand-third{background-color:#20a0de!important}.u-color-white{color:#FFF!important}.u-color-black{color:#000!important}.u-color-transparent{color:transparent!important}.u-color-transparent-white{color:rgba(255,255,255,0)!important}.u-color-gray-05{color:#f2f2f2!important}.u-color-gray-10{color:#e6e6e6!important}.u-color-gray-20{color:#ccc!important}.u-color-gray-30{color:#b3b3b3!important}.u-color-gray-70{color:#4d4d4d!important}.u-color-gray-80{color:#333!important}.u-color-gray-90{color:#1a1a1a!important}.u-bg-color-white{background-color:#FFF!important}.u-bg-color-black{background-color:#000!important}.u-bg-color-transparent{background-color:transparent!important}.u-bg-color-transparent-white{background-color:rgba(255,255,255,0)!important}.u-bg-color-gray-05{background-color:#f2f2f2!important}.u-bg-color-gray-10{background-color:#e6e6e6!important}.u-bg-color-gray-20{background-color:#ccc!important}.u-bg-color-gray-30{background-color:#b3b3b3!important}.u-bg-color-gray-70{background-color:#4d4d4d!important}.u-bg-color-gray-80{background-color:#333!important}.u-bg-color-gray-90{background-color:#1a1a1a!important}.u-color-state-success{color:#36ba33!important}.u-color-state-info{color:#20a0de!important}.u-color-state-warning{color:#f99500!important}.u-color-state-danger{color:#c1101f!important}.d-body,a{color:#333}.u-bg-color-state-success{background-color:#36ba33!important}.u-bg-color-state-info{background-color:#20a0de!important}.u-bg-color-state-warning{background-color:#f99500!important}.u-bg-color-state-danger{background-color:#c1101f!important}}

Usa sólamente las que necesitas

Variables de conmutación

        
$u-color__colors-brand--enabled: true !default;

@if ($u-color__colors-brand--enabled) {
  @each $name, $color in $s-colors-brand {
    .u-color-#{$name} {
      color: $color !important;
    }
  }
}
        
    

Reduce los mapas

        
$u-color__colors-brand: map_remove($s-colors-brand, third) !default;

@each $name, $color in $u-color__colors-brand {
  .u-color-#{$name} {
    color: $color !important;
  }
}

        
    

Optimiza la salida de CSS

Agrupación de media queries

                    
@media (min-width: 34.28571em) {
    .u-hidden-from\@xs {
        display: none !important; } }

@media (min-width: 42.85714em) {
    .u-hidden-from\@sm {
        display: none !important; } }

@media (min-width: 34.28571em) {
    .u-1\/2\@xs {
        width: 50% !important; } }

@media (min-width: 42.85714em) {
    .u-1\/2\@sm {
        width: 50% !important; } }
                    
                
                    
@media (min-width: 34.28571em) {
    .u-hidden-from\@xs {
        display: none !important; }
    .u-1\/2\@xs {
        width: 50% !important; } }

@media (min-width: 42.85714em) {
    .u-hidden-from\@sm {
        display: none !important; }
    .u-1\/2\@sm {
        width: 50% !important; } }
                    
                

Y lo más !importante ...

Guárdalas en secreto

ITCSS objects

Patrones de diseño reusables

Propiedades de los objetos

  • display, positioning & float
  • margin & padding
  • alignment & direction
  • width & ratio
  • clearfix

Object box

        
.o-box {
  @include t-clearfix();
  display: block;
  padding: map-get($s-spaces, "medium");

  > :last-child {
    margin-bottom: 0;
  }

}
        
    

Object media

        
.o-media {
  @include t-clearfix;
  display: block;
}
.o-media__img {
  float: left;
  margin-right: map-get($s-spaces, "medium");
  > img { display: block; }
}
.o-media__body {
  overflow: hidden;
  display: block;
  &, > :last-child { margin-bottom: 0; }
}
        
    

Object pack

        
.o-pack {
  width: 100%;
  margin-left: 0;
  display: table;
  table-layout: fixed;
  border-spacing: map-get($s-spaces, "medium");
}

.o-pack__item {
  display: table-cell;
  vertical-align: top;
}
        
    

Object layout

        
.o-layout {
  display: block;
  margin: 0;
  padding: 0;
  margin-left: -(map-get($s-spaces, "medium"));
}

.o-layout__item {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: top;
  width: 100%;
  padding-left: map-get($s-spaces, "medium");
}
        
    

Resumiendo ...

Pura magia negra

Usa sólamente los que necesitas

Conmuta y reduce

        
$o-layout-enabled:            true !default;
$o-layout__spaces:            map_remove($s-spaces, "large", "huge") !default;
$o-layout__spaces--default:   "medium" !default;
$o-layout__spaces--enable:    true !default;

@if ($o-layout-enabled and $o-layout__spaces--enable) {
  @each $space-name, $space-value in $o-layout__spaces {
    @if ($space-name != $o-layout__spaces--default) {
      .o-layout--space-#{$space-name} {
        margin-left: -$space-value;
        > .o-layout__item {
          padding-left: $space-value;
} } } } }


        
    

Y véte despidiendo de:

  • Bootstrap
  • Foundation
  • Susy
  • ... y demás dolores de cabeza

ITCSS components

{{ undefined }}

Principios de los componentes

  • Aislamiento
  • Reusabilidad
  • Flexibilidad
  • Agnósticos de su contenido

Propiedades de los componentes

  • colors & borders
  • typography
  • forms
  • box model properties on child elements

Variaciones de los componentes

La variación es aquella mutación que no va a cambiar durante la vida de la página. Usa modificadores.

        
// Xmas modifier

.c-site-search--xmas {

  &.c-site-search {
    background-color: $s-color__xmas--bg;
  }

  &.c-site-search__btn {
    background-color: $s-color__xmas--complementary;
    color: $s-color__xmas--accent;
  }
}
        
    

Estados de los componentes

El estado es aquél comportamiento susceptibe de ser cambiado durante la vida de la página. Usa clases de estado.

        
// Disabled state
.is-disabled {

  &.c-site-search {
    opacity: .5;
  }

  &.c-site-search__field,
  &.c-site-search__btn {
    pointer-events: none;
  }

}
        
    

Distribución de los componentes

Usa los objetos para envolver tu componente y distribuírlo en una página

        

Distribución de los componentes

Los elementos del componente, preferiblemente deben der distribuídos en los estilos del componente

        
.c-site-search {}

.c-site-search__field {
  display: inline-block;
  width: 70%;
}

.c-site-search__btn {
  display: inline-block;
  width: 30%;
}
        
    

Distribución de los componentes

Si el componente es un elemento de otro componente padre puedes usar tal comportamiento para su distribución en ese contexto

                    

                    
.c-post {}
.c-post__title {}

.c-post__search {
  float: right;
  max-width: 40%;
}
                    
                

Jerarquía entre componentes

Atomic design

  • Atoms
  • Molecules
  • Organisms
  • Templates

Personalizado

  • Material
  • Components
  • Widgets

Menos es más 🙏

Sin más secretos

Ahora que ya conoces

ITCSS

Añadiendo capas

Capa animation

Movimientos y transiciones reusables

        
.a-lift-reveal {
  opacity: 0;
  transition: transform $s-timing--fast ease-out, opacity $s-timing--fast linear;
  transform: translate(0, -25%);

  &.in {
    opacity: 1;
    transform: translate(0, 0);
  }
}
        
    

Capa scopes

La caja negra que te saca de los apuros

        
.s-wysinwyg {
  h1, h2, h3, h4, h5, h6 {
    font-size: $s-core-font-size;
  }
  ul, ol {
    margin-left: $s-space;
  }
  br + br {
    display: none;
  }
  [style]:after {
    content: " ¡¡ Como me cambies el color te meto dos yoyas !!";
    color: red;
  }
}
        
    

ITCSS es una arquitecura

Flexible

Si te ha gustado

Toca implementar

Píde a negocio recursos

y explícales que vas a estar ocupado

¿No has tenido suerte?

Deberás encontrar la fórmula

Scope ITCSS

        
$s-core-font-size:          12px;

@import '01_settings/settings';
@import '02_tools/tools';

.s-itcss {
  @import '03_generic/generic';
  @import '04_elements/elements';
  @import '05_objects/objects';
  @import '06_components/components';
  @import '09_utilities/utilities';
}
        
    

Des del centro hacia el exterior

        
1.999

Capa defense

        
// old.css overrides color by 0|0|3|1
// Solution: Specificity needs to increase

.c-site-search__btn {
  html &#{&}#{&} {
    color: $s-color-primary;
  }
}
        
    

Capa shame

Deuda técnica

        
// c-site-search__field
// Bug PV-563 on IE <= 10

._c-site-search__field {
  margin-left: -2px;
  margin-right: -2px;
}
        
    

Remedios a la especificidad

        
// #buscador {
[id="buscador"] {}

// ul li
html body li {}

// .cabecera .logo
.logo.logo.logo {}
        
    

Debug

        
// Highlight scoped ITCSS
[class^="s-itcss"],
[class*=" s-itcss"] {
  outline: 10px solid green;
}

// Highlight components
[class^="c-"],
[class*=" c-"] {
  outline: 10px solid cyan;
}


        
    

Ya no tienes excusas

Gracias

Próximamente en github

🍍 HAITI CSS

Un frankstein en desarrollo