Introducción a la Metodología BEM
Publicado: 2022-03-11¿Qué es la metodología BEM?
Cuando está creando sitios web más pequeños, la forma en que organiza sus estilos no suele ser un gran problema. Creas tus archivos habituales, escribes todo el CSS necesario y eso es todo. Sin embargo, cuando se trata de proyectos más grandes y complejos, la forma en que organiza su código se vuelve crucial . La forma en que se estructura el código es aún más importante si está trabajando en un equipo formado por varios desarrolladores front-end y back-end.
Hoy en día, existen muchas metodologías con el objetivo de reducir el código CSS y hacer que su código CSS sea más fácil de mantener. En este artículo, voy a explicar y dar algunos ejemplos de uno de ellos: BEM. BEM significa M odificador de elemento de bloque. La idea principal detrás de esto es acelerar el proceso de desarrollo y facilitar el trabajo en equipo de los desarrolladores organizando las clases de CSS en módulos independientes. Si alguna vez vio un nombre de clase como header__form--search
, ese es BEM en acción. Sí, las clases pueden tener nombres muy largos, pero todas son legibles y comprensibles.
Tenga en cuenta que la mejor práctica es usar BEM solo con clases y no con ID porque las clases le permiten repetir nombres si es necesario y crear una estructura de codificación más consistente. Además, si desea dividir su sitio web en módulos organizados, debe tener la misma estructura: bloque, elemento y modificador. Donde cada bloque puede tener múltiples elementos, y tanto el bloque como los elementos pueden tener múltiples modificadores. Sin embargo, primero comencemos con la estructura básica de BEM y la explicaremos con ejemplos.
Cuadra
Un bloque representa un objeto en su sitio web. Piense en ello como fragmentos estructurales más grandes de su código. Los bloques más comunes en todos los sitios web hoy en día son el encabezado, el contenido, la barra lateral, el pie de página y la búsqueda. Los bloques en BEM son siempre un punto de partida para encadenar sus clases de CSS. Eche un vistazo a algunos ejemplos de bloques:
- un contenido
- un menú
- un formulario de búsqueda
.content {/* Styles */} .menu {/* Styles */} .search {/* Styles */}
Elemento
Un elemento es un componente dentro del bloque que realiza una función particular. Solo debería tener sentido en el contexto de su bloque:
- un artículo de contenido
- un elemento del menú
- un campo de entrada de búsqueda
.content__article {/* Styles */} .menu__item {/* Styles */} .search__input {/* Styles */}
modificador
Un modificador es cómo representamos las variaciones de un bloque. Si alguna vez ha usado Bootstrap, el mejor ejemplo sería el tamaño de los botones. Los tamaños de los botones son solo variaciones de tamaño del botón en sí, lo que lo convierte en el modificador:
- un artículo destacado de contenido
- un enlace de menú
- un campo de búsqueda con o sin icono
.content__article--featured {/* Styles */} .menu__item--link {/* Styles */} .search__input--icon {/* Styles */}
Convenciones de nombres
El objetivo principal de la metodología BEM es hacer que los nombres de los selectores de CSS sean lo más informativos y transparentes posible. El estilo BEM original se define de esta manera:
El nombre del bloque suele ser una sola palabra como .header
, pero si tiene una definición de bloque más larga, se divide con un solo guión -
:
.lang-switcher {/* Styles */}
El nombre del elemento comienza con doble guión bajo __
:
.lang-switcher__flag {/* Styles */}
El nombre del modificador comienza con un solo guión bajo _
:
.lang-switcher__flag_basic {/* Styles */}
Solo hay una regla muy crítica en la metodología BEM: un modificador no se puede usar fuera del contexto de su propietario.
Ejemplo:
.btn_big {/* Styles */}
Puede usar btn_big
solo si el encabezado también está definido.
Mal ejemplo:
<div class=”btn_big”>...</div>
Buen ejemplo:
<div class=”btn btn_big”>...</div>
Además de estos estilos BEM originales, existen esquemas de nombres alternativos como los estilos Harry Roberts y CamelCase.
Ejemplo de estilo de Harry Roberts:
.block-name__element-name--modifier-name {/* Styles */}
Ejemplo de estilo CamelCase:
.BlockName__ElementName_ModifierName {/* Styles */}
También hay algunos otros, pero estos dos son los más comunes. Personalmente, soy fanático de la convención de nomenclatura propuesta por Harris Roberts, que tiene las siguientes reglas:
- Los nombres se escriben en minúsculas.
- Las palabras dentro de los nombres de las entidades BEM están separadas por un guión
-
- El nombre de un elemento está separado del nombre de un bloque por un guión bajo doble
__
- Los modificadores booleanos están delimitados por guiones dobles
--
- No se utilizan modificadores de tipo clave-valor
La razón por la que esta convención de nomenclatura está mucho mejor formada que otras es que puede distinguir fácilmente un elemento modificador de los demás. En las convenciones de nomenclatura originales, el modificador se definiría así:
.block__element_modifier {/* Styles */}
Pero como puede ver, no hay mucha diferencia entre un guión bajo simple y uno doble. Por otro lado, el doble guión proporciona una separación clara y puede ver el modificador al instante:
.block__element--modifier {/* Styles */}
Ejemplo de BEM en diferentes formatos
Tenga en cuenta que además de CSS, BEM también es muy útil para organizar sus JSON, XML, archivos de árbol o cualquier formato compatible con el anidamiento. Piense en la metodología BEM como una buena manera de construir su interfaz de usuario.
Consideremos el siguiente HTML, estructurado en formato BEM:
<header class=”header”> <img class=”header__logo”> <form class=”header__search-from”> <input class=”header__search-from__input” type=”input”> <button class=”header__search-from__button” type=”button”> </form> <div class=”header__lang-switcher”></div> </header>
Lo mismo se puede lograr utilizando el formato JSON y XML.
XML:
<block:header> <block:logo/> <block:search-from> <block:input/> <block:button/> </block> <block:lang-switcher/> </block>
JSON:
{ block: 'header', content: [ { block: 'logo' }, { block: 'search-form', content: [ { block: 'input' }, { block: 'button' } ] }, { block: 'lang-switcher' } ] }
Organización del sistema de archivos de un proyecto BEM
En BEM, es fundamental organizar sus archivos de manera correcta. BEM no solo le brinda una excelente organización de clases CSS y las hace completamente comprensibles, sino que también le brinda una estructura de archivos muy fácil de mantener. Tomemos un proyecto de ejemplo, utilizando la técnica de organización de archivos BEM con archivos SASS:
blocks/ input/ __box/ --big/ input__box--big.scss input__box.scss button/ --big/ button--big.scss
Como puede ver arriba, con solo ver la estructura de subcarpetas dentro de su carpeta principal, todo está claro y organizado. De esta manera, no importa quién esté trabajando después de ti o si estás trabajando después de alguien, porque es increíblemente fácil seguir el mismo patrón.
Dividir el proyecto BEM en plataformas
Además de organizar sus archivos usando técnicas de metodología BEM, también puede entrar en cosas más específicas. Por ejemplo, si está creando un proyecto web que va a ser totalmente receptivo y el cliente especificó que algunos bloques en el dispositivo móvil son totalmente diferentes a los de los dispositivos de escritorio, sería mejor dividir la estructura de carpetas de BEM en plataformas. Ejemplo de organización de botones en varias plataformas:
common.blocks/ button/ button.scss desktop.blocks/ button/ buttons.scss mobile.blocks/ button/ button.scss
Tenga en cuenta que este es solo un ejemplo si desea organizar todo su proyecto utilizando la metodología BEM. El árbol de archivos con estructura BEM no es obligatorio para usar BEM correctamente, puede usar BEM solo en algunos segmentos del proyecto. Hasta ahora no he estado usando esta estricta organización de estructura de archivos BEM donde cada elemento y modificador tiene su archivo creado. En cambio, solo estoy creando una estructura de archivos para bloques que tienen una declaración de sus elementos y modificadores.
BEM en la práctica
Como ahora está familiarizado con las convenciones de nomenclatura, demostraré la metodología BEM en la práctica. Digamos que tenemos este código HTML en acción:
<a class=”btn btn--big btn--primary-color” href=”#” title=”Title”> <span class=”btn__price”>$3.99</span> <span class=”btn__text”>Product</span> </a>
Con el siguiente marcado CSS aplicado:
.btn__price {/* Styles */} .btn__text {/* Styles */} .btn--big {/* Styles */} .btn--primary-color {/* Styles */}
Ahora, no se deje engañar. En nuestros ejemplos hasta ahora, casi siempre teníamos un bloque, un elemento y un modificador, lo que no siempre tiene que ser el caso.
Por ejemplo, digamos que tenemos un bloque llamado persona . Una persona tiene piernas y manos, también puede ser mujer o hombre. Si queremos definir a una persona de sexo masculino con la mano derecha se verá así:
.person--male__hand--right {/* Styles */}
Ahora puedes ver el significado real del BEM. Definimos una persona cuyo modificador es un género. Ya que no importa si una persona es hombre o mujer, tiene una mano, y la mano es un elemento. Y nuevamente, cada persona puede tener la mano derecha o la izquierda, lo que nuevamente es un modificador.

