Über Sass-Konflikte und relativ neue CSS-Funktionen

In jüngerer Zeit gab es in CSS viele interessante Funktionen, wie z. B. CSS-Variablen und neue Funktionen . Während all dies Webdesignern das Leben erheblich erleichtern kann, können diese Funktionen auf unerwartete Weise mit CSS-Präprozessoren wie Sass interagieren. Die Autorin des Materials, dessen Übersetzung wir heute veröffentlichen, wird darüber sprechen, mit welchen Problemen sie konfrontiert war, wie sie damit umgegangen ist und warum sie glaubt, dass Sass heutzutage immer noch unmöglich ist.











Fehler



Wenn Sie mit CSS-Funktionen experimentieren min()und max()dann verschiedene Maßeinheiten verwenden, können Fehlermeldungen wie die folgenden auftreten : Incompatible units: vh and em.





Fehlermeldung bei Verwendung unterschiedlicher Einheiten in den Funktionen min () und max ()



Diese Meldung wird angezeigt, da Sass über eine eigene Funktion verfügtmin(). Die CSS-Funktion wird dahermin()ignoriert. Darüber hinaus kann Sass keine Berechnungen mit Einheiten durchführen, zwischen denen keine eindeutige Beziehung besteht.



Zum Beispiel ist die Beziehung der Einheitencmgutindefiniert, sodass Sass das Ergebnis einer Funktion finden kannmin(20in, 50cm)und keinen Fehler auslöst, wenn Sie so etwas in Ihrem Code verwenden.



Das gleiche passiert mit anderen Maßeinheiten. Zum Beispiel werden alle Eckelemente miteinander verbunden:1turn,1radoder1gradwerden immer in die gleichen Werte umgerechnet, die in Einheiten ausgedrückt werden deg. Gleiches gilt beispielsweise für den Fall, dass 1ses immer gleich ist 1000ms. 1kHzimmer gleich 1000Hz, 1dppximmer gleich 96dpi, 1inimmer gleich 96px. Aus diesem Grund kann Sass die in diesen Einheiten ausgedrückten Werte ineinander umwandeln und in Berechnungen mischen, die in verschiedenen Funktionen verwendet werden, z. B. in seiner eigenen Funktion min().



Aber alles geht schief, wenn es keine klare Beziehung zwischen den Maßeinheiten gibt (wie zum Beispiel oben y emund vh).



Dies geschieht nicht nur bei Verwendung von Werten, die in verschiedenen Maßeinheiten ausgedrückt werden. Versuch, eine Funktion calc()intern zu verwendenmin()führt auch zu einem Fehler. Wenn Sie versuchen min(), etwas wie zu setzen calc(20em + 7px), wird der folgende Fehler angezeigt : calc(20em + 7px) is not a number for min.





Fehlermeldung tritt auf, wenn Sie versuchen , Calc () zu verwenden , in min ()



Ein weiteres Problem in einer Situation trittwenn versuchtden CSS-Variable oder die Ausgabe von CSS-mathematischen Funktionen (wiecalc(),min(),max()) in CSS-ähnlichen Filterninvert().



Hier ist die Fehlermeldung, die unter ähnlichen Umständen angezeigt wird:$color: 'var(--p, 0.85) is not a color for invert





Die Verwendung von var () im Filter: invert () führt zu einem Fehler.



Dasselbe passiert mitgrayscale():$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale.





Die CALC () im Filter: Graustufen () führt zu einem Fehler



Designfilter: opacity()ist auch Gegenstand zu ähnlichen Fragen:$color: ‘var(--p, 0.8)‘ is not a color for opacity.





Mit var () im Filter: Opazität () führt zu einem Fehler



, aberandere Funktionen verwendetfilter, einschließlichsepia(),blur(),drop-shadow(),brightness(),contrast()undhue-rotate()mit den CSS-Variablen arbeitenist völlig normal!



Es stellte sich heraus, dass die Ursache für dieses Problem ähnlich ist wie die, die die Funktionenmin()undbetrifftmax(). Die Sass keine eingebauten Funktionensepia(),blur(),drop-shadow(),brightness(),contrast(),hue-rotate(). Aber es hat seine eigenen Funktionen Graustufen () , invertieren () und Deckkraft () . Das erste Argument für diese Funktionen ist der Wert$color. Der Fehler tritt aufgrund der Tatsache auf, dass Sass bei Verwendung problematischer Konstruktionen kein solches Argument findet.



Aus dem gleichen Grund treten Probleme bei der Verwendung von CSS-Variablen auf, die mindestens zwei hsl()oder hsla()-Werte darstellen.





Fehler bei der Verwendung von var () in Farbe: hsl ()



