web-dev-qa-db-fra.com

Utilisation de variables Sass avec des requêtes de média CSS3

J'essaie de combiner l'utilisation d'une variable Sass avec des requêtes @media comme suit:

$base_width:1160px;

@media screen and (max-width: 1170px) {$base_width: 960px;}
@media screen and (min-width: 1171px) {$base_width: 1160px;}

$base_width est ensuite défini en différents points dans les mesures basées sur le pourcentage de largeur de la feuille de style pour produire des présentations de fluide.

Lorsque je fais cela, la variable semble être correctement reconnue, mais les conditions de la requête multimédia ne le sont pas. Par exemple, le code ci-dessus produit une disposition de 1160 pixels quelle que soit la largeur de l'écran. Si je retourne les déclarations @media de la manière suivante:

@media screen and (min-width: 1171px) {$base_width: 1160px;}
@media screen and (max-width: 1170px) {$base_width: 960px;}

Il produit une mise en page de 960 pixels, quelle que soit la largeur de l'écran. Notez également que si je supprime la première ligne de $base_width: 1160px; _ renvoie une erreur pour une variable non définie. Des idées ce que je manque?

87
Jeremy S.

Ce n'est tout simplement pas possible. Comme le déclencheur @media screen and (max-width: 1170px) se produit côté client.

Atteindre le résultat attendu ne serait possible que si SASS saisissait toutes les règles et propriétés de votre feuille de style contenant votre $base_width variable et copié/modifié en conséquence.

Comme cela ne fonctionnera pas automatiquement, vous pouvez le faire à la main comme ceci:

@media screen and (max-width: 1170px)
      $base_width: 960px // you need to indent it to (re)set it just within this media-query
      // now you copy all the css rules/properties that contain or are relative to $base_width e.g.
      #wrapper
          width: $base_width
          ...

@media screen and (min-width: 1171px)
    $base_width: 1160px
      #wrapper
          width: $base_width
          ...

Ce n'est pas vraiment DRY mais c'est tout ce que vous pouvez faire.

Si les modifications sont les mêmes à chaque fois, vous pouvez également préparer un mixin contenant toutes les valeurs modifiées, sans avoir à le répéter. De plus, vous pouvez essayer de combiner le mixin avec des modifications spécifiques. Comme:

@media screen and (min-width: 1171px)
    +base_width_changes(1160px)
    #width-1171-specific-element // additional specific changes, that aren't in the mixin
        display: block

Et le Mixin ressemblerait à ceci

=base_width_changes($base_width)
    #wrapper
        width: $base_width
80
woerndl

Semblable à la réponse de Philipp Zedler, vous pouvez le faire avec un mixin. Cela vous permet de tout avoir dans un seul fichier si vous le souhaitez.

@mixin styling($base-width) {
    // your SCSS here, e.g.
    #Contents {
        width: $base-width;
    }
}

@media screen and (max-width: 1170px) {
    @include styling($base-width: 960px);
}
@media screen and (min-width: 1171px) {
    @include styling($base-width: 1160px);
}
39
ronen

Edit: S'il vous plaît ne pas utiliser cette solution. La réponse de Ronen est bien meilleure.

En tant que solution DRY, vous pouvez utiliser le @import déclaration dans une requête multimédia, par exemple comme ça.

@media screen and (max-width: 1170px) {
    $base_width: 960px;
    @import "responsive_elements";
}
@media screen and (min-width: 1171px) {
    $base_width: 1160px;
    @import "responsive_elements";
}

Vous définissez tous les éléments sensibles dans le fichier inclus à l'aide des variables définies dans la requête multimédia. Donc, tout ce que vous devez répéter est la déclaration d'importation.

6
Philipp Zedler

J'ai eu le même problème.

La variable $menu-width Doit être de 240px sur la vue mobile@media only screen and (max-width : 768px) et de 340px sur la vue desktop.

Donc, j'ai simplement créé deux variables:

$menu-width: 340px;
$menu-mobile-width: 240px;

Et voici comment je l'ai utilisé:

.menu {
    width: $menu-width;
    @media only screen and (max-width : 768px) {
      width: $menu-mobile-width;
    }
}
2
Dawid Dyrcz

Ce n'est pas possible avec SASS, mais c'est possible avec des variables CSS (ou propriétés personnalisées CSS ). Le seul inconvénient est la prise en charge du navigateur - mais il existe en fait un plugin PostCSS - variables postcss-css - qui "aplatit" l'utilisation des variables CSS (qui prend également en charge les navigateurs plus anciens).

L'exemple suivant fonctionne très bien avec SASS (et avec les variables postcss-css-variables, vous bénéficiez également d'une assistance pour les navigateurs plus anciens).

$mq-laptop: 1440px;
$mq-desktop: 1680px;

:root {
    --font-size-regular: 14px;
    --Gutter: 1rem;
}

// The fact that we have to use a `max-width` media query here, so as to not
// overlap with the next media query, is a quirk of postcss-css-variables
@media (min-width: $mq-laptop) and (max-width: $mq-desktop - 1px) {
    :root {
        --font-size-regular: 16px;
        --Gutter: 1.5rem;
    }
}

@media (min-width: $mq-desktop) {
    :root {
        --font-size-regular: 18px;
        --Gutter: 1.75rem;
    }
}

.my-element {
    font-size: var(--font-size-regular);
    padding: 0 calc(var(--Gutter) / 2);
}

Cela donnerait le CSS suivant. Les requêtes multimédias répétitives augmenteront la taille du fichier, mais j’ai constaté que l’augmentation est généralement négligeable une fois que le serveur Web applique gzip (ce qu’il fera habituellement automatiquement).

.my-element {
  font-size: 14px;
  padding: 0 calc(1rem / 2);
}
@media (min-width: 1680px) {
  .my-element {
  padding: 0 calc(1.75rem / 2);
  }
}
@media (min-width: 1440px) and (max-width: 1679px) {
  .my-element {
  padding: 0 calc(1.5rem / 2);
  }
}
@media (min-width: 1680px) {
  .my-element {
  font-size: 18px;
  }
}
@media (min-width: 1440px) and (max-width: 1679px) {
  .my-element {
  font-size: 16px;
  }
}
2
fredrikekelund

Avec @ ronen's bonne réponse et une carte, vous disposez d'un réel pouvoir:

@mixin styling($map) {
    .myDiv {
        background: map-get($map, 'foo');
        font-size: map-get($map, 'bar');
    }
}

@media (min-height: 500px) {
    @include styling((
        foo: green,
        bar: 50px
    ));
}

@media (min-height: 1000px) {
    @include styling((
        foo: red,
        bar: 100px
    ));
}

Il est maintenant possible d’en avoir beaucoup plus DRY) requêtes multimédia ciblant .myDiv avec un tas de valeurs différentes.


Documents cartographiques: https://sass-lang.com/documentation/functions/map

Exemple d'utilisation de la carte: https://www.sitepoint.com/using-sass-maps/

1
Ben