CSS-native Variablen funktionieren nicht in Medienabfragen


139

Ich versuche, CSS-Variablen in Medienabfragen zu verwenden, und es funktioniert nicht.

:root {
  --mobile-breakpoint: 642px;
}

@media (max-width: var(--mobile-breakpoint)) {

}

Haben Sie es in mehreren Browsern versucht? (Wie Chrome und Firefox)
Cohars

1
Ohne Präprozessor @SandrinaPereira
Cohars

1
@ SandrinaPereira So können Sie auf Firefox und Chrome 👍
Cohars


3
Nur zur Verdeutlichung für Personen, die dies über Google finden: Sie können benutzerdefinierte CSS-Eigenschaften im Rahmen einer Medienabfrage verwenden, Sie können sie jedoch nicht in einer Deklaration für Medienabfragen verwenden.
David Deprost

Antworten:


112

Aus der Spezifikation ,

Die var()Funktion kann anstelle eines beliebigen Teils eines Werts in einer beliebigen Eigenschaft eines Elements verwendet werden. Die var()Funktion kann nicht als Eigenschaftsnamen, Selektoren oder andere Elemente als Eigenschaftswerte verwendet werden. (Dies führt normalerweise zu einer ungültigen Syntax oder zu einem Wert, dessen Bedeutung keine Verbindung zur Variablen hat.)

Nein, Sie können es nicht in einer Medienabfrage verwenden.

Und das macht Sinn. Denn Sie können --mobile-breakpointzB auf :rootdas <html>Element setzen und von dort an andere Elemente vererbt werden. Eine Medienabfrage ist jedoch kein Element, von dem sie nicht erbt <html>, sodass sie nicht funktionieren kann.

Dies ist nicht das, was CSS-Variablen erreichen wollen. Sie können stattdessen einen CSS-Präprozessor verwenden.


76
Die Antwort ist insofern richtig, als die Spezifikation derzeit keine CSS-Variablen in Medienabfragen verarbeitet, aber falsch darin ist nicht das, was CSS-Variablen erreichen wollen. Das Reduzieren von Wiederholungen und magischen Zahlen ist genau der Grund, warum CSS-Variablen erstellt wurden - siehe w3.org/TR/css-variables-1/#intro
mikemaccana

68

Wie Oriol geantwortet hat, können CSS-Variablen der Stufe 1 var()derzeit nicht in Medienabfragen verwendet werden . Es gab jedoch jüngste Entwicklungen, die dieses Problem angehen werden. In einigen Jahren, sobald das CSS-Umgebungsvariablenmodul Level 1 standardisiert und implementiert ist, können wir env()Variablen in Medienabfragen in allen modernen Browsern verwenden.

Wenn Sie die Spezifikation lesen und Bedenken haben oder Ihre Unterstützung für den Anwendungsfall für Medienabfragen zum Ausdruck bringen möchten , können Sie dies dennoch in GitHub w3c / csswg-Drafts # 1693 oder in einem CSS-GitHub-Problem mit dem Präfix „[ css-env-1] ” .


Ursprüngliche Antwort 09.11.2017 : Vor kurzem hat die CSS-Arbeitsgruppe entschieden, dass CSS-Variablen der Stufe 2 benutzerdefinierte Umgebungsvariablen verwenden env()und versuchen, sie in Medienabfragen gültig zu machen . Die Gruppe löste dies, nachdem Apple kurz vor der offiziellen Ankündigung des iPhone X im September 2017 erstmals Standard-Eigenschaften für Benutzeragenten vorgeschlagen hatte (siehe auch WebKit: „Entwerfen von Websites für das iPhone X“ von Timothy Horton ). Andere Browser-Vertreter waren sich dann einig, dass sie für viele Geräte wie Fernsehbildschirme und Tintendruck mit Beschnittungskanten im Allgemeinen nützlich sind. (wurde env()früher genanntconstant(), aber das ist jetzt veraltet. Möglicherweise sehen Sie immer noch Artikel, die sich auf den alten Namen beziehen, wie z. B. diesen Artikel von Peter-Paul Koch .) Nach einigen Wochen erkannte Cameron McCormack von Mozilla, dass diese Umgebungsvariablen in Medienabfragen verwendet werden können, und Tab Atkins, Jr. von Google erkannte dann, dass benutzerdefinierte Umgebungsvariablen besonders nützlich sind als globale, nicht überschreibbare Stammvariablen, die in Medienabfragen verwendet werden können. Jetzt wird Dean "Dino" Jackson von Apple zusammen mit Atkins Level 2 bearbeiten.

