Luchando contra BEM CSS: 10 problemas comunes y cómo evitarlos

 

 

 

  • Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX
  • SmashingConf Friburgo 2024

  • Índice
    1. 1. "¿Qué hacer con los selectores de 'nietos' (y más allá)?"
    2. 2. "¿Debería establecer espacios entre nombres?"
    3. 3. "¿Cómo debería nombrar los envoltorios?"
    4. 4. “¿Componentes cruzados…?”
    5. 5. “¿Modificador o componente nuevo?”
    6. 6. "¿Cómo manejar los estados?"
    7. 7. "¿Cuándo está bien no agregar una clase a un elemento?"
    8. 8. "¿Cómo anidar componentes?"
    9. 9. "¿No terminarán los componentes con un millón de clases?"
    10. 10. "¿Podemos cambiar el tipo de componente de forma responsiva?"
    11. Resumen
      1. Otras lecturas

    BEM ha sido un absoluto salvavidas para mí en mi esfuerzo por crear aplicaciones de forma modular y basada en componentes. David Berner lo ha estado usando durante casi tres años y los problemas mencionados anteriormente son los pocos obstáculos que ha encontrado en el camino. Este artículo pretende ser útil para las personas que ya son entusiastas de BEM y desean utilizarlo de forma más eficaz o para las personas que tienen curiosidad por saber más sobre él.

     

    Si acaba de descubrir BEM o es un experto (¡al menos en términos web!), probablemente aprecie lo útil que es esta metodología. Si no sabe qué es BEM, le sugiero que lo lea en el sitio web de BEM antes de continuar con esta publicación, porque usaré términos que suponen una comprensión básica de esta metodología CSS.

    Este artículo pretende ser útil para las personas que ya son entusiastas de BEM y desean utilizarlo de forma más eficaz o para las personas que tienen curiosidad por saber más sobre él.

    Ahora bien, no me hago ilusiones de que esta sea una forma hermosa de nombrar las cosas. No lo es en absoluto. Una de las cosas que me impidió adoptarlo durante tanto tiempo fue lo tremendamente fea que es la sintaxis. El diseñador que hay en mí no quería que mi sexy marcado estuviera abarrotado de guiones dobles sucios y guiones dobles desagradables.

     

    El desarrollador que hay en mí lo miró de forma pragmática. Y, finalmente, la forma lógica y modular de construir una interfaz de usuario superó el lado derecho de mi cerebro que se quejaba: "¡Pero no es lo suficientemente bonito!". Ciertamente no recomiendo elegir un centro de mesa para la sala de estar de esta manera, pero cuando necesites un chaleco salvavidas (como lo haces en un mar de CSS), prevaleceré la función en cualquier momento. De todos modos, basta de divagar. Aquí están los 10 dilemas con los que he luchado y algunos consejos sobre cómo afrontarlos.

    1. "¿Qué hacer con los selectores de 'nietos' (y más allá)?"

    Para aclarar, usaría un selector nieto cuando necesite hacer referencia a un elemento que está anidado en dos niveles de profundidad. Estos chicos malos son la pesadilla de mi vida y estoy seguro de que su mal uso es una de las razones por las que la gente tiene una aversión inmediata a BEM. Te daré un ejemplo:

    div div !-- Here comes the grandchild… -- h2Title text here/h2 /div div img src="some-img.png" alt="description" pLorem ipsum dolor sit amet, consectetur/p pAdipiscing elit. a href="/somelink.html"Pellentesque amet/a /p /div/div

    Como se puede imaginar, nombrar de esta manera puede salirse de control rápidamente, y cuanto más anidado esté un componente, más horribles e ilegibles se volverán los nombres de las clases. He usado un nombre de bloque corto de c-cardy los nombres de elemento cortos de body, texty link, pero puedes imaginar lo fuera de control que se pone cuando el elemento del bloque inicial se llama algo así como c-drop-down-menu.

    Creo que el patrón de doble subrayado debería aparecer solo una vez en el nombre de un selector. BEM significa , no . Por lo tanto, evite nombrar varios niveles de elementos. Si está llegando a los niveles de tataranieto, probablemente querrá revisar la estructura de sus componentes de todos modos.BlockElement–Modifier BlockElement__Element–Modifier

    La denominación BEM no está estrictamente ligada al DOM, por lo que no importa a cuántos niveles de profundidad esté anidado un elemento descendiente. La convención de nomenclatura está ahí para ayudarle a identificar las relaciones con el bloque de componentes de nivel superior (en este caso, c-card.

    Así es como trataría el mismo componente de la tarjeta:

    div div h2Title text here/h2 /div div img src="some-img.png" alt="description" pLorem ipsum dolor sit amet, consectetur/p pAdipiscing elit. a href="/somelink.html"Pellentesque amet/a /p /div/div

    Esto significa que todos los elementos descendientes se verán afectados únicamente por el bloque de cartas. Por lo tanto, podríamos mover el texto y las imágenes o incluso introducir un nuevo elemento sin romper la estructura semántica.c-cardheaderc-cardfooter

     

    2. "¿Debería establecer espacios entre nombres?"

    A estas alturas, probablemente hayas notado el uso de c-basura en mis ejemplos de código. Esto significa "componente" y forma la base de cómo le doy el espacio de nombres a mis clases BEM. Esta idea surge de la técnica de espacio de nombres de Harry Robert , que mejora la legibilidad del código.

    Este es el sistema que he adoptado y muchos de los prefijos aparecerán en los ejemplos de código de este artículo:

    Tipo Prefijo Ejemplos Descripción
    Componente c- c-cardc-checklist Forme la columna vertebral de una aplicación y contenga todos los cosméticos de un componente independiente.
    Módulo de diseño l- l-gridl-container Estos módulos no tienen cosmética y se utilizan exclusivamente para posicionar c-componentes y estructurar el diseño de una aplicación.
    Ayudantes h- h-showh-hide Estas clases de utilidad tienen una única función, y a menudo se utilizan !importantpara aumentar su especificidad. (Comúnmente utilizado para posicionamiento o visibilidad).
    Estados is-has- is-visiblehas-loaded Indica los diferentes estados que c-puede tener un componente. Se pueden encontrar más detalles sobre este concepto en el problema 6 a continuación, pero
    Ganchos de JavaScript js- js-tab-switcher Estos indican que el comportamiento de JavaScript está adjunto a un componente. No se debe asociar ningún estilo con ellos; se utilizan exclusivamente para permitir una manipulación más sencilla del script.

    Descubrí que el uso de estos espacios de nombres ha hecho que mi código sea infinitamente más legible. Incluso si no logro venderte en BEM, esta es definitivamente una conclusión clave.

    Podría adoptar muchos otros espacios de nombres, como qa-para pruebas de control de calidad, ss-para enlaces del lado del servidor, etc. Pero la lista anterior es un buen punto de partida y puede introducir otros a medida que se sienta cómodo con la técnica.

    Verás un buen ejemplo de la utilidad de este estilo de espacio de nombres en el siguiente problema.

    3. "¿Cómo debería nombrar los envoltorios?"

    Algunos componentes requieren un contenedor (o contenedor) principal que dicta el diseño de los elementos secundarios. En estos casos, siempre trato de abstraer el diseño en un módulo de diseño, como l-gride insertar cada componente como contenido de cada uno l-grid__item.

     

    En nuestro ejemplo de tarjeta, si quisiéramos diseñar una lista de cuatro c-card, usaría el siguiente marcado:

    ul li div div […] /div div […] /div /div /li li div div […] /div div […] /div /div /li li div div […] /div div […] /div /div /li li div div […] /div div […] /div /div /li/ul

    Ahora debería tener una idea sólida de cómo deben combinarse los módulos de diseño y los espacios de nombres de los componentes.

    No tenga miedo de utilizar un pequeño margen de beneficio adicional para ahorrarse un gran dolor de cabeza. ¡Nadie te dará una palmadita en la espalda por quitarte un par de divetiquetas!

    En algunos casos, esto no es posible. Si, por ejemplo, tu grilla no te va a dar el resultado que deseas o simplemente quieres algo semántico para nombrar un elemento padre, ¿qué debes hacer? Tiendo a optar por la palabra containero list, según el escenario. Siguiendo con nuestro ejemplo de tarjetas, podría usar div[…]/divo ul[…]/ul, según el caso de uso. La clave es ser coherente con la convención de nomenclatura.

    4. “¿Componentes cruzados…?”

    Otro problema que se enfrenta comúnmente es el de un componente cuyo estilo o posicionamiento se ve afectado por su contenedor principal. Simurai cubre en detalle varias soluciones a este problema . Simplemente le informaré sobre lo que creo que es el enfoque más escalable.

    Para resumir, supongamos que queremos agregar a c-buttonen card__bodynuestro ejemplo anterior. El botón ya es un componente propio y está marcado así:

    buttonClick me!/button

    Si no hay diferencias de estilo en el componente del botón normal, entonces no hay problema. Simplemente lo colocaríamos así:

    div div h2Title text here/h3 /div div img src="some-img.png" pLorem ipsum dolor sit amet, consectetur/p pAdipiscing elit. Pellentesque./p !-- Our nested button component -- buttonClick me!/button /div/div

    Sin embargo, ¿qué sucede cuando hay algunas diferencias sutiles de estilo; por ejemplo, queremos hacerlo un poco más pequeño, con esquinas completamente redondeadas, pero solo cuando es parte de un c-cardcomponente?

    Anteriormente, dije que considero que una clase de componentes cruzados es la solución más sólida:

    div div h2Title text here/h3 /div div img src="some-img.png" pLorem ipsum dolor sit amet, consectetur/p pAdipiscing elit. Pellentesque./p !-- My *old* cross-component approach -- buttonClick me!/button /div/div

    Esto es lo que en el sitio web de BEM se conoce como “mezcla”. Sin embargo, he cambiado mi postura sobre este enfoque, luego de algunos excelentes comentarios de Esteban Lussich. Free porn comics

     

    En el ejemplo anterior, la c-card__c-buttonclase intenta modificar una o más propiedades existentes de c-button, pero dependerá del orden de origen (o incluso de la especificidad) para poder aplicarlas con éxito. La c-card__c-buttonclase funcionará sólo si se declara después del c-buttonbloque en el código fuente, lo que podría salirse de control rápidamente a medida que se construyen más de estos componentes cruzados. (Golpear a un !importantes, por supuesto, una opción, ¡pero ciertamente no lo recomendaría!)

    La apariencia de un elemento de interfaz de usuario verdaderamente modular debe ser totalmente independiente del contenedor principal del elemento: debe verse igual independientemente de dónde lo coloque. Agregar una clase de otro componente para un estilo personalizado, como lo hace el enfoque de “mezcla”, viola el principio abierto/cerrado del diseño basado en componentes, es decir, no debería haber dependencia de otro módulo por motivos estéticos.

    Lo mejor que puede hacer es utilizar un modificador para estas pequeñas diferencias cosméticas, porque es posible que desee reutilizarlas en otros lugares a medida que su proyecto crezca.

    buttonClick me!/button

    Incluso si nunca vuelve a utilizar esas clases adicionales, al menos no estará vinculado al contenedor principal, la especificidad o el orden de origen para aplicar las modificaciones.

    Por supuesto, la otra opción es volver con su diseñador y decirle que el botón debe ser coherente con el resto de los botones del sitio web y evitar este problema por completo... pero eso es para otro día.

    5. “¿Modificador o componente nuevo?”

    Uno de los mayores problemas es decidir dónde termina un componente y comienza uno nuevo. En el c-cardejemplo, más adelante podría crear otro componente con un nombre c-panelcon atributos de estilo muy similares pero con algunas diferencias notables.

    Pero, ¿qué determina si debe haber dos componentes, c-panely c-card, o simplemente un modificador c-cardque aplique los estilos únicos?

    Es muy fácil sobremodularizar y convertir todo en un componente. Recomiendo comenzar con modificadores, pero si descubre que el archivo CSS de su componente específico se está volviendo difícil de administrar, entonces probablemente sea el momento de dividir algunos de esos modificadores. Un buen indicador es cuando tienes que restablecer todo el CSS de "bloque" para poder diseñar tu nuevo modificador; esto, para mí, sugiere tiempo para el nuevo componente.

    La mejor manera, si trabaja con otros desarrolladores o diseñadores, es pedirles su opinión. Tráelos por un par de minutos y discútelo. Sé que esta respuesta es un poco evasiva, pero para una aplicación grande, es vital que todos comprendan qué módulos están disponibles y se pongan de acuerdo exactamente sobre qué constituye un componente.

    6. "¿Cómo manejar los estados?"

    Este es un problema común, particularmente cuando se aplica estilo a un componente en un estado activo o abierto. Digamos que nuestras tarjetas tienen un estado activo; entonces, cuando se hace clic en ellos, se destacan con un bonito tratamiento de estilo en el borde. ¿Cómo se hace para nombrar esa clase?

     

    A mi modo de ver, realmente tienes dos opciones: un gancho de estado independiente o un modificador de nombres similar a BEM a nivel de componente:

    !-- standalone state hook --div […]/div!-- or BEM modifier --div […]/div

    Si bien me gusta la idea de mantener la denominación similar a BEM para mantener la coherencia, la ventaja de la clase independiente es que facilita el uso de JavaScript para aplicar enlaces de estado genéricos a cualquier componente. Cuando tienes que aplicar clases de estado basadas en modificadores específicos con script, esto se vuelve más problemático. Por supuesto, es completamente posible, pero significa escribir mucho más JavaScript para cada posibilidad.

    Tiene sentido ceñirse a un conjunto estándar de ganchos estatales. Chris Pearce ha compilado una buena lista , por lo que recomiendo simplemente seleccionarlas.

    7. "¿Cuándo está bien no agregar una clase a un elemento?"

    Puedo entender que las personas se sientan abrumadas por la gran cantidad de clases necesarias para crear una pieza compleja de interfaz de usuario, especialmente si no están acostumbradas a asignar una clase a cada etiqueta.

    Normalmente, adjuntaré clases a cualquier cosa que deba tener un estilo diferente en el contexto del componente. A menudo dejo plas etiquetas sin clase, a menos que el componente requiera que se vean únicas en ese contexto.

    Por supuesto, esto podría significar que su marcado contendrá muchas clases. Sin embargo, en última instancia, sus componentes podrán vivir de forma independiente y dejarse caer en cualquier lugar sin riesgo de efectos secundarios.

    Debido a la naturaleza global de CSS, poner una clase en todo nos da control sobre cómo se representan exactamente nuestros componentes. El malestar mental inicial causado bien vale los beneficios de un sistema totalmente modular.

    8. "¿Cómo anidar componentes?"

    Supongamos que queremos mostrar una lista de verificación en nuestro c-cardcomponente. Aquí hay una demostración de cómo no marcar esto:

    div div h2Title text here/h3 /div div pI would like to buy:/p !-- Uh oh! A nested component -- ul li input type="checkbox" name="checkbox" label for="option_1"Apples/label /li li input type="checkbox" name="checkbox" label for="option_2"Pears/label /li /ul /div !-- .c-card__body --/div!-- .c-card --

    Tenemos un par de problemas aquí. Uno es el selector abuelo que cubrimos en la sección 1. El segundo es que todos los estilos aplicados tienen como ámbito este caso de uso específico y no serán reutilizables.c-cardchecklistitem

    Mi preferencia aquí sería dividir la lista en un módulo de diseño y los elementos de la lista de verificación en sus propios componentes, permitiéndoles usarse de forma independiente en otros lugares. Esto l-también vuelve a poner en juego nuestro espacio de nombres:

    div div h2Title text here/h3 /div divdiv pI would like to buy:/p !-- Much nicer - a layout module -- ul li !-- A reusable nested component -- div input type="checkbox" name="checkbox" label for="option_1"Apples/label /div /li li div input type="checkbox" name="checkbox" label for="option_2"Pears/label /div /li /ul !-- .l-list -- /div !-- .c-card__body --/div!-- .c-card --

    Esto le evita tener que repetir los estilos y significa que podemos usar tanto el l-listcomo c-checkboxen otras áreas de nuestra aplicación. Significa un poco más de marcado, pero es un pequeño precio a pagar por la legibilidad, la encapsulación y la reutilización. ¡Probablemente hayas notado que estos son temas comunes!

     

    9. "¿No terminarán los componentes con un millón de clases?"

    Algunos argumentan que tener muchas clases por elemento no es bueno y –modifiersciertamente puede sumar. Personalmente, no encuentro que esto sea problemático, porque significa que el código es más legible y sé exactamente lo que se supone que debe hacer.

    Para contextualizar, este es un ejemplo de cuatro clases que se necesitan para diseñar un botón:

    buttonClick me!/button

    Entiendo que esta sintaxis no es la más bonita a la vista, pero es explícita.

    Sin embargo, si esto te causa un gran dolor de cabeza, puedes consultar la técnica de extensión que se le ocurrió a Sergey Zarouski. Básicamente, lo usaríamos .className [class^=“className”], [class*=” className”]en la hoja de estilos para emular la funcionalidad de la extensión en CSS básico. Si esta sintaxis le resulta familiar, es porque es muy similar a la forma en que Icomoon maneja sus selectores de íconos.

    Con esta técnica, su resultado podría verse así:

    buttonClick me!/button

    No sé si el impacto en el rendimiento al usar los selectores class^=y class*=es mucho mayor que el uso de clases individuales a escala, pero en teoría esta es una buena alternativa. A mí me parece bien la opción de clases múltiples, pero pensé que merecía una mención para aquellos que prefieren una alternativa.

    10. "¿Podemos cambiar el tipo de componente de forma responsiva?"

    Este fue un problema que me planteó Arie Thulank y me costó encontrar una solución 100% concreta.

    Un ejemplo de esto podría ser un menú desplegable que se convierte en un conjunto de pestañas en un punto de interrupción determinado, o una navegación fuera de la pantalla que cambia a una barra de menú en un punto de interrupción determinado.

    Básicamente, un componente tendría dos tratamientos cosméticos muy diferentes, dictados por una consulta de los medios.

    Mi inclinación por estos dos ejemplos particulares es simplemente construir un c-navigationcomponente, porque en ambos puntos de interrupción esto es esencialmente lo que está haciendo. Pero me hizo pensar: ¿qué tal una lista de imágenes que se convierte en un carrusel en pantallas más grandes? Esto me parece un caso extremo, y siempre que esté bien documentado y comentado, creo que es perfectamente razonable crear un componente independiente y único para este tipo de interfaz de usuario, con nombres explícitos (como c-image-list-to-carousel).

    Harry Roberts ha escrito sobre sufijos responsivos , que es una forma de manejar esto. Su enfoque está destinado más a cambios en el diseño y los estilos de impresión, que a cambios de componentes completos, pero no veo por qué la técnica no podría aplicarse aquí. Básicamente, crearías clases como esta:

    ul

    Estos luego residirían en sus consultas de medios para los respectivos tamaños de pantalla. Consejo profesional: debes escapar del @signo en tu CSS con una barra invertida, así:

    .c-image-list@small-screen { /* styles here */}

    No he tenido muchos motivos para crear este tipo de componentes, pero esta parece una forma muy amigable para los desarrolladores de hacerlo, si es necesario. La siguiente persona que entre debería poder comprender fácilmente su intención. No estoy defendiendo nombres como small-screeny large-screen: se utilizan aquí únicamente para facilitar la lectura.

    Resumen

    BEM ha sido un absoluto salvavidas para mí en mi esfuerzo por crear aplicaciones de forma modular y basada en componentes. Lo he estado usando durante casi tres años y los problemas anteriores son los pocos obstáculos que he encontrado en el camino. Espero que este artículo te haya resultado útil y, si aún no has probado BEM, te recomiendo encarecidamente que lo hagas.

    Nota : esta es una versión mejorada de mi artículo original " Luchando contra BEM: 5 problemas comunes y cómo evitarlos ", que apareció en Medium. Agregué cinco problemas comunes más (algunos de los cuales se preguntaron en los comentarios de ese artículo) y modifiqué mis puntos de vista sobre uno de los problemas originales.

    Otras lecturas

    • Una nueva metodología front-end: BEM
    • Reducción de la metodología BEM para proyectos pequeños
    • La evolución de la metodología BEM
    • Comenzando con la ramificación de neón

    (vf, al, il, mrn)Explora más en

    • Codificación
    • Marcos
    • CSS
    • javascript
    • HTML5





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Luchando contra BEM CSS: 10 problemas comunes y cómo evitarlos

    Luchando contra BEM CSS: 10 problemas comunes y cómo evitarlos

    Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX SmashingConf Friburgo 2024 Índice

    programar

    es

    https://aprendeprogramando.es/static/images/programar-luchando-contra-bem-css-10-problemas-comunes-y-como-evitarlos-893-0.jpg

    2024-05-20

     

    Luchando contra BEM CSS: 10 problemas comunes y cómo evitarlos
    Luchando contra BEM CSS: 10 problemas comunes y cómo evitarlos

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20