Das Problem mit der Vorverarbeitung von CSS-Custom Properties

Avatar of Chris Coyier
Chris Coyier on

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

CSS hat jetzt Custom Properties. Wir haben in letzter Zeit viel darüber geschrieben. Die Browserunterstützung ist gut, aber natürlich haben alte, nicht-evergreen Browser wie der Internet Explorer sie nicht und werden sie nie haben. Ich kann die Anziehungskraft erkennen, mit "zukünftigem CSS" zu authoring und es von einem Präprozessor für ältere Browser zurückportieren zu lassen. Babel für CSS! Warum nicht?!

Das macht mir jedoch Sorgen – weil nur *einige* Anwendungsfälle von Custom Properties vorverarbeitet werden können. Es gibt viele Situationen, in denen das, was Sie mit einer Custom Property tun, einfach *nicht* vorverarbeitet werden kann. Wenn Sie es also tun, bringen Sie sich in eine ziemlich seltsame Situation.

Wenn Sie sich in einer Situation befinden, in der Sie sie vorverarbeiten *können* und das gewünschte Ergebnis erzielen, hätten Sie wahrscheinlich einfach Präprozessor-Variablen verwenden sollen.

Präprozessoren können die DOM-Struktur nicht verstehen

Erst zur "Laufzeit", wenn ein vollständiges DOM aufgebaut ist, werden die CSS angewendet. Ganz zu schweigen von dem wahrscheinlichen Szenario, dass jede gegebene CSS-Datei eine von vielen ist, die die Seite beeinflussen.

postcss-custom-properties ist vielleicht der beliebteste Custom Property-Präprozessor (er ist in cssnext gebündelt) und erlaubt es Ihnen nur, Variablen im :root zu setzen, wie

:root {
  --backgroundColor: white;
}
.header {
   background-color: var(--backgroundColor);
}

Aber vielleicht ist eine der nützlichsten Eigenschaften von CSS Custom Properties, dass sie in der Kaskade verwendet werden können. Dies ist ein konstruiertes Beispiel, aber Sie werden den Punkt verstehen

:root {
  --backgroundColor: white;
}
.header {
   background-color: var(--backgroundColor);
}
.header.is-about-page {
  --backgroundColor: yellow;
}

Mit postcss-custom-properties wird die Root-Variable verarbeitet, aber nicht die Zustandsvariation, was zu ziemlich nutzlosem CSS führt

.header {
   background-color: white;
}
.header.is-about-page {
  --backgroundColor: yellow;
}

Sie sind sich dessen bewusst

Die Transformation *ist nicht vollständig* und *kann nicht sein* (dynamische *kaskadierende* Variablen basierend auf Custom Properties sind vom DOM-Baum abhängig). Sie zielt derzeit nur darauf ab, eine zukunftssichere Methode zur Verwendung einer *begrenzten Teilmenge (auf den :root-Selektor)* der Funktionen nativer CSS Custom Properties zu bieten. *Da wir das DOM im Kontext dieses Plugins nicht kennen, können wir keine sichere Ausgabe erzeugen*.

Sie können interessante Diskussionen über all das lesen, wie diese hier.

Es gibt einen weiteren Custom Properties-Prozessor namens postcss-css-variables, der versucht, mehr zu tun. Zum Beispiel

.header {
   background-color: var(--backgroundColor, white);
}
.header:hover {
  --backgroundColor: orange;
}
.header.is-about-page {
  --backgroundColor: yellow;
}

Was ausgibt

.header {
   background-color: white;
}
.header:hover {
   background-color: orange;
}

Es könnte den Hover richtig behandeln, aber hat sich immer noch am genannten Selektor aufgegeben.

Beide Plugins stimmen überein: *Es gibt einfach keine Möglichkeit, das, was CSS Custom Properties können, perfekt in einem CSS-Präprozessor zu replizieren.*

Wenn Sie es also tun, müssen Sie sich entweder bei der Verwendung einschränken oder falsche Ergebnisse erzielen.

Sie verlieren die Möglichkeit, sie mit JavaScript zu ändern

Neben der Kaskade ist das andere Killer-Feature von CSS Custom Properties die Möglichkeit, sie mit JavaScript zu ändern. Anstatt also mit JavaScript die X Dinge abzufragen, die Sie ändern müssen, und sie alle einzeln zu ändern, können Sie einfach eine Custom Property ändern, die sich dann wie erwartet durchsetzt.

Indem Sie CSS Custom Properties wegvorverarbeiten, existieren sie nicht im verarbeiteten CSS, und dadurch verlieren Sie diese Möglichkeit.

Wann schaltet man es ab?

