Abstracciones
Uno de lo principios de OOCSS o escritura de estilos orientada a objetos es la reutilización de código y para ello propone el uso extensivo de abstraciones para definir estilos.
Una abstracción es un conjunto de reglas básicas enlazadas a un selector que permiten definir una apariencia o funcionalidad específica. La cual puede ser compartida y extendida por otros selectores. Las abstracciones permiten la reutilización de código, con lo que no sólo diseñamos más rápido, sino que mantenerlo es más secillo1.
Las abstracciones funcionan de manera similar a las clases abstractas de los lenguajes de programación, en el caso de los estilos se pueden extender al concatenar estilos y se sobreescribir reglas.
/* Framework.css */
.btn {
display: inline-block;
padding: .5em .75em;
}
Esta abstracción aplica estilos que permiten que un elemento con la clase .btn
se muestre como un botón con apariencia básica. Si en nuestro diseño utilizamos distintos tipos de botones, podemos extender la abstracción. Por ejemplo si necesitamos botones más grandes y verdes, agregamos las siguientes abstracciones:
/* Framework.css */
.large{
font-size: 1.5em;
}
.red{
background-color:red;
}
Y podemos tener 4 tipos de botones con las tres abstracciones anteriores:
- botones
- botones grandes
- botones rojos
- botones rojos y grandes
Desacoplar estilos del HTML
El OOCSS también propone desacoplar el estilo del HTML a través del uso de clases, lo cual resulta rápido cuando se diseña el sitio por primera vez, de hecho, hay quienes omiten el uso de wireframes y directamente escriben código, en lo que se conoce como Rapid Prototyping.
Siguiendo nuestro ejemplo, para aplicar las abstracciones utilizamos el siguiente código:
<button class="btn btn-large btn-red">Eliminar</button>
Y sin mucho esfuerzo podemos ir declarando botones de todos tamaños y colores, sin embargo, este código, en apariencia inofensivo, termina llenando nuestro HTML de clases arbritarias. Pronto nos damos cuenta de que el uso de clases no es una división natural entre el HTML y el CSS por que en realidad no logran desacoplar los estilos de la estructura, ya que para modificar la apariencia debemos tocar el HTML agregando o modificando clases cuando menos.
El principal problema con las clases es que no son muy inteligentes, y sobrecalifican nuestras etiquetas, al punto que se crea toda una estructura de clases arbitrarias que debemos aprender para poder aplicar estilos. Y si cambiamos de framework o incluso de versión, las clases que aprendimos ya no funcionan y tenemos nuevas clases que aprender.
Creo que la única razón justificada para usar clases era como respaldo para navegadores antiguos (IE6) que no podían interpretar los selectores inteligentes, pero ya no aplica.
Selectores Inteligentes
The
p
selector is an example of an intelligent selector in its simplest form. Thep
selector is intelligent because it has innate knowledge of semantic classification. Without intervention by the author, it already knows how to identify paragraphs and when to style them as such — simple yet effective.
En su excelente artículo. Heydon Pickering propone utilizar HTML semático junto con selectores inteligentes para aplicar estilos. Si ya el W3C se encarga de definir etiquetas y atributos estándar, por qué no utilizarlos en lugar de las clases que cada desarrollador invento. Siguiendo nuestro ejemplo, ahora con selectores inteligentes quedaría así:
<button>Eliminar</button>
Y el css sería el siguiente:
button {
display: inline-block;
padding: .5em .75em;
}
button[role=alert]{
font-size:1.5em;
}
Como se explica en el artículo, el uso de selectores inteligentes permite un mayor control sobre los elementos a los que se aplica. Se puede argumentar que el selector button
, no es tan flexible como .btn
en cuanto a la reutilización de estilos, y es cierto, porque no funciona como una abstracción dado que es imposible aplicar los estilos a cualquier otro elemento que no sea button
. Sin embargo, no es una tarea para los selectores inteligentes, para ello podemos utilizar un enfoque diferente con mapas y abstracciones como veremos a continuación.
Ámbito de las abstracciones
Podemos decir que la abstracción con el selector .btn
es pública porque está disponible para cualquier elemento HTML. De hecho, utilizando exclusivamente CSS sólo podemos declarar abstracciones públicas. Es por eso que previo al uso de preprocesadores, la mejor opción para tener un código organizado y fácil de mantener era utilizando el enfoque OOCSS. Ahora, con la ayuda de los preprocesador es posible generar abstracciones que podríamos llamar abstracciones privadas, las cuales no estarán disponibles para su uso directo en el HTML.
Para convertir la abstracción pública .btn
en privada, utilizando SASS2, simplemente cambiamos el punto por el signo de porcentaje.
%btn {
display: inline-block;
padding: .5em .75em;
}
Para aplicar la abstracción anterior utilizamos la claúsula @extend
button {
@extend %btn;
}
Las abstracciones privadas al igual que las públicas son arbritarias, no obstante, pertenecen exclusivamente al CSS y con ello permite desacoplar los estilos del HTML.
@extend
o @include
En un principio los mixins parecerían la opción adecuada para las abstraciones, y aunque en ocasiones el resultado es el mismo, es recomendable usar @extend por las siguientes razones:
- Para cambiar el ámbito se requiere modificar un sólo carácter. Podríamos por ejemplo, reemplazar todos puntos por signos de porcentaje en Twitter Bootstap y la mayoría de las abstracciones seguirían funcionando.
- Puede declararse varias veces sumando las reglas y en su caso sobreescribiendo.
- Generan menos código porque cuando se utiliza más de una vez, solamente se agregan las reglas al selector base.
Aunque también tienen varios inconvienientes, dentro de los cuales destacan:
- En proyectos grandes es difícil mantener el orden en que se aplican, puesto que al compilarse el código aparecen siguiendo el orden en que se declararon.
- Es complicado aplicar media queries.
Se requiere un poco más de experimentación, pero con lo que hemos visto conidero que la claúsula @extend
es la adecuada.
Mapas
Un mapa es un selector, de preferecia inteligente, el cual para definir estilos utiliza abstracciones privadas.
Al igual que las abstracciones públicas, también es posible combinar las abstracciones privadas, regresando a nuestro ejemplo, si agregamos un selector inteligente tendremos un mapa:
button[role=alert]{
@extend %btn;
@extend %btn-red;
}
Tenemos las mismas combinaciones de estilos que con las abstraciones públicas del principio, pero nuestro HTML es completamente semántico:
<button role="alert">Eliminar</button>
Los mapas son el puentre entre el OOCSS y los selectores inteligentes. Son la capa que permite tener HTML semántico, selectores inteligentes y abstracciones totalmente portables.
Organización de archivos
Otra de las ventajas de utilizar preprocesadores es que nos permiten organizar nuestros estilos en varios archivos, al final todo se puede compilar en un solo archivo minificado.
Los mapas, al cumplir una función específica deben estar en archivos independientes, considero que podrían organizarse de la siguiente manera:
├ estilos
├────┼ abstracciones # Abstracciones privadas, que pueden compartirse en proyectos
| ├──── _buttons.scss
| ├──── [...]
├────┼ mapas # Mapas con estilos específicos para el proyecto
| ├──── _navigation.scss
| ├──── [...]
├──── main.scss # Archivo para importar mapas y abstracciones
Conclusión
Una de las aplicaciones más importantes del enfoque OOCSS son los frameworks que contienen estilos predefinidos para casi cualquier elemento de la interfaz gráfica, entre ellos destacan Twitter Bootstrap y Zurb Foundation.
Por otro lado están los selectores inteligentes, los cuales como vimos, enriquecen nuestro arsenal de selectores y eliminan la dependencia de las clases. Aparentemente dos enfoques irreconciliables que gracias al uso de abstracciones privadas y mapas podrían dar lugar a frameworks igual de conpletos que Bootstrap, pero más fáciles de mantener, portables y sobre todo que respeten el HTML semántico.
-
Más información en el artículo de Nichollas Gallagher "About HTML semantics and front-end architecture" ↩
-
Tanto SASS, LESS y Stylus soportan las abstracciones privadas, aunque tienen distinta syntaxis. ↩