Andererseits ist ein Konstrukt ohne Verwendung von Sasscolor: hsl(9, var(--sl, 95%, 65%))vollkommen korrekt und funktioniert perfekt als CSS-Konstrukt.



Gleiches gilt für Funktionen wiergb()undrgba():





Fehler bei der Verwendung von var () in der Farbe: rgba ()



Wenn Sie Compass importieren und versuchen, eine CSS-Variable inlinear-gradient()oder zu verwendenradial-gradient(), tritt möglicherweise ein anderer Fehler auf. Gleichzeitig könnenconic-gradient()Sie aber problemlos Variablen verwenden (natürlich, wenn der Browser diese Funktion unterstützt).





Fehler bei der Verwendung von var () im Hintergrund: linear-gradient ()



Der Grund für das Problem liegt in der Tatsache, dass Compass einen eigenen linearen Gradienten () und eigeneradial-gradient()Funktionen hat, die Funktionconic-gradient()jedoch nie vorhanden war.



Im Allgemeinen ergeben sich all diese Probleme aus der Tatsache, dass Sass oder Compass ihre eigenen Funktionen haben, deren Namen mit denen in CSS identisch sind. Sowohl Sass als auch Compass glauben, wenn wir diese Funktionen erfüllen, dass wir ihre eigenen Implementierungen dieser Funktionen verwenden werden und nicht die Standardimplementierungen.



Hier ist ein Hinterhalt!



Lösung



Dieses Problem kann gelöst werden, indem Sie sich daran erinnern, dass bei Sass zwischen Groß- und Kleinschreibung unterschieden wird, bei CSS jedoch nicht.



Dies bedeutet, dass Sie so etwas schreiben können Min(20em, 50vh)und Sass seine eigene Funktion in diesem Konstrukt nicht erkennt min(). Es werden keine Fehler generiert. Dieses Konstrukt wird ein wohlgeformtes CSS sein, das genau wie erwartet funktioniert. In ähnlicher Weise zu bekommen mit anderen Funktionen von Problemen zu befreien, nicht standardisierte Art und Weise sein , mit ihren Namen zu schreiben: HSL(), HSLA(), RGB(), RGBA(), Invert().



Wenn es um Farbverläufe geht, verwende ich normalerweise diese Form: linear-Gradient()und radial-Gradient(). Ich mache das, weil diese Notation in der Nähe der in SVG verwendeten Namen liegtIn dieser Situation funktioniert jedoch jeder andere ähnliche Name, der mindestens einen Großbuchstaben enthält.



Warum all diese Komplikationen?



Fast jedes Mal, wenn ich etwas über Sass twittere, werde ich darüber belehrt, dass Sie Sass jetzt, da Sie über CSS-Variablen verfügen, nicht mehr verwenden müssen. Ich beschloss, darauf zu antworten und den Grund für meine Ablehnung dieser Idee zu erläutern.



Zunächst möchte ich feststellen, dass ich CSS-Variablen äußerst nützlich finde und sie in den letzten drei Jahren für eine Vielzahl von Aufgaben verwendet habe. Aber ich nehme an, Sie müssen sich daran erinnern, dass die Verwendung diese Auswirkungen auf die Leistung hat. Und die Suche nach einem Problem im Labyrinth der Anrufecalc()kann die unangenehmste Erfahrung sein. Standard-Browser-Entwicklertools sind noch nicht sehr gut darin. Ich versuche, mich nicht von der Verwendung von CSS-Variablen mitreißen zu lassen, um nicht in Situationen zu geraten, in denen sich ihre Nachteile mehr als ihre Vorteile zeigen.





Es ist nicht leicht zu verstehen, wie die Ergebnisse der Auswertung dieser calc () - Ausdrücke aussehen



werden. Wenn eine Variable als Konstante verwendet wird, ändert sie sich im Allgemeinen nicht von Element zu Element oder von Status zu Status (und in solchen Fällen sollten CSS-Variablen definitiv verwendet werden benötigt ), oder wenn die Variable die Menge an kompiliertem CSS nicht reduziert (um das durch Präfixe verursachte Wiederholungsproblem zu lösen ), verwende ich eine Sass-Variable.



Zweitens war das Verwalten von Variablen unter den Gründen, die ich für Sass verwende, immer ein eher untergeordneter Grund. Als ich in der zweiten Jahreshälfte 2012 anfing, Sass zu verwenden, habe ich es hauptsächlich für Loops gemacht. Für eine Funktion, die in CSS noch fehlt. Während ich einen Teil der Schleifenlogik in den HTML-Präprozessor verschoben habe (da dies die Menge des generierten Codes reduziert und die Notwendigkeit vermeidet, sowohl HTML als auch CSS zu ändern), verwende ich in vielen Fällen immer noch Sass-Schleifen. Dazu gehören das Generieren von Wertelisten, das Erstellen von Werten zum Anpassen von Verläufen, das Erstellen von Punktelisten bei der Arbeit mit einer Funktion polygon(), das Erstellen von Transformationslisten usw.



