Die beste Einführung in BEM gibt es von Harry Roberts
BEM – bedeutet Block, Element, Modifier – ist eine Front-End-Namensgebungsmethodik, die sich die Jungs von Yandex ausgedacht haben. Es ist eine intelligente Methode, Ihre CSS-Klassen zu benennen, um ihnen mehr Transparenz und Bedeutung für andere Entwickler zu verleihen. Sie sind weitaus strenger und informativer, was die BEM-Namenskonvention ideal für Entwicklungsteams bei größeren Projekten macht, die eine Weile dauern könnten.
Seit Sass 3.3 können wir Dinge so schreiben:
.block {
/* CSS declarations for `.block` */
&__element {
/* CSS declarations for `.block__element` */
}
&--modifier {
/* CSS declarations for `.block--modifier` */
&__element {
/* CSS declarations for `.block--modifier__element` */
}
}
}
Solange CSS-Regeln kurz sind und der Basisselektor einfach ist, bleibt die Lesbarkeit in Ordnung. Aber wenn die Dinge komplexer werden, macht diese Syntax es schwer zu erkennen, was vor sich geht. Aus diesem Grund könnten wir versucht sein, zwei Wrapper-Mixins für unsere BEM-Syntax zu erstellen.
/// Block Element
/// @access public
/// @param {String} $element - Element's name
@mixin element($element) {
&__#{$element} {
@content;
}
}
/// Block Modifier
/// @access public
/// @param {String} $modifier - Modifier's name
@mixin modifier($modifier) {
&--#{$modifier} {
@content;
}
}
Umschreiben unseres vorherigen Beispiels mit unseren brandneuen Mixins
.block {
/* CSS declarations for `.block` */
@include element('element') {
/* CSS declarations for `.block__element` */
}
@include modifier('modifier') {
/* CSS declarations for `.block--modifier` */
@include element('element') {
/* CSS declarations for `.block--modifier__element` */
}
}
}
Beachten Sie, dass Anführungszeichen um Zeichenfolgen optional sind, wir fügen sie nur zur zusätzlichen Lesbarkeit hinzu.
Wenn Sie nun der Meinung sind, dass element und modifier zu lang zum Tippen sind, können Sie zwei kürzere Aliase erstellen, wie folgt:
/// @alias element
@mixin e($element) {
@include element($element) {
@content;
}
}
/// @alias modifier
@mixin m($modifier) {
@include modifier($modifier) {
@content;
}
}
Verwendung von Aliassen
.block {
/* CSS declarations for `.block` */
@include e('element') {
/* CSS declarations for `.block__element` */
}
@include m('modifier') {
/* CSS declarations for `.block--modifier` */
@include e('element') {
/* CSS declarations for `.block--modifier__element` */
}
}
}
Würde die zweite &__element nicht .block–modifier__element ergeben?
Korrigiert, vielen Dank!
Falsch. Tuto. Die 1. Antwort ist richtig. Modifier ist immer an letzter Stelle.
Und die Verwendung von Mixins bringt unnötige Komplexität mit sich.
Ich verstehe nicht, warum wir Sass-Code verkomplizieren müssen. Das lässt Anfänger davonlaufen. Der Standardweg ist kürzer und sehr einfach zu verstehen…
.block {
color: black;
&__element { border: 1px solid; }
}
&__elementmag für Sie einfacher zu verstehen sein, aber für Anfänger wie Sie sagten, mag eine solche Syntax unfreundlich sein. Lassen Sie die Leute ihre eigenen Werkzeuge wählen.stimme Ihnen vollkommen zu, die Einführung von Mixins macht es weniger lesbar
100% Zustimmung mit Luis. Das löst kein Problem, im Gegenteil, es verkompliziert die Dinge. Die Zeit, die ein „Anfänger“ bräuchte, um zu lernen, was dieser Mixin tut, könnte er schon herausgefunden haben, was
&__elementtut. Ich meine, sie müssen trotzdem die Klasse zum HTML hinzufügen, oder?!?Ich stimme Luis nicht zu. Ich glaube, dass Anfänger lernen sollten, wie man &__ benutzt, bevor sie diese Mixins lernen, genau wie sie CSS lernen sollten, bevor sie SASS/LESS lernen.
Ich denke, dass diese Mixins nützlich sind, wenn man nicht mehr neu ist und seinen Code semantischer gestalten und sinnvoller machen möchte – und seinem Gehirn ermöglichen will, schneller zu verstehen, was jede Zeile mit einfachem Englisch bedeutet.
Außerdem sind diese Mixins bei Verwendung der SASS-Syntax sehr kurz und schnell zu verwenden
Das würde für mich übermäßig komplexer erscheinen, als für einen „Anfänger“ einen Ampersand für das Verschachteln von Selektoren zu deklarieren. Wie soll ein „Anfänger“ wissen, wie man Mixins und Includes schreibt, anstatt einfach herauszufinden, dass er einen Ampersand für das Verschachteln von Selektoren übergeben kann?
@include m('modifier') { ... }ist immer noch unnötiger und aufwendigerer Schnickschnack, als einfach eine einfache Deklaration zu schreiben. Dies ermutigt, wenn überhaupt, Leute oder „Anfänger“, kostspielige Manöver zu verwenden, um alles zu verschachteln. So ziemlich das Gegenteil des Artikels, den Sie hier gesehen haben.Könnte das als tatsächlich „nützlich“ übersehen, aber ich bin offen für Meinungen! :-)
Prost.
… und eine nun *noch* unerträglichere Codebasis, was mich zu der Frage bringt, wie nützlich Kommentare beim Verschachteln von Selektoren sind – wiederum im Gegensatz zum oben genannten Artikelbezug. Hmm. Ich muss überzeugt werden! Haha.
Hallo Leute, habt ihr bemerkt, dass sie jetzt einen einzelnen Unterstrich „_“ anstelle von doppelten Bindestrichen „–“ für Modifier verwenden?
http://en.bem.info/method/definitions/
Eigentlich bin ich dem nicht abgeneigt, auch wenn ich es etwas schwerer zu lesen finde, aber wenn einer von euch weiß, warum sie diese Wahl getroffen haben, würde ich es gerne wissen.
Ich habe versucht, das zu tun, aber ich habe diese Fehlermeldung erhalten
Ungültiges CSS nach „... element(input)“: erwartet „}“, aber Komma erhaltenIch benutze das, um mein Problem zu lösen.
Könnte der Mixin mehrere Parameter akzeptieren, um mehr als ein Element zu stylen?
Ich habe meine eigene Art, mein SCSS zu strukturieren, und bisher finden andere, mit denen ich arbeite, es einfach zu verstehen/erweitern/pflegen… aber ich schaue mir Dinge wie OOCSS, SMACSS, BEM usw. an.
Es scheint mir, dass dieser Ansatz in einer Situation wie dieser zusammenbricht…
(Annahme von Jade für Markup)
Nehmen wir an, die Klasse
--disabledwird vonng-classangewendet. Wenn ich möchte, dass meine Ikone/mein Text unterschiedliche Eigenschaften hat, basierend darauf, dass der Button--disabledist, müsste ich Folgendes tun…Scheint eher eine lästige Angelegenheit zu sein, oder denke ich falsch über den Anwendungsfall?
Gute Frage. Ich löse das im Allgemeinen mit einem Attributselektor wie folgt:
Leider funktioniert das nicht für HTML mit mehreren Klassen (wie
.btn.primary), aber das vermeide ich generell sowieso, indem ich eine Klasse verwende, um das Ding darzustellen, und Sass, um die Präsentationsschichten zu bestimmen.Nach BEM-Konventionen müssen Sie den Block-Modifier nicht innerhalb des Elements angeben. Also wäre
.button--disabled__iconkein gültiger BEM-Code.Stattdessen sollte Ihre Verschachtelung so aussehen:
Und damit das funktioniert, sollte die Struktur des kompilierten CSS so aussehen:
Diese Ausgabe kann erreicht werden, indem die „unnötigen“ Mixins aktualisiert und auf diesen Anwendungsfall aufmerksam gemacht werden. Jetzt würden die Mixins tatsächlich nützlich werden.
Mit Sass 3.4 können Zeichenfolgenfunktionen auf dem
&Selektor ausgeführt werden.Das ist sehr aufregend, da wir innerhalb der
modifier()undelementMixins1. eine Funktion erstellen können, die prüft, ob der Elternselektor bereits einen Modifier hat
2. die Klassennamen entsprechend berechnen können
Um es zu detaillieren: Wenn wir diese Art von Eingabe haben
Der Mixin
element('icon')prüft, ob der Elternselektor (&) bereits einen Modifier enthält, und gibt.block--modifier .block__elementaus, andernfalls nurblock__element.Ich liebe die Verwendung dieser Mixins zur Generierung von BEM-Code, aber
Wie würde ich den
:afterdes letzten Links loswerden?Ich kann nicht
Die Idee hinter der BEM-Methodik ist es, jegliche Logik in kleine Stücke zu zerlegen, damit alles viel wartungsfreundlicher wird. Ich würde annehmen, dass die „Breadcrumb“ in Ihrem Code ein Block ist, während item und link Elemente sind.
Tatsächlich sollte das Verschachteln eines Elements innerhalb eines Elements nicht funktionieren (weil es die grundlegenden BEM-Regeln bricht). Aber Sie könnten es funktionsfähig machen, indem Sie das Item in einen Block verwandeln und daraus ein Block-Element-Modifier-Objekt erstellen.
Sie würden also die aktuelle Struktur bis zum Item beibehalten und dann darin einen Breadcrumb-Item-Block erstellen, wo Sie Ihre erweiterte Linklogik definieren.
Dann könnten Sie im HTML diesen neuen BEM-Block verwenden, um die Logik des ursprünglichen Elements zu ergänzen.
Wie ist das hilfreich? Sie haben jetzt die Logik in ein kleineres BEM-Modul aufgeteilt und auch die Verantwortlichkeiten aufgeteilt.
Das Element-Element
.breadcrumb__itemkümmert sich um den Float, der Block.breadcrumb-itemkümmert sich um die Link- und Trennerlogik.Wenn Sie dem Link mehr Komplexität hinzufügen, wie z. B. ein Icon oder einen hervorgehobenen Modifier, werden Sie dies viel einfacher tun, indem Sie nur diese kleine Struktur ändern.
Ich glaube nicht, dass die
funktionieren wird – der
eMixin wird versuchen, seinen__linkSelektor über den&:not(:last-child)zu legen, was zu etwas wie diesem führen würde:siehe diesen Gist. Es sei denn, mein
eMixin ist falsch.Eigentlich habe ich gerade einen Workaround gefunden – siehe diesen Gist. Der Schlüssel war, den
&Elternselektor beimeMixin zu nehmen und ihn nach Pseudo-Selektoren zu durchsuchen. Wenn sie existierten, schneiden Sie sie heraus.Das stimmt Danny, der Element-Mixin sollte etwas komplexer sein als der im Beispiel bereitgestellte. Es reicht nicht aus, nur zu prüfen, ob der Selektor einen Pseudo-Selektor enthält, Sie müssen auch berücksichtigen, ob die Eltern einen Modifier enthalten oder nicht, um Klassen wie
.block--modifier .elementanstelle von.block--modifier__elementzu generieren – was kein gültiges BEM ist.Ihr Gist sollte einwandfrei funktionieren.
Ich verwende eine Reihe von benutzerdefinierten Mixins, die mehr Anwendungsfälle abdecken. Vielleicht schreibe ich eine kurze Einführung und poste den Link hier, wenn Sie denken, dass es hilfreich sein könnte.
Guter Punkt! Ja, ich würde gerne sehen, was Sie sich einfallen lassen haben, um vom Elternselektor zum Block/Element zu gelangen. Ich habe dieses Problem bei einer vielversprechenden Bibliothek eröffnet. Es wäre schön, eine gemeinschaftsgesteuerte eigenständige Bibliothek von BEM-bezogenen Mixins zu sehen.
Hier ist ein Blogbeitrag, der einige weitere Anwendungsfälle und eine Reihe fortschrittlicher Mixins beschreibt, die helfen, modulare und wartungsfreundliche BEM-Strukturen zu erstellen.
https://m.alphasights.com/how-we-use-bem-to-modularise-our-css-82a0c39463b0#.o4tc7cevq
sderhbr rfvjui o
Ich finde es immer noch schade, dass der Starts-mit (Wildcard) Selektor nicht mit verschachtelten Ampersands funktioniert (und ja, ich verstehe die Logik, warum das nicht funktioniert, sage es nur). Dies würde die Notwendigkeit eines doppelten Blockselektors eliminieren. Anstatt also
<div class="tile tile--disabled">zu verwenden, wäre es möglich, einfach<div class="tile--disabled">zu schreiben und trotzdem den Tile und eine deaktivierte Version im selben 1-Level-tiefen Verschachtelungsblock zu stylen. Dies würde zu einem Verlust von 1 Level an Spezifität in SCSS führen (was sehr nützlich sein könnte).Das ist in der Tat eine interessante Idee, man könnte einen Mixin erstellen, der den Wildcard-Match-Klassennamen empfangen und den Wildcard + Modifier zurückgeben könnte (habe nicht viel darüber nachgedacht, aber es ist machbar, da bin ich sicher).
Eine andere Sache, die Sie tun könnten, wenn Sie die Standard-BEM-Konvention wirklich hassen, ist, die Blockeigenschaften in einem Platzhalter zu haben und diese dann auf allen Modifikatoren zu erweitern.
Es könnte so aussehen:
Dies ist eine Möglichkeit, dies zu tun, ohne die generierten CSS-Eigenschaften duplizieren zu müssen.
Aber der ganze Sinn des Modifiers ist es, Stile eines Elements oder eines Blocks zu erweitern. Ich finde es wirklich nützlich,
class="aufzurufen.block__title
block__title--highlighted
block__title--with-icon
aber am Ende ist es nur eine Frage der Konventionen.
Sehr schön. Ihr Ansatz hat mich dazu inspiriert, ein Lesbarkeitsproblem anzugehen, das ich immer mit Sass + BEM hatte: das Kombinieren mehrerer Modifikatoren.
Ich habe Ihren Mixin erweitert, um mehrere Parameter zu akzeptieren:
Das macht Sass-Code wie diesen…
…generiert das folgende CSS:
Wenn Sie interessiert sind, habe ich die Mixin-Idee seit diesem Beitrag etwas erweitert
https://github.com/alphasights/paint/blob/develop/styles/tools/_bem.scss
Es gibt auch einen Test, der einige mögliche Anwendungsfälle zeigt
https://github.com/alphasights/paint/blob/develop/test/tools/_bem.scss
Ich persönlich konnte bisher keinen starken Grund finden, Modifier zu kombinieren, zum Beispiel würde ich in Ihrem Fall den Modifier einfach
warning-invertednennen, aber es sieht definitiv nach einer guten Lösung aus.Lassen Sie mich wissen, ob Sie es hilfreich finden :)
Würden die längeren Klassennamen die HTML-Struktur nicht aufblähen?