Ressources en ligne sur BEM, Block Element Modifier
Une liste de ressources qui m’ont aidé à comprendre la méthodologie BEM:
- Site officiel sur la méthodologie BEM
- MindBEMding – getting your head ’round BEM syntax
- Atomic OOBEMITSCSS
- BEM block, naming & nesting
Example perso avec un store locator
Regarder notamment le principe d’imbrication de plusieurs BLOCKs et la présence de la classe helper .is-store--china
(comment elle est utilisée dans le code LESS ensuite).
Code HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<div id="storeLocator" class="store-locator is-store--china"> <div class="store-locator__map"> <div id="mapControl" class="map-control"> <input type="text" id="autocompleteField" class="map-control--autocomplete__field" placeholder="Enter a place"> <button id="geolocationButton" class="map-control--geolocation__button"> <span>Me localiser</span> </button> </div> <div id="map" class="map"> <?php // MUST remain empty; here comes the map ?> </div> </div> <div class="store-locator__result"> <div class="result-filter"></div> <div class="result-list"> <p>Result...</p> </div> </div> </div> </div> |
Code CSS (LESS)
Première explication sous forme de code commenté (pour comprendre)
…mais, ATTENTION: ce n’est pas comme ça que vous devez organiser votre code. Voir la section suivante.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.store-locator {} /* store-locator est un nouveau BLOCK */ .store-locator__map {} /* la map est un ELEMENT (une partie) du store locator comme la main est une partie de la personne */ .map-control {} /* map-control est un nouveau BLOCK, enfant du BLOCK store-locator */ .map-control--autocomplete {} /* est un MODIFIER (autocomplete est un type/genre) de map-control comme la femme est un type/genre de personne */ .map-control--autocomplete__field {} /* field est ELEMENT (une partie) de autocomplete */ .map-control--geolocation {} /* est un MODIFIER (geolocation est un autre type/genre) de map-control */ .map-control--geolocation__button {} /* button est un ELEMENT (une partie) de geolocation */ .map {} /* map est un nouveau BLOCK, enfant du BLOCK store-locator */ .store-locator__result {} /* les result sont un ELEMENT (une partie) du store locator comme la main est une partie de la personne */ .result-filter {} /* result-filter est un nouveau BLOCK, enfant du BLOCK store-locator */ .result-list {} /* result-list est un nouveau BLOCK, enfant du BLOCK store-locator (c'est une liste de boutiques ou de retailers mais, par principe d'abstraction, on ne le précise pas */ |
Organisation du code LESS en composants/BLOCKs
Valable pour SASS/SCSS également.
L’organisation du code en parties représentant chacune un block/composant permet le respect du principe d’inception: pas plus de 3 niveaux d’imbrication (à l’exception de la déclaration de :pseudo-classes
).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
.store-locator { display: block; &__map { height: 100%; } &__result {} } .service-center {} .boutique-selector {} .map-control { max-width: 50%; &--autocomplete { &__field {} } &--geolocation { &__button { &:hover {} } } } .map { height: 100%; } |
Autre exemple, avec du HTML cette fois:
Le h3 class="store__name"
s’affichera:
- en rouge si la classe
store--is-boutique
est présente sur l’élément parent - en gris si la classe
store--is-retailer
est présente sur l’élément parent
Les autres styles appliqués au h3 class="store__name"
seront affectés aux deux.
1 2 |
<a class="store store--is-retailer" href="#"> <h3 class="store__name">Bartorelli 1882 Spa</h3> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
.store { &--is-boutique & { &__name { color: #c40d2e; } } &--is-retailer & { &__name { color: #555555; } } &__name { font-weight: 700; font-size: 16px; text-transform: uppercase; } |
Exploitation d’une classe helper .is-store--china
L’organisation du code en parties représentant chacune un block/composant est reprise. La classe helper s’intercale au besoin.
Pour <div class="store-locator">
, toutes les bordures seront pink.
Pour <div class="store-locator is-store--china">
, toutes les bordures seront red.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
.store-locator { border: 12px solid pink; &.is-store--china { border: 12px solid red; } &__map { border: 12px solid pink; .is-store--china & { border: 12px solid red; } } } .map-control { border: 12px solid pink; &--autocomplete { &__field { border: 6px solid pink !important; } } .is-store--china & { border: 12px solid red; &--autocomplete { &__field { border: 6px solid red !important; } } } } |