Unten finden Sie ein Beispiel dafür, was ich früher beim Erstellen einiger HTML-Elemente mit dem Präprozessor getan hätte. Welcher Präprozessor es ist, spielt keine Rolle, aber ich habe mich für Pug entschieden:



- let n = 12;

while n--
  .item


Dann würde ich eine Variable $nin Sass erstellen (und diese Variable sollte den gleichen Wert wie in HTML haben) und damit eine Schleife starten, in der ich die Transformationen generieren würde, die zum Positionieren der einzelnen Elemente verwendet werden:



$n: 12;
$ba: 360deg/$n;
$d: 2em;

.item {
  position: absolute;
  top: 50%; left: 50%;
  margin: -.5*$d;
  width: $d; height: $d;
  /*    */

  @for $i from 0 to $n {
    &:nth-child(#{$i + 1}) {
      transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba);
      &::before { content: '#{$i}' }
    }
  }
}


Der Nachteil dabei ist, dass ich die Werte sowohl im Mops-Code als auch im Sass-Code ändern müsste, falls sich die Anzahl der Elemente ändert. Es gibt auch viele Wiederholungen im Code.





Aus dem obigen Code generierter CSS-Code



Jetzt habe ich einen anderen Ansatz gewählt. Mit Pug generiere ich nämlich Indizes als benutzerdefinierte Eigenschaften und verwende sie dann in der Deklarationtransform.



Hier ist der Code, den Pug verarbeiten möchte:



- let n = 12;

body(style=`--n: ${n}`)
  - for(let i = 0; i < n; i++)
    .item(style=`--i: ${i}`)


Hier ist der Sass-Code:



$d: 2em;

.item {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -.5*$d;
  width: $d;
  height: $d;
  /*    */
  --az: calc(var(--i)*1turn/var(--n));
  transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az)));
  counter-reset: i var(--i);

  &::before { content: counter(i) }
}


Sie können hier mit diesem Code experimentieren.





Mit Schleifen generierte und gestaltete Elemente Durch die



Verwendung dieses Ansatzes wurde die Menge an automatisch generiertem CSS erheblich reduziert.





Aus dem obigen Code generiertes CSS



Wenn Sie jedoch so etwas wie einen Regenbogen erstellen möchten, können Sie nicht auf Sass-Schleifen verzichten.



@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) {
  $unit: 360/$n;
  $s-list: ();

  @for $i from 0 through $n {
    $s-list: $s-list, hsl($i*$unit, $sat, $lum)
  }

  @return $s-list
}

html { background: linear-gradient(90deg, get-rainbow()) }


Hier ist eine funktionierende Version dieses Beispiels.





Mehrfarbiger Hintergrund



Natürlich kann dies mit Pug-Variablen generiert werden, aber dieser Ansatz hat keinen Vorteil gegenüber der Dynamik von CSS-Variablen und reduziert nicht die Menge an Code, die an den Browser übergeben wird. Daher macht es für mich keinen Sinn aufzugeben, was ich gewohnt bin.



Ich verwende häufig in Sass (und Compass) integrierte mathematische Funktionen, wie z. B. trigonometrische Funktionen. Heutzutage sind diese Funktionen Teil der CSS-Spezifikation , werden jedoch noch nicht von allen Browsern unterstützt. Sass hat diese Funktionen nicht, Compass jedoch, weshalb ich häufig Compass verwende.



Und natürlich kann ich in Sass meine eigenen Funktionen dieser Art schreiben. Ich habe dies am Anfang getan, bevor Compass inverse trigonometrische Funktionen unterstützte. Ich brauche diese Funktionen wirklich, also habe ich sie selbst mit Taylor-Serien geschrieben . Aber heutzutage sind diese Funktionen in Compass. Sie sind besser und produktiver als die, die ich selbst geschrieben habe.



Mathematische Funktionen sind mir sehr wichtig, weil ich Programmierer und kein Künstler bin. Die Werte in meinem CSS-Code werden normalerweise aus mathematischen Berechnungen generiert. Dies sind keine "magischen Zahlen" oder etwas, das eine rein ästhetische Rolle spielt. Ein Beispiel für ihre Verwendung ist das Generieren einer Liste von regulären oder quasi-regulären Polygonen fürclip-path... Dies wird zum Beispiel verwendet, wenn Sie so etwas wie Avatare oder Aufkleber erstellen, deren Form sich von der rechteckigen unterscheidet.



