Bedingte Media Query Mixins

Avatar of Chris Coyier
Chris Coyier am

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

Sass macht die Arbeit mit Media Queries ziemlich ausgezeichnet. Sie können diese direkt innerhalb anderer CSS-Blöcke verschachteln, was die geänderten Eigenschaften und Werte nebeneinander platziert. Das schafft eine offensichtliche Verbindung zwischen ihnen, was ein wesentlich besseres Autoring-Erlebnis ist, als zu versuchen, diese Änderungen, getrennt durch viel anderen Code oder in einer anderen Datei, zu verwalten. Wir haben das schon einmal behandelt. Es war neu in Sass 3.2.

.column-1-3 {
  width: 33.3333%;
  @media (max-width: 600px) {
    width: 100%;
  }
}

Da wir dies wahrscheinlich immer wieder tun werden, sollten wir diese Media Query wie jede andere Variable abstrahieren.

$bp-babybear: "(max-width: 600px)";

.column-1-3 {
  width: 33.33%;
  @media #{$bp-babybear} {
    width: 100%;
  }
}

Üblicher ist jedoch die Verwendung von @mixin in Verbindung mit Sass @content-Blöcken. Dies haben wir im Artikel Benennung von Media Queries behandelt.

@mixin bp($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 600px)  { @content; }
  }
}

Welches Sie so verwenden

.sidebar {
  width: 33.33%;
  @include bp(baby-bear) {
    width: 100%;
  }
}

Und es gibt keinen Grund, warum Sie nicht beides tun können, indem Sie die Media Queries in Variablen abstrahieren, wenn Sie die Optik davon bevorzugen

@mixin bp($point) {
  
  $bp-babybear: "(max-width: 600px)";
  $bp-mamabear: "(max-width: 1250px)";
  $bp-papabear: "(max-width: 1600px)";

  @if $point == papa-bear {
    @media #{$bp-papabear} { @content; }
  }
  @else if $point == mama-bear {
    @media #{$bp-mamabear} { @content; }
  }
  @else if $point == baby-bear {
    @media #{$bp-babybear}  { @content; }
  }

}

Was die exakt gleiche Verwendung hat.

Nebenbei bemerkt, mag ich "bp" als Namen, da es etwas ist, das man immer wieder tippen muss und es kurz und bündig ist.

Auf den ersten Blick scheint der @mixin-Ansatz einen begrenzten Wert zu haben. Die Verwendung einer Variable ist weniger ausführlich und ergibt genauso viel Sinn. Mit dem @mixin erhalten wir jedoch zusätzliche Kräfte!

Vielleicht möchten wir eine Version eines Stylesheets erstellen, das überhaupt keine Media Queries enthält. Das ist unter bestimmten Umständen absolut sinnvoll. Vielleicht möchten wir ein Stylesheet für IE 8 und darunter erstellen. Nicolas Gallagher spielte vor Jahren mit der Verwendung von Sass dafür, aber das ist etwas anders. IE 8 und darunter unterstützen von Haus aus keine Media Queries, also entscheiden wir uns vielleicht dafür, ihnen ein gestrafftes Stylesheet zur Verfügung zu stellen, das sie überhaupt nicht enthält. Alte Browser wie dieser sind sowieso langsamer, also bestrafen wir sie nicht mit zusätzlichem Code, den sie nicht verwenden können, sondern helfen ihnen, indem wir ihnen weniger zur Verfügung stellen. Eine Art Universal IE 6 Stylesheet-Idee.

Wir können eine Kombination von bedingten Kommentaren verwenden, um das zu tun.

<!--[if !IE 8]><!-->
  <link rel="stylesheet" href="style.css">
<!--<![endif]-->

<!--[if gte IE 9]>
  <link rel="stylesheet" href="style.css">
<![endif]-->

<!--[if lte IE 8]>
  <link rel="stylesheet" href="style-NoMQs.css">
<![endif]-->

Ein weiterer sinnvoller und realweltlicher Grund, ein Stylesheet ohne Media Queries bereitzustellen, ist, wenn einige Seiten Ihrer Website responsives Design verwenden und einige Seiten Ihrer Website eine mobil-spezifische Version haben. Ich halte das für vernünftig. Die Seiten, die eine mobil-spezifische Version haben, benötigen diese Media Queries eigentlich nicht.

Wie erstellen wir also sowohl ein style.css als auch ein style-NoMQs.css aus demselben Quell-Sass? Wir nutzen die Kraft unseres @mixin.

Wir verwenden eine Logikbedingung innerhalb des bp @mixin, die entweder fortfährt und die Media Query ausgibt oder nichts ausgibt.

$MQs: true;

@mixin bp($point) {
  @if ($MQs) {
    $bp-babybear: "(max-width: 600px)";
    $bp-mamabear: "(max-width: 1250px)";
    $bp-papabear: "(max-width: 1600px)";
  
    @if $point == papa-bear {
      @media #{$bp-papabear} { @content; }
    }
    @else if $point == mama-bear {
      @media #{$bp-mamabear} { @content; }
    }
    @else if $point == baby-bear {
      @media #{$bp-babybear}  { @content; }
    }
  }
}

Sie würden diese Variable jedoch nicht direkt außerhalb des @mixin deklarieren. Sie würden sie aus Ihrer "Master"-Datei deklarieren, die alle Teil-Dateien importiert. Ihre style.scss-Datei könnte also so aussehen

$MQs: true;

@import "variables";
@import "colors";
@import "global";
/* etc. */

Und Sie erstellen die "Keine Media Queries"-Version (style-NoMQs.css), indem Sie eine style-NoMQs.scss erstellen

$MQs: false;

@import "variables";
@import "colors";
@import "global";
/* etc. */

Ändern Sie diese Variable einfach auf false, und die Ausgabe-CSS enthält überhaupt keine Media Queries.

Großen Dank an Cat Farman, die über dieselbe Idee in ihrem Cognition-Artikel Fall Back to the Cascade schrieb, mit der leichten Abwandlung, die Support-Variable an das @mixin selbst zu übergeben. (Ist das sicherer?)

Und als letzter Hinweis: Ich weiß, viele Leute mögen es nicht, wie Sass repetitive Media Queries in der endgültigen Ausgabe erzeugt und die Media Query nur so weit nach oben "blubbert" wie bis zum Ende der Verschachtelung. Das ist notwendig, um die Quellreihenfolge-Spezifität des Selektors zu berücksichtigen (soweit ich das verstehe). Ich persönlich habe mich nie darum gekümmert, da ich immer Assets mit aktiviertem GZip ausliefert, und GZip isst repetitive Texte zum Frühstück, es ändert die Dateigröße nicht wesentlich. Ganz zu schweigen davon, dass Browser problemlos durch diese Regeln zoomen und sie anwenden können. Wenn Ihnen das aber immer noch nicht gefällt (oder ich falsch liege), gibt es ein Grunt-Plugin dafür.

Andere Ansätze