OOCSS / BEM / SMACSS-Architektur

8

Ich habe diesen Artikel durchgearbeitet , um meinen Front-End-Code zu organisieren. Es verweist auf Artikel zu BEM / SMACSS, die wiederum auf andere Artikel verweisen.

Ich versuche wirklich zu verstehen, was die besten Praktiken sind ... Ich habe ein paar Tage Zeit, um diesen "Standard" festzulegen, und muss dann ein Projekt mit hoher Priorität / hoher Sichtbarkeit / begrenzter Zeitachse durchbrennen. Daher möchte ich sicherstellen, dass ich mit einer Grundlage beginne, die sich wie meine App skalieren lässt.

Bei einer Komponente mit dem Namen segment... erstelle ich Seiten mit ~ 10 segmentspro Seite. Jeder segmentteilt die gleiche Basisklasse. Bestimmte segmentshaben jedoch Modifikatoren (verschiedene Hintergrundfarben). Ferner haben Elemente in jedem Block (im BEM-Ansatz) auch Modifikatoren. Um dies zu demonstrieren, ist hier eine einfache Implementierung (mit nur einem einzigen Element arrow, während meine vollständige Site jeweils 4-5 Elemente enthält segment):

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow--orange {
    @extend .segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--white {
    @extend .segment__arrow;
    background-image: url('/images/arrow_white.png');
}

Das ist also der Einzelklassenansatz:

<div class="segment__arrow--white"> ... </div>

Alternativ könnte ich mich für den Mehrklassenansatz entscheiden:

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow--orange {
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--white {
    background-image: url('/images/arrow_white.png');
}

Wo mein Markup wäre:

<div class="segment__arrow segment__arrow--white"> ... </div>

Drittens könnte ich tun:

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow.orange {
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow.white {
    background-image: url('/images/arrow_white.png');
}

Und dann wäre meine Klasse def

<div class="segment__arrow orange"> ... </div>

Vielleicht sogar orangefarbener Namespace mit so etwas wie sa_orangelosen Selektoren.

Das Endergebnis, das ich suche, ist weniger Code / einfacher zu warten (was wahrscheinlich den Einzelklassenansatz (Option 1) ausschließt, wie in diesem großartigen Artikel über skalierbare Architektur beschrieben. Der Mehrklassenansatz (Option 2) führt zu viel Ausführlichkeit (besonders in meinem HTML), ist aber extrem explizit. Der dritte Ansatz verwendet einen Mehrklassenansatz, verwendet jedoch keine Modifikatoren mit Namespace (wie .segment__arrow), ist also etwas weniger ausführlich (aber auch weniger explizit und höher) Kollisionsgefahr).

Hat jemand mit realer Erfahrung mit diesem Zeug Feedback darüber, wie man das am besten angeht?

Scott Silvi
quelle
Das Entkoppeln der Modifikatoren von den Elementen widerspricht diesen Prinzipien, oder? .orangehat allein als Modifikator keine Bedeutung. Ich sehe kein großes Problem darin, .segment__arrow--orangezusammen mit Ihrem Multiklassen-Ansatz zu verwenden. Natürlich kann Ihr HTML-Code in größeren Projekten etwas außer Kontrolle geraten (viele Klassen).
Kleinfreund
Weg in den Urlaub. Danke für die Antwort. Ja, deshalb habe ich mich für die dritte Option entschieden. Sie haben Recht, es widerspricht diesen Prinzipien, aber wenn ein Projekt skaliert, stelle ich mir eine Klasse vor = "segment__arrow segment__arrow - orange segment__arrow - is-sichtbares segment__arrow - etwas anderes" ... und das nur fängt an, ein bisschen Code für mich zu stinken ...
Scott Silvi
Wahr. Man sollte diesen ganzen BEM-Bus nicht zu weit fahren. Nicht alles muss BEMifiziert werden.
Kleinfreund

Antworten:

8

Seit langer Zeit verwende und empfehle ich den expliziten Mehrklassenansatz (das zweite Beispiel), da er der universellste, wartbarste und kohärenteste ist. Hier werde ich versuchen, diese Behauptung zu unterstützen.

Einzelklasse

Dieser Ansatz hat ein großes Problem, wenn es zwei oder mehr Kategorien von Modifikatoren gibt. Zum Beispiel eine Schaltfläche mit den Modifikatoren klein , groß , groß für Größe und Primär , Erfolg , Informationen und Warnung für "Farbe". Zusätzlich zu den üblichen 7 (= 3 + 4) Klassen müssen auch alle 12 Kombinationen erstellt werden:

.button--small--primary
.button--small--success
.button--small--info

Bisher etwas unpraktisch, aber keine Katastrophe.

Ein weiteres Ärgernis - ein größeres - ist, dass die richtige Reihenfolge "Größe zuerst, Farbe zweitens" verwendet und daher gespeichert (und gut dokumentiert) werden muss.

Das Schlimmste ist, wenn JavaScript beteiligt ist. Möchten Sie die "Farbe" dieser Schaltfläche ändern, aber die aktuelle Größe beibehalten? Analysieren Sie das Klassenattribut! Möchten Sie nur den Erfolgsmodifikator entfernen ? Analysieren Sie das Klassenattribut!

Zählen Sie, dass z. B. Bootstrap 7 "Farben", 4 Größen und aktive / deaktivierte Zustände hat; für die 119 (= 13 + [7 * 4 + 7 * 2 + 4 * 2] + 7 * 4 * 2) Klassen deklariert werden müssen, um den Einzelklassenansatz beizubehalten! Das ist das große Problem.

Explizite Mehrfachklassen würden nur 13 Klassen erfordern (eine für jeden Modifikator). Die Reihenfolge wäre willkürlich. Schließlich würde das Hinzufügen, Entfernen und Ändern einer Datei unter Beibehaltung anderer in jQuery folgendermaßen aussehen:

$('#login-button').removeClass('button--primary').addClass('button--success');

Verknüpfung für mehrere Klassen

Erstens besteht, wie Sie bereits erwähnt haben, die Gefahr von Kollisionen - eine schlechte Sache für sich.

Zweitens bedeutet dies auch, dass das .segment__arrow.orangeeine höhere Spezifität hat und nicht mit einem einzelnen Klassenselektor überschrieben werden kann. Dies ist häufig der Fall, wenn ein Element nicht nur eine große Schaltfläche, sondern auch eine Anmeldeschaltfläche ist . Sein Code würde so aussehen:

<a href="#" class="button large primary login__button">Log in</a>

Möglicherweise möchten Sie eine größere linke und rechte Polsterung auf der Anmeldeschaltfläche haben, aber die Höhe der großen beibehalten . Dies würde zu immer spezifischeren Selektoren führen, die uns zur Hölle der Spezifität bringen würden - ein Ort, vor dem OOCSS uns retten sollte.

Es ist offensichtlich, dass dies im expliziten Mehrklassenansatz nicht passieren würde .

Explizite Mehrklassen

Das einzige Problem (soweit mir bekannt ist) ist, dass das Markup einige manchmal ziemlich lange Klassen enthält. Ich gebe das zu.

Lassen Sie mich bemerken, dass dies nur eine Geschmackssache des Entwicklers ist, da es einen vernachlässigbaren (bis gar keinen) Effekt auf die Leistung hat. Dafür sorgt die Standardkomprimierung.

Davon abgesehen hilft die Verwendung einer guten IDE beim Schreiben (ja, ich weiß, es wird immer noch ein bisschen lächerlich aussehen).

Einerseits würde ich sagen, wenn man so lange Klassen sieht, muss man mehr über die Struktur nachdenken. zB ob es nicht besser wäre, eine neue (wiederverwendbare) Komponente einzuführen, anstatt sie in etwas anderes zu verschachteln.

Robin Pokorny
quelle
0

Ich diskutiere gerade mit meinen Teamkollegen über diese Einzel- / Mehrklassenprobleme

Hier sind einige meiner persönlichen Ansichten, die auf bewährten Verfahren basieren

Beste Übung

  • HTML deklariert Elemente
  • CSS-Steuerelemente rendern

Einzelne Klasse folgt immer der Best Practice

mit zusätzlichen Wartungsvorteilen, mit guten Namen kann es erreichen

  • Stiländerung erfordert kein HTML-Update * (siehe Demo)

  • Sperrstil in HTML (Sie haben den richtigen Stil oder nichts)

Demo

@mixin segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}

.segment__arrow--type1 {
    @include segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--type2 {
    @include segment__arrow;
    background-image: url('/images/arrow_white.png');
}

@mixin include ist besser als @extend

  1. Kontrolle über die Codereihenfolge in der endgültigen CSS
  2. kleinere Größe in der gzip-Version

und genau wie @extend kann es wiederverwendet werden und mehrere Klassen in HTML ersetzen

Mit @mixin erhalten Sie zusätzliche Flexibilität

@mixin segment__arrow--type1 {
    @include segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
@mixin segment__arrow--type2 {
    @include segment__arrow;
    background-image: url('/images/arrow_white.png');
}
.segment__margic-arrow {
    @include screen(mobile) {
       @include segment__arrow--type1
    }
    @include screen(desktop) {
       @include segment__arrow--type2
    }
}

Für Javascript verwenden

staatliche Regeln von smacss

Nachteil der Einzelklasse

der einzige:

Größere CSS-Dateien, ABER Sie können CSS immer einfach basierend auf Website-Abschnitten oder Komponenten auf der Seite optimieren

Liang
quelle