En otro caso, si queremos definir persona general con una sola mano, lo haremos así:
.person__hand {/* Styles */}
Como puede notar, una vez que se sienta cómodo con BEM, es muy fácil estructurar su estructura CSS y HTML con él.
Uso de BEM con preprocesadores CSS
Personalmente, no puedo imaginar comenzar ningún proyecto nuevo sin usar uno de los preprocesadores de CSS. Como todos saben, los preprocesadores son una gran cosa y nos brindan muchos beneficios y, lo que es más importante, son una combinación perfecta con la metodología BEM.
En el siguiente ejemplo, puedes ver el ejemplo más típico de BEM, en combinación con SASS:
.person { &__hand {/* Styles */} &__leg {/* Styles */} &--male { /* Styles */ &__hand { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } &__leg { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } } &--female { /* Styles */ &__hand { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } &__leg { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } } }
El código SASS se compilará en el siguiente CSS:
.person__hand {/* Styles */} .person__leg {/* Styles */} .person--male {/* Styles */} .person--male__hand {/* Styles */} .person--male__hand--left {/* Styles */} .person--male__hand--right {/* Styles */} .person--male__leg {/* Styles */} .person--male__leg--left {/* Styles */} .person--male__leg--right {/* Styles */} .person--female {/* Styles */} .person--female__hand {/* Styles */} .person--female__hand--left {/* Styles */} .person--female__hand--right {/* Styles */} .person--female__leg {/* Styles */} .person--female__leg--left {/* Styles */} .person--female__leg--right {/* Styles */}
Si quiere ir aún más lejos, puede usar una práctica combinación de SASS para BEM:
/// Block Element /// @param {String} $element - Element's name @mixin element($element) { &__#{$element} { @content; } } /// Block Modifier /// @param {String} $modifier - Modifier's name @mixin modifier($modifier) { &--#{$modifier} { @content; } }
Y puedes usarlo así:
.person { @include element('hand') {/* Person hand */} @include element('leg') {/* Person leg */} @include modifier('male') { /* Person male */ @include element('hand') { /* Person male hand */ @include modifier('left') { /* Person male left hand */ } @include modifier('right') { /* Person male right hand */ } } } }
Lo que producirá la siguiente salida CSS:
.person__hand { /* Person hand */ } .person__leg { /* Person leg */ } .person--male { /* Person male */ } .person--male__hand { /* Person male hand */ } .person--male__hand--left { /* Person male left hand */ } .person--male__hand--right { /* Person male right hand */ }
Sé que lo más probable es que no tenga un caso de uso por tanto tiempo, pero este es un gran ejemplo de cómo se usa BEM y por qué es tan poderoso, tanto en proyectos de pequeña como de gran escala.
Inicio de su proyecto BEM
Como se explica en la documentación oficial de BEM, la forma más sencilla de iniciar su propio proyecto BEM nuevo es utilizar el repositorio GIT existente. Simplemente use el comando de clonación de Git:
$ git clone https://github.com/bem/project-stub.git
A continuación, vaya a un directorio recién creado e instale todas las dependencias:
$ npm install
Se instalarán todas las dependencias requeridas:
Cree el proyecto usando ENB:
$ node_modules/.bin/enb make
Ejecute un modo de servidor para el desarrollo:
$ node_modules/.bin/enb server
Como resultado, aparece el siguiente mensaje:
Server started at 0.0.0.0:8080
Ahora, esto significa que el servidor está en funcionamiento. Ahora puede consultar los resultados en esta dirección:
http://localhost:8080/desktop.bundles/index/index.html
Como puede ver, hay muchos elementos ya creados que están definidos dentro del archivo bemjson
que se encuentra aquí:
project-stub/desktop.bundles/index/index.bemjson.js
Puede ver y explorar la estructura actual del archivo que está generando todo ese HTML, que ve en su archivo localhost index.html
. Vamos a modificar este archivo para obtener nuestro proyecto BEM "Persona" que explicamos en un capítulo anterior. Puede eliminar (o comentar) todo el código del archivo index.bemjson.js
y reemplazarlo con este:
module.exports = { block: 'page', title: 'Person BEM', favicon : '/favicon.ico', head : [ { elem : 'meta', attrs : { name : 'description', content : '' } }, { elem : 'meta', attrs : { name : 'viewport', content : 'width=device-width, initial-scale=1' } }, { elem : 'css', url : 'index.min.css' } ], scripts: [{ elem : 'js', url : 'index.min.js' }], content: [ { block: 'person', content: [ { elem: 'male', content: [ { elem: 'leg', mods: {side: 'left'}, content: 'Male person leg -- left' }, { elem: 'leg', mods: {side: 'right'}, content: 'Male person leg -- right' }, { elem: 'hand', mods: {side: 'left'}, content: 'Male person hand -- left' }, { elem: 'hand', mods: {side: 'right'}, content: 'Male person hand -- right' } ] }, { elem: 'female', content: [ { elem: 'leg', mods: {side: 'left'}, content: 'Female person leg -- left' }, { elem: 'leg', mods: {side: 'right'}, content: 'Female person leg -- right' }, { elem: 'hand', mods: {side: 'left'}, content: 'Female person hand -- left' }, { elem: 'hand', mods: {side: 'right'}, content: 'Female person hand -- right' } ] }, ] } ] };
Ahora, se generará el siguiente HTML:
<div class="person"> <div class="person__male"> <div class="person__leg person__leg_side_left"> Male person leg -- left </div> <div class="person__leg person__leg_side_right"> Male person leg -- right </div> <div class="person__hand person__hand_side_left"> Male person hand -- left </div> <div class="person__hand person__hand_side_right"> Male person hand -- right </div> </div> <div class="person__female"> <div class="person__leg person__leg_side_left"> Female person leg -- left </div> <div class="person__leg person__leg_side_right"> Female person leg -- right </div> <div class="person__hand person__hand_side_left"> Female person hand -- left </div> <div class="person__hand person__hand_side_right"> Female person hand -- right </div> </div> </div>
Como puede ver en el código anterior, el esquema de codificación BEM predeterminado se usó en este escenario, ya que solo estamos usando la configuración predeterminada que nos proporcionó BEM. Hay muchos más comandos y opciones que puede explorar y usar, como crear nuevas páginas, bloques o modificar BEM HTML. No profundizaré demasiado en esto, y todo se puede encontrar en la documentación oficial de BEM.
Ventajas y preocupaciones
Ventajas
- BEM es excelente para el mantenimiento. ¿Cuántas veces ha tenido que trabajar detrás de alguien en un proyecto a gran escala y tiene demasiado miedo de cambiar algo sin que algo desconocido se derrumbe? Al usar BEM, sabe el propósito exacto del elemento y en qué bloque puede aparecer.
- Los nombres de las clases son lógicos e intuitivos, y cada miembro del equipo sabe qué hace ese elemento en el sitio web. BEM brinda a todos en un proyecto una sintaxis declarativa que pueden compartir para que estén en la misma página.
- BEM elimina los selectores CSS anidados. Cada elemento HTML tiene su propia clase CSS, y por su nombre sabes cuál es su propósito. Un selector para gobernarlos a todos .
Inquietudes y errores comunes
- No profundice demasiado en la anidación. La regla principal debería ser no usar más de dos niveles de padre e hijo.
- Tenga cuidado con dónde comienza su alcance de bloque. Un error común aquí es cuando un desarrollador está usando un bloque, pero no se da cuenta de que en el punto posterior del desarrollo ese mismo bloque tendrá un bloque padre principal que posiblemente romperá la regla con el anidamiento.
- Evite SASS @extend. Para citar a Harry Roberts sobre esto:
Puede crear una mayor cantidad de combinaciones en la vista al no 'atar' las clases en Sass. El HTML tiene un rastro de papel mucho mejor en el que puede ver cada clase actuando en una parte del DOM. Su CSS se mantiene mucho más delgado en el sentido de que no tiene que crear nuevas clases de marcador de posición (o las clases de manifiesto que las combinan) cada vez que desea crear una nueva pieza de interfaz de usuario.
Conclusión
Cuando vi el esquema de codificación BEM por primera vez, mi primer pensamiento fue:
Estas clases son demasiado largas para escribir y leer.
Pero después de probarlo, ahora no puedo imaginar comenzar un nuevo proyecto sin usarlo. Para mí, BEM mejoró enormemente la capacidad de mantenimiento de mi código, y puedo decir con seguridad que cada desarrollador que será "arrojado" al proyecto basado en BEM se pondrá al día muy rápidamente con toda la estructura del código.
A pesar de todo esto, hay mucha discusión en las redes sociales sobre BEM. Algunos dicen que BEM no es bueno y se preguntan por qué deberían escribir clases de nombres tan largos en lugar de simplemente usar elementos HTML anidados predeterminados. Bueno, nadie dice que te deba gustar BEM, pero el hecho es que la mayoría de los desarrolladores front-end lo aceptan y lo encuentran extraordinariamente útil.