Vielleicht denken Sie über diese Vorverarbeitung nur als Übergangslösung nach. Irgendwann werden Sie sie abschalten und dann Custom Properties nativ ausliefern. Sie müssen einige Arbeit leisten, um sicherzustellen, dass

  1. Die native Verarbeitung ist genau wie die Präprozessor-Verarbeitung
  2. Kein anderer Teil des Vorverarbeitungsprozesses wird dadurch verwirrt
  3. Ihre Fallback-Situation ist solide, wenn Sie in Browsern, die sie nicht unterstützen, immer noch eine funktionierende Erfahrung benötigen

🙃

Entschuldigung, ich weiß, dass es sich anfühlt, als würde ich hier jemandes Sache schlechtmachen. Tatsächlich halte ich solche Erkundungen für supercool und lohnenswert, sie durchzuführen und zu teilen. Die Leute, die sie machen, sind unbestreitbar intelligenter als ich.

Manche Leute sind begeistert davon. Mike Street

Ich arbeite für eine Agentur, bei der die Cross-Browser-Unterstützung ein Muss ist, und das schließt leider auch IE11 ein. Obwohl wir CSS-Variablen noch nicht ganz in der Produktion einsetzen können, bieten sie viele Vorteile für die Entwicklung und die Nachbearbeitung zu ihren ursprünglichen Eigenschaften.

Unser Gulp-Prozess beinhaltet postcss-css-variables, das jede CSS-Variable in Ihren Stylesheets in die von Ihnen festgelegten Werte umwandelt. Ähnlich wie SCSS-Variablen (auf die gleiche Weise, wie sie verarbeitet werden), aber es ermöglicht Ihnen, kleinere SCSS zu schreiben und, wenn die Zeit reif ist, die Verarbeitung zu entfernen und Ihre Stylesheets mit bereits vorhandenen Custom Properties bereitzustellen.

Ich finde einfach, dass es sich lohnt, ein wenig Vorsicht walten zu lassen. Auf der Website von cssnext gibt es ein großes Banner mit der Aufschrift "Use tomorrow’s CSS syntax, today." und ich befürchte, dass diese Art von Marketing etwas so Einfaches verkauft, das leider kompliziert und nuanciert ist.

Wenn Sie Custom Properties vorverarbeiten, können Sie genauso gut tatsächliche Präprozessor-Variablen verwenden

Das erscheint mir jedenfalls eine kluge Entscheidung zu sein.

Sass, Less und Stylus haben alle Variablen, die gut funktionieren. Sie haben sogar ein gewisses Maß an Geltungsbereich, wenn auch nicht so mächtig wie die echte Kaskade.

Wenn Sie auf das PostCSS-Ding stehen, gibt es Plugins, die Variablen zulassen, die eine Syntax verwenden, die die native CSS-Syntax nicht überlappt.

Mike Street hatte einen ziemlich coolen Anwendungsfall, bei dem er die Richtung eines Gradienten an einer Media Query umkehrte, indem er eine kleine Änderung an einer CSS Custom Property vornahm (was eine super nützliche Sache ist, die sie tun können).

div {
  --direction: to bottom;
  
  background: linear-gradient( 
    var(--direction), 
    rgba(0, 0, 0, 1) 0, 
    rgba(0, 0, 0, 0.1) 100%);
  
  @media (max-width: 1000px) {
    --direction: to right;
  }
}

Nur postcss-css-variables (glaube ich) versucht, dies zu verarbeiten. Es ist schön prägnant, aber es ist möglich, fast das gleiche schöne Abstraktionsniveau mit SCSS zu erreichen.

@mixin specificGradient($direction) {
  background: linear-gradient(
    $direction, 
    rgba(0, 0, 0, 1) 0, 
    rgba(0, 0, 0, 0.1) 100%
  );
}

div {
  @include specificGradient(to bottom);
  @media (max-width: 1000px) {
    @include specificGradient(to right);
  }
}

Verwenden Sie beide / behandeln Sie Fallbacks jetzt

Sie können definitiv jeden Präprozessor *und* CSS Custom Properties verwenden.

Sie können sogar einige Dinge, wie Ihre $brandColor oder etwas Ähnliches, als Präprozessor-Variable belassen. Nutzen Sie dann gleichzeitig CSS Custom Properties für Dinge, bei denen Sie sich vorstellen können, dass sie eines Tages dynamisch sein werden. Sie können sogar sofort Fallbacks behandeln, sodass Sie sich mit der Cross-Browser-Unterstützung auseinandersetzen, anstatt dies als etwas zu betrachten, das Sie wegvorverarbeiten.

$brandColor: #f06d06;

html {
  background: $brandColor;
  
  --base-font-size: 100%;
  font-size: 100%;
  font-size: var(--base-font-size);
}