Stellen Sie sich ein reguläres Polygon vor, dessen Eckpunkte auf einem Kreis liegen. Durch Ziehen des Schiebereglers im folgenden Beispiel, mit dem wir hier experimentieren können , können wir sehen, wo die Punkte für Formen mit unterschiedlicher Anzahl von Scheitelpunkten platziert sind.





Eine Form mit drei Eckpunkten



So sieht der entsprechende Sass-Code aus:



@mixin reg-poly($n: 3) {
  $ba: 360deg/$n; //  
  $p: (); //   ,  

  @for $i from 0 to $n {
    $ca: $i*$ba; //  
    $x: 50%*(1 + cos($ca)); //  x  
    $y: 50%*(1 + sin($ca)); //  y  
    $p: $p, $x $y //       
  }

  clip-path: polygon($p) //       clip-path 
}


Bitte beachten Sie, dass wir hier Schleifen und andere Konstrukte verwenden, deren Verwendung mit reinem CSS sehr unpraktisch ist.



In einer etwas fortgeschritteneren Version dieses Beispiels kann das Polygon gedreht werden, indem $oader Ecke, die jedem Scheitelpunkt entspricht, derselbe Versatz ( ) hinzugefügt wird . Dies ist im folgenden Beispiel zu sehen . Hier werden Sterne erzeugt, die ähnlich angeordnet sind, aber immer eine gerade Anzahl von Eckpunkten haben. In diesem Fall befindet sich jeder Scheitelpunkt mit einem ungeraden Index auf einem Kreis, dessen Radius kleiner als der Hauptkreis ist ( $f*50%).





Stern



Du kannst so interessante Sterne machen.





Sterne



Sie können Aufkleber mit Rahmen (border)erstellen,die mit ungewöhnlichen Vorlagen erstellt wurden. In diesem Beispiel wird ein Aufkleber aus einem einzelnen HTML-Element erstellt, und die zur Anpassung verwendete Vorlage wirdbordermithilfe vonclip-pathSass-Schleifen und Mathematik erstellt. Tatsächlich gibt es hier viele Berechnungen.





Aufkleber mit komplexen Rändern



Ein weiteres Beispiel ist die Erstellung eines Hintergrunds für Karten. Hier wird in einer Schleife unter Verwendung des Moduloperators und der Exponentialfunktionen ein Hintergrund mit einer Nachahmung des Dithering-Effekts erzeugt.





Dithering-Effekt Auch



hier werden häufig CSS-Variablen verwendet.



Als Nächstes können Sie Mixins verwenden, um zu vermeiden, dass Sie beim Stylen von Schiebereglern immer wieder dieselbe Deklaration schreiben müssen. Verschiedene Browser verwenden unterschiedliche Pseudoelemente, um die internen Komponenten solcher Steuerelemente zu formatieren. Daher müssen Sie für jede Komponente Stile definieren, die ihr Erscheinungsbild mithilfe verschiedener Pseudoelemente steuern.



Leider können Sie in CSS, so verlockend es auch klingt, so etwas wie den folgenden Code nicht einfügen:



input::-webkit-slider-runnable-trackinput::-moz-range-trackinput::-ms-track { /*   */ }


Es wird nicht funktionieren. Dieser gesamte Regelsatz wird ignoriert, wenn mindestens ein Selektor nicht erkannt wird. Und da in diesem Beispiel kein Browser über die Existenz aller drei Selektoren Bescheid weiß, werden diese Stile in keinem Browser angewendet.



Wenn das Styling funktionieren soll, müssen Sie Folgendes tun:



input::-webkit-slider-runnable-track { /*   */ }
input::-moz-range-track { /*   */ }
input::-ms-track { /*   */ }


Dies kann jedoch dazu führen, dass dieselben Stile dreimal im Code vorkommen. Wenn Sie beispielsweise eine trackEigenschaft ändern müssen, müssen backgroundSie die Stile in ::-webkit-slider-runnable-track, in ::-moz-range-trackund in bearbeiten ::-ms-track.



Die einzig vernünftige Lösung für dieses Problem ist die Verwendung von Mixins. Stile werden im kompilierten Code wiederholt, da es keine Möglichkeit gibt, darauf zu verzichten, aber jetzt müssen wir zumindest nicht denselben Code dreimal im Editor eingeben.



@mixin track() { /*   */ }

input {
  &::-webkit-slider-runnable-track { @include track }
  &::-moz-range-track { @include track }
  &::-ms-track { @include track }
}


Ergebnis



Die wichtigste Schlussfolgerung, die ich ziehen kann, lautet: Auf Sass in können wir nicht verzichten.



Benutzt du Sass?






All Articles