Block, Element, Modifier
Block, Element, Modifier (BEM) ist eine Namenskonvention in die Softwareentwicklung für die Elemente einer Webseite bzw. Weboberfläche.
BEM wurde zwischen 2007 und 2009 vom russischen Suchmaschinenbetreiber Yandex entwickelt.[1]
Konzept
In BEM wird die Hypertext Markup Language, das übliche HTML einer Webseite, in Blöcke und Elemente aufgeteilt. Elemente existieren nur innerhalb eines Blocks, Blöcke können auch in anderen Blöcken existieren. Die Modifier verändern die Darstellung der Elemente und Blöcke.[2]
Als Beispiel dient Pinterest, ein Online-Pinnwand für Grafiken und Fotografien mit optionalem sozialen Netzwerk und visueller Suchmaschine.
Block
Der Block ist eine HTML-Einheit, die unabhängig von ihrem Einsatzort existiert. Für gewöhnlich enthalten Blöcke HTML-Elemente zur Navigation (nav), zu Kopfzeile (header), Fußzeile (footer) oder zu ungeordneten Listen <ul>. Weitere Blöcke können definiert werden, wenn sie Eigenschaften haben, die in einer speziellen Anwendung genutzt werden.
Element
Die Elemente bestehen auch aus HTML, sind aber an einen Block gebunden, z. B. die Listenelemente <ul> oder <ol> und <li>. Ob ein bestimmtes Objekt auf der Webseite zum Element oder zum Block wird, hängt vom Kontext ab. Soll das Objekt unabhängig vom umgebenden Block genutzt werden, sollte es nicht ein Element, sondern ein Block sein. Umgekehrt, wenn das Objekt nicht wiederverwendet wird und nur im Kontext eines Blocks nutzbar ist, wird es als Element angelegt.
Modifier
Modifier werden für kleine Veränderungen in der Gestaltung von Blöcken und Elementen genutzt. Diese Anweisungen gehören zu den HTML-Elementen und sie bestimmen das Aussehen der Website. Beispielsweise betreffen sie das Format einer Schaltfläche, die Farbvariante oder die Größe. Realisiert werden sie über Cascading Style Sheets (CSS). Gute Modifier sind ein wesentlicher Teil von BEM.
Namenskonvention
Die Namenskonvention in BEM ist der Kern des Entwurfsmusters. Sie dient dazu, eine flache CSS-Hierarchie zu erzeugen. CSS-Klassen sind in BEM folgendermaßen aufgebaut:[3]
.block{}
.block--modifier{}
.block__element{}
.block__element--modifier{}
Die Trennzeichen zwischen Block und Element, sowie zwischen Block/Element und Modifier, sind frei wählbar. Sollten sie vom Standard abweichen ist ein Trennzeichen zu wählen, das in der normalen Klassenbezeichnung nicht vorkommt.
BEM-basierte Frameworks
Es gibt eine Vielzahl von CSS-Frameworks, die auf BEM basieren. Eine sehr bekannte Umsetzung ist inuit.css von Harry Roberts.[4]
Anwendungsbeispiel
Das Beispiel zeigt die Restrukturierung des Codes der Pinterest Startseite.
Eine mosaikartig zusammengesetzte Grafik ist eine Kachelgrafik, die einzelnen Blöcke und Elemente werden Tiles genannt. Das Standard Tile sieht wie folgt aus:
.tile-grid__item{}
.tile{}
.tile__description{}
.tile__author{}
.tile__image{}
.tile__author-title{}
.tile__author-description{}
.tile__author-image{}
Die Blöcke und Elemente sowie deren Modifier eines Featured Tiles sind:
.tile-grid__item{}
.tile{}
.tile__author--featured{}
.tile__author-title{}
.tile__author-description--featured{}
.tile__author-image--featured{}
.showcast{}
.showcast__big-image{}
.showcast__small-image{}
.button--white{}
.text-link{}
.flat-button--white{}
Die Klassenbezeichnung zeigt, dass die Blöcke für die Wiederverwendbarkeit geschrieben wurden. So kann der Block Showcast ebenso in einem völlig anderen Kontext eingesetzt werden, zum Beispiel bei einem Blog-Artikel.
Das folgende Beispiel zeigt das vollständige HTML-Markup für das Featured Tile und für das Standard Tile inklusive grid. Das tile-grid dient als Schnittstelle und Wrapper-Software für alle Tiles, was die Positionierung auf der Website vereinfacht.
<div class="tile-grid">
<div class="tile-grid__item">
<div class="tile">
<div class="tile__author--featured">
<div class="tile__author-image--featured">
<img src="path/to/image">
</div>
<div class="tile__author-title--featured">
Design
</div>
<div class="tile__author-description--featured">
Desi Themsfeldt
</div>
</div>
<div class="showcast">
<div class="showcast__big-image">
<img src="path/to/image">
</div>
<div class="showcast__small-image">
<img src="path/to/image">
</div>
<div class="showcast__small-image">
<img src="path/to/image">
</div>
<div class="showcast__small-image">
<img src="path/to/image">
</div>
</div>
<button class="button--white">
Pinnwand folgen
</button>
<a class="text-lin">
Weitere Ideen von Freunden
</a>
</div>
<button class="flat-button--white">
Freunde zum Pinnen einladen
</button>
</div>
<div class="tile-grid__item">
<div class="tile">
<div class="tile__image">
<img src="path/to/file">
</div>
<div class="tile__description">
Tasche JohnBoy by Elbmarie (freebook)
</div>
<div class="tile__author">
<div class="tile__author-image">
<img src="path/to/image">
</div>
<div class="tile__author-title">
Für dich ausgewählt
</div>
<div class="tile__author-description">
Nähen
</div>
</div>
</div>
</div>
</div>
Dagegen hat das HTML Markup des echten Featured Tile von Pinterest die folgende, komplexe Form:
<div class="FriendCenterMerchandising Module fixedHeight follow networkConnected" data-component-type="12001">
<div class="fallbackContent">
<div class="centered">
<a href="/find_friends/recommendations/?invite_src=homefeed_friend_center_merch" data-element-type="996">
<h2>Sammeln deine Freunde Pins, die dir gefallen?</h2>
<div class="sampleImage"></div>
</a>
</div>
</div>
<div class="suggestionContent">
<div class="FriendBoardRecommendationTiles Module cycler">
<div class="Module ModuleCycler default">
<div class="FriendBoardRecommendationTile Module boardUserCompact">
<div class="DiscoveryTile Module noContainer">
<div class="dismiss">
<div class="closeIcon"></div>
</div>
<div class="Module User boardRepTitle hasText thumb">
<a class="profileSource" href="/trdaisy/design/" data-element-type="52">
<div class="thumbImageWrapper">
<img src="https://s-media-cache-ak0.pinimg.com/avatars/trdaisy_1385371223_75.jpg"
alt="Desi Themsfeldt" title="Mehr von Desi Themsfeldt">
</div>
<h3 class="title">Design</h3>
<h4 class="fullname">
Desi Themsfeldt
</h4>
</a>
</div>
<div class="Board Module boardCoverImage draggable noContainer noContext">
<a href="/trdaisy/design/" class="boardLinkWrapper" data-element-type="36">
<div class="boardName">
<div class="name">
Design
</div>
</div>
<div class="boardCoverWrapper">
<span class="hoverMask"></span>
<img src="https://s-media-cache-ak0.pinimg.com/216x146/24/2d/74/242d744cecd607e24928dd0395cf219d.jpg"
class="boardCover" data-load-state="pending" alt="Design/von ">
<span class="boardPinCount">
<div class="Module PinCount">
<span class="pinIcon"></span>29
</div>
</span>
</div>
<ul class="boardThumbs">
<li>
<span class="hoverMask"></span>
<img src="https://s-media-cache-ak0.pinimg.com/75x75/d5/e7/cd/d5e7cdfad2ef8ed963af6a2b56215d5d.jpg"
class="thumb" data-load-state="pending">
</li>
<li>
<span class="hoverMask"></span>
<img src="https://s-media-cache-ak0.pinimg.com/75x75/96/73/d5/9673d5d69b4b3e4472a19219f710da44.jpg"
class="thumb" data-load-state="pending">
</li>
<li>
<span class="hoverMask"></span>
<img src="https://s-media-cache-ak0.pinimg.com/75x75/72/f0/b7/72f0b7cab11539d8e0fc28e0a416987b.jpg"
class="thumb" data-load-state="pending">
</li>
</ul>
</a>
<button class="BoardFollowButton Button FollowButton Module boardFollowUnfollowButton btn hasText notNavigatable rounded"
data-element-type="37" type="button">
<span class="buttonText">Pinnwand folgen</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<a class="seeAllFriends" href="/find_friends/recommendations/?invite_src=homefeed_friend_center_merch" data-element-type="996">
Weitere Ideen von Freunden
<div class="arrow"></div>
</a>
</div>
<div class="loadingContent">
<div class="caption">
Ideen von Freunden erkunden
</div>
</div>
</div>
Das HTML Markup eines Standard Tile in Pinterest sieht wie folgt aus:
<div class="Module Pin summary" data-component-type="0">
<div class="pinWrapper ">
<div class="bulkEditPinWrapper">
</div>
<div class="pinImageActionButtonWrapper">
<div class="repinSendButtonWrapper">
<button class="Button Module ShowModalButton btn primary primaryOnHover repinSmall rounded" data-element-type="0" type="button">
<em></em>
<span class="accessibilityText">Pin it</span></button>
<button class="Button DropdownButton Module btn hasText rounded sendSmall sendPinGrid" data-element-type="98" type="button">
<em></em>
<span class="buttonText">Senden</span>
</button>
</div>
<div class="likeEditButtonWrapper">
<button class="Button LikeButton Module PinLikeButton btn likeSmall rounded" data-element-type="1" data-source-interest-id="" type="button">
<em></em>
<span class="accessibilityText">Gefällt mir</span></button>
</div>
<a class="Button Module NavigateButton borderless hasText pinNavLink navLinkOverlay" data-element-type="162" href="https://djdodo-kreativ.blogspot.com/2016/01/rums-88-gute-nacht-johnboy.html?m=1%22 rel="nofollow" type="button">
<em></em>
<span class="buttonText">Mehr Infos: djdodo-kreativ.blogspot.de</span>
</a>
<div class="pinHolder">
<a href="/pin/574701602429560539/" class="pinImageWrapper draggable" data-element-type="35" style="background: #9a7774;">
<div class="pinDomain">djdodo-kreativ.blogspot.de</div>
<div class="fadeContainer">
<div class="pinImageDim">
<div class="dimOverlay"></div>
<div class="dimGradient"></div>
</div>
<div class="Image Module pinUiImage" style="width: 236px">
<div class="heightContainer" style="padding-bottom: 62.2881356%">
<img src="https://s-media-cache-ak0.pinimg.com/236x/87/31/c5/8731c53e1a154996439fef26118e9a22.jpg" class="pinImg fullBleed loaded fade" onload="P.lazy.onImageLoad(this)" alt="Tasche JohnBoy by Elbmarie (freebook)">
</div>
</div>
</div>
</a>
</div>
</div>
<div class="pinMetaWrapper">
<div class="pinMeta ">
<p class="pinDescription">
Tasche JohnBoy by Elbmarie (freebook)
</p><div class="Module SocialIconsCounts">
<div class="pinSocialMeta">
<a class="socialItem" href="/pin/574701602429560539/repins/" data-element-type="174">
<em class="repinIconSmall"></em>
<em class="socialMetaCount repinCountSmall">
1
</em>
</a>
</div>
</div>
</div>
</div>
<div class="pinCredits">
<div class="pinCreditWrapper" data-element-type="282">
<button class="Button DropdownButton Module borderless hidePinInfo" data-element-type="284" type="button">
<em></em>
<span class="accessibilityText">Mehr dazu</span></button>
<div class="creditItem ">
<a href="/miriamhaehnel/n%C3%A4hen/">
<div class="Image Module creditImg unknownImage">
<div class="heightContainer">
<img src="https://s-media-cache-ak0.pinimg.com/upload/574701671137981071_board_thumbnail_2016-02-19-08-16-32_44630_60.jpg" data-load-state="pending" alt="Nähen" data-src="https://s-media-cache-ak0.pinimg.com/upload/574701671137981071_board_thumbnail_2016-02-19-08-16-32_44630_60.jpg">
</div>
</div>
<div class="creditName">Für dich ausgewählt</div>
<div class="creditTitle">
Nähen
</div>
</a>
</div>
</div>
</div>
</div>
</div>
Weblinks
- Robin Rendle: BEM 101
- Maxim Shirshin: Scaling down the BEM methology for small projects
- Varvara Stepanova: A new front-end methology: BEM
Einzelnachweise
- ↑ History / Methodology / BEM. Block, Element, Modifier / BEM. In: en.bem.info. Abgerufen am 18. Februar 2016.
- ↑ BEM: Key concepts / Methodology / BEM. Block, Element, Modifier / BEM. In: en.bem.info. Abgerufen am 18. Februar 2016.
- ↑ Naming convention / Methodology / BEM. Block, Element, Modifier / BEM. In: en.bem.info. Abgerufen am 18. Februar 2016.
- ↑ Inuit.css