Sie können Updates zu diesem Thema in der w3c/csswg-draftsGitHub-Ausgabe Nr. 1693 abonnieren . (Erweitern Sie für besonders relevante historische Details die in den Auflösungen des CSSWG Meeting Bot eingebetteten Besprechungsprotokolle und suchen Sie nach "MQ", was für "Medienabfragen" steht.)

Ich plane, diese Frage in Zukunft zu aktualisieren, wenn weitere Entwicklungen auftreten. Die Zukunft ist aufregend.


Update 2018-02-08 : Safari Technology Preview 49 hat Unterstützung für das Parsen calc()in Medienabfragen hinzugefügt , was möglicherweise auch ein Auftakt für die Unterstützung env()in diesen ist.


Update 27.04.2018 : Das Chromium-Team von Google hat beschlossen, mit der Arbeit zu beginnen env(). Als Reaktion darauf hat Atkins begonnen, env()in einem separaten, inoffiziellen Standardentwurf festzulegen : das CSS-Umgebungsvariablenmodul Level 1 . (Siehe seinen GitHub-Kommentar in w3c / csswg-Drafts # 1693 und seinen Kommentar in w3c / csswg-Drafts # 1817. ) Der Entwurf ruft Variablen in Medienabfragen als expliziten Anwendungsfall auf:

Da Umgebungsvariablen nicht vom Wert eines aus einem bestimmten Element gezeichneten Elements abhängen, können sie an Stellen verwendet werden, an denen kein offensichtliches Element zum Zeichnen vorhanden ist, z. B. in @mediaRegeln, in denen die var()Funktion nicht gültig wäre.

Wenn Sie die Spezifikation lesen und Bedenken haben oder Ihre Unterstützung für den Anwendungsfall für Medienabfragen zum Ausdruck bringen möchten , können Sie dies dennoch in GitHub w3c / csswg-Drafts # 1693 oder in einem CSS-GitHub-Problem mit dem Präfix „[ css-env-1] ” .


Update 2019-07-06 : Die Arbeiten an den Spezifikationen werden fortgesetzt. GitHub-Ausgabe Nr. 2627 und GitHub-Ausgabe Nr. 3578 sind benutzerdefinierten Umgebungsvariablen in Medienabfragen gewidmet.


29

Was Sie jedoch tun können, ist @media, fragen Sie Ihre: root-Anweisung ab!

:root {
     /* desktop vars */
}
@media screen and (max-width: 479px) {
    :root {
        /* mobile vars */
    }
}

Funktioniert vollständig in Chrome, Firefox und Edge, mindestens den neuesten Produktionsversionen ab diesem Beitrag.


Wow, danke! Dies sollte definitiv die richtige Antwort sein.
SimplyComplexable

1
Gut zu wissen. Eine Einschränkung: Wenn Sie auch auf diesen Wert als zugreifen müssen, varum ihn in anderen Berechnungen verwenden zu können css, müssen Sie den "magischen Wert" (hier 479px) an zwei Stellen eingeben: der Medienabfrage und einer var-Deklaration.
ToolmakerSteve

8

Anscheinend ist es einfach nicht möglich, solche nativen CSS-Variablen zu verwenden. Das ist eine der Einschränkungen .

Eine clevere Möglichkeit, es zu verwenden, besteht darin, Ihre Variablen in der Medienabfrage zu ändern, um Ihren gesamten Stil zu beeinflussen. Ich empfehle diesen Artikel .

:root {
  --gutter: 4px;
}

section {
  margin: var(--gutter);
}

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}

Ich verstehe die Bedeutung von "Ändern Sie Ihre Variablen in der Medienabfrage" nicht. Können Sie ein Beispiel zeigen?

1
Das habe ich nicht gemeint. Ich habe nach dem Wert der Medienabfrage gefragt.

