Les variables natives CSS ne fonctionnent pas dans les requêtes multimédias

140

J'essaie d'utiliser des variables CSS dans la requête multimédia et cela ne fonctionne pas.

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

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

}

la source
Avez-vous essayé dans plusieurs navigateurs? (Comme Chrome et Firefox)
Cohars
1
Sans préprocesseur @SandrinaPereira
Cohars
1
@SandrinaPereira Donc vous pouvez sur Firefox et Chrome 👍
Cohars
3
Juste pour clarifier pour les personnes qui trouvent cela via Google: vous pouvez utiliser des propriétés personnalisées CSS dans le cadre d'une requête multimédia, vous ne pouvez tout simplement pas les utiliser dans une déclaration de requête multimédia.
David Deprost

Réponses:

112

De la spécification ,

La var()fonction peut être utilisée à la place de n'importe quelle partie d'une valeur dans n'importe quelle propriété d'un élément. La var()fonction ne peut pas être utilisée comme noms de propriété, sélecteurs ou autre chose que les valeurs de propriété. (Cela produit généralement une syntaxe invalide, ou bien une valeur dont la signification n'a aucun lien avec la variable.)

Donc non, vous ne pouvez pas l'utiliser dans une requête multimédia.

Et cela a du sens. Parce que vous pouvez définir --mobile-breakpointpar exemple à :root, c'est-à-dire l' <html>élément, et de là être hérité à d'autres éléments. Mais une requête multimédia n'est pas un élément, elle n'hérite pas <html>, donc elle ne peut pas fonctionner.

Ce n'est pas ce que les variables CSS essaient d'accomplir. Vous pouvez utiliser un préprocesseur CSS à la place.

Oriol
la source
77
La réponse est correcte en ce que la spécification ne gère actuellement pas les variables CSS dans les requêtes multimédias, mais incorrecte en ce que ce n'est pas ce que les variables CSS essaient d'accomplir. Réduire la répétition et les nombres magiques est exactement la raison pour laquelle les variables CSS ont été créées - voir w3.org/TR/css-variables-1/#intro
mikemaccana
69

Comme Oriol a répondu , actuellement, les variables CSS de niveau 1 ne var()peuvent pas être utilisées dans les requêtes multimédias . Cependant, des développements récents permettront de résoudre ce problème. Dans quelques années, une fois que le module de variables d'environnement CSS niveau 1 sera standardisé et implémenté, nous pourrons utiliser des env()variables dans les requêtes multimédias dans tous les navigateurs modernes.

Si vous lisez la spécification et avez un problème, ou si vous souhaitez exprimer votre soutien pour le cas d'utilisation de la requête multimédia, vous pouvez toujours le faire dans GitHub w3c / csswg-drafts # 1693 ou dans tout problème CSS GitHub préfixé par "[ css-env-1] » .


Réponse originale 09/11/2017 : Récemment, le groupe de travail CSS a décidé que les variables CSS de niveau 2 prendront en charge les variables d'environnement définies par l'utilisateur env()et essaieront de les rendre valides dans les requêtes multimédias . Le Groupe a résolu ce problème après qu'Apple ait proposé pour la première fois des propriétés d'agent utilisateur standard , peu de temps avant l'annonce officielle de l'iPhone X en septembre 2017 (voir également WebKit: «Conception de sites Web pour iPhone X» par Timothy Horton ). D'autres représentants de navigateurs ont alors convenu qu'ils seraient généralement utiles sur de nombreux appareils, tels que les écrans de télévision et l'impression à l'encre avec des bords perdus. ( env()anciennement appeléconstant(), mais cela est désormais obsolète. Vous verrez peut-être encore des articles faisant référence à l'ancien nom, comme cet article de Peter-Paul Koch .) Après quelques semaines, Cameron McCormack de Mozilla s'est rendu compte que ces variables d'environnement seraient utilisables dans les requêtes médiatiques, et Tab Atkins, Jr. de Google s'est alors rendu compte que les variables d'environnement définies par l'utilisateur seraient particulièrement utiles en tant que variables racine globales et non remplaçables utilisables dans les requêtes multimédias. Désormais, Dean «Dino» Jackson d'Apple se joindra à Atkins pour éditer le niveau 2.

Vous pouvez vous abonner aux mises à jour sur ce sujet dans le w3c/csswg-draftsnuméro 1693 de GitHub . (Pour des détails historiques particulièrement pertinents, développez les journaux de réunion intégrés dans les résolutions du CSSWG Meeting Bot et recherchez «MQ», qui signifie «requêtes médias».)

Je prévois de mettre à jour cette question à l'avenir lorsque d'autres développements se produiront. L'avenir est passionnant.


Mise à jour 2018-02-08 : Safari Technology Preview 49 a ajouté la prise en charge de l'analyse calc()dans les requêtes multimédias, ce qui peut être un prélude à env()leur prise en charge.


Mise à jour 27/04/2018 : l'équipe Chromium de Google a décidé de commencer à travailler env(). En réponse, Atkins a commencé à spécifier env()dans un projet de norme séparé et non officiel: le module de variables d'environnement CSS niveau 1 . (Voir son commentaire GitHub dans w3c / csswg-drafts # 1693 et son commentaire dans w3c / csswg-drafts # 1817. ) Le brouillon appelle les variables dans les requêtes multimédias comme cas d'utilisation explicite:

Étant donné que les variables d'environnement ne dépendent pas de la valeur de tout élément tiré d'un élément particulier, elles peuvent être utilisées dans des endroits où il n'y a pas d'élément évident à partir @mediaduquel tirer, comme dans les règles, où la var()fonction ne serait pas valide.

Si vous lisez la spécification et avez un problème, ou si vous souhaitez exprimer votre soutien pour le cas d'utilisation de la requête multimédia, vous pouvez toujours le faire dans GitHub w3c / csswg-drafts # 1693 ou dans tout problème CSS GitHub préfixé par "[ css-env-1] » .


Mise à jour 2019-07-06 : Le travail se poursuit sur les spécifications. Le numéro 2627 de GitHub et le numéro 3578 de GitHub sont consacrés aux variables d'environnement personnalisées dans les requêtes multimédias.

jschoi
la source
31

Ce que vous POUVEZ faire cependant, c'est @media interroger votre instruction: root!

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

Fonctionne totalement dans Chrome, Firefox et Edge au moins les dernières versions de production à partir de cette publication.

Sean
la source
Ouah merci! Cela devrait certainement être la bonne réponse.
SimplyComplexable
1
Bon à savoir. Une limitation: si vous avez également besoin d'accéder à cette valeur en tant que var, afin de pouvoir l'utiliser dans des calculs ailleurs dans le css, cela nécessite toujours de mettre la "valeur magique" (ici, 479px) à deux endroits: la requête multimédia et une déclaration var.
ToolmakerSteve
8

Apparemment, il n'est tout simplement pas possible d'utiliser des variables CSS natives comme ça. C'est l'une des limites .

Une manière intelligente de l'utiliser est de changer vos variables dans la requête média, pour avoir un impact sur tout votre style. Je recommande cet article .

:root {
  --gutter: 4px;
}

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

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}
Cohars
la source
Je ne comprends pas la signification de "modifier vos variables dans la requête multimédia", vous pouvez montrer l'exemple?
1
Ce n'est pas ce que je voulais dire. J'ai posé des questions sur la valeur de la requête multimédia.
4
Oui, je viens de le faire, c'est dans l'article que j'ai lié. Je sais que ce n'est pas ce à quoi vous vous attendiez, mais les variables CSS ne peuvent tout simplement pas être utilisées pour définir les requêtes multimédias
Cohars
8

Une façon d'obtenir ce que vous voulez est d'utiliser le package npm postcss-media-variables.

Si vous êtes d'accord avec l'utilisation des packages npm, vous pouvez consulter la documentation pour la même chose ici

Exemple

/* 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) {}
pradeep1991singh
la source
4
Merci, mais j'essayais de ne pas utiliser de préprocesseur.
et. al: Avec postcss, vous pouvez également utiliser cssnext cssnext.io/features/#custom-media-queries
sebilasse
1
@sebilasse: custom-media-queries ne résout pas le problème principal de ne pas pouvoir utiliser des variables css comme points d'arrêt pour les requêtes de média
zhirzh
1
postcss n'est pas un préprocesseur
1

Comme vous pouvez lire d'autres réponses, il n'est toujours pas possible de le faire.

Quelqu'un a mentionné des variables d'environnement personnalisées (similaires aux variables css personnalisées env()au lieu de var()), et le principe est valable, bien qu'il y ait encore 2 problèmes majeurs:

  • faible support du navigateur
  • jusqu'à présent, il n'y a aucun moyen de les définir (mais le sera probablement dans le futur, car il ne s'agit pour l'instant que d'un projet non officiel)
Le Vojtisek
la source
1

Réponse courte

Vous pouvez utiliser JavaScript pour modifier la valeur des requêtes multimédias et la définir sur la valeur d'une variable css.

// 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 = '..'


Longue réponse

J'ai écrit un petit script que vous pouvez inclure sur votre page. Il remplace chaque règle de média par une valeur de 1pxpar la valeur de la variable css --replace-media-1px, les règles par une valeur 2pxpar --replace-media-2pxet ainsi de suite. Cela fonctionne pour les requêtes des médias with, min-width, max-width, height, min-heightet max-heightmême quand ils sont connectés à l' aide 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) {
  ...
}
Ich_73
la source