4
Ja, habe es gerade getan, es steht in dem Artikel, den ich verlinkt habe. Ich weiß, es ist nicht das, was Sie erwartet haben, aber CSS-Variablen können einfach nicht verwendet werden, um die Medienabfragen zu definieren
Cohars

8

Eine Möglichkeit, das zu erreichen, was Sie wollen, ist die Verwendung des npm-Pakets postcss-media-variables.

Wenn Sie mit der Verwendung von npm-Paketen einverstanden sind, können Sie hier eine Dokumentation finden

Beispiel

/* input */
:root {
  --min-width: 1000px;
  --smallscreen: 480px;
}
@media (min-width: var(--min-width)) {}
@media (max-width: calc(var(--min-width) - 1px)) {}

@custom-media --small-device (max-width: var(--smallscreen));
@media (--small-device) {}

4
Danke, aber ich habe versucht, keinen Präprozessor zu verwenden.

et. al: Mit postcss können Sie auch cssnext cssnext.io/features/#custom-media-queries
sebilasse

1
@sebilasse: benutzerdefinierte Medienabfragen behebt nicht das Hauptproblem, CSS-Variablen nicht als Haltepunkte für Medienabfragen verwenden zu können
zhirzh

1
postcss ist kein Präprozessor

1

Da Sie andere Antworten lesen können, ist dies immer noch nicht möglich .

Jemand erwähnte benutzerdefinierte Umgebungsvariablen (ähnlich wie benutzerdefinierte CSS-Variablen env()anstelle von var()), und das Prinzip ist solide, obwohl es immer noch zwei Hauptprobleme gibt:

  • schwache Browserunterstützung
  • Bisher gibt es keine Möglichkeit, sie zu definieren (wird aber wahrscheinlich in Zukunft sein, da dies bisher nur ein inoffizieller Entwurf ist).

1

Kurze Antwort

Sie können JavaScript verwenden, um den Wert von Medienabfragen zu ändern und auf den Wert einer CSS-Variablen festzulegen.

// get value of css variable
getComputedStyle(document.documentElement).getPropertyValue('--mobile-breakpoint'); // '642px'

// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];

// update media rule
mediaRule.media.mediaText = '..'


Lange Antwort

Ich habe ein kleines Skript geschrieben, das Sie auf Ihrer Seite einfügen können. Es ersetzt jede Medienregel durch einen Wert von 1pxdurch den Wert der CSS-Variablen --replace-media-1px, Regeln durch einen Wert 2pxmit --replace-media-2pxund so weiter. Dies funktioniert für die Medien - Anfragen with, min-width, max-width, height, min-heightund max-heightauch wenn sie mit verbunden sind and.

JavaScript:

function* visitCssRule(cssRule) {
    // visit imported stylesheet
    if (cssRule.type == cssRule.IMPORT_RULE)
        yield* visitStyleSheet(cssRule.styleSheet);

    // yield media rule
    if (cssRule.type == cssRule.MEDIA_RULE)
        yield cssRule;
}

function* visitStyleSheet(styleSheet) {
    try {
        // visit every rule in the stylesheet
        var cssRules = styleSheet.cssRules;
        for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
            yield* visitCssRule(cssRule);
    } catch (ignored) {}
}

function* findAllMediaRules() {
    // visit all stylesheets
    var styleSheets = document.styleSheets;
    for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
        yield* visitStyleSheet(styleSheet);
}

// collect all media rules
const mediaRules = Array.from(findAllMediaRules());

// read replacement values
var style = getComputedStyle(document.documentElement);
var replacements = [];
for (var k = 1, value; value = style.getPropertyValue('--replace-media-' + k + 'px'); k++)
    replacements.push(value);

// update media rules
for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
    for (var k = 0; k < replacements.length; k++) {
        var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): ' + (k+1) + 'px\\)', 'g');
        var replacement = '($1: ' + replacements[k] + ')';
        mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
    }
}

CSS:

:root {
  --mobile-breakpoint: 642px;

  --replace-media-1px: var(--mobile-breakpoint);
  --replace-media-2px: ...;
}

@media (max-width: 1px) { /* replaced by 642px */
  ...
}

@media (max-width: 2px) {
  ...
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.