web-dev-qa-db-fra.com

Ajouter un type d'unité au résultat d'un calcul

J'ai récemment refacturé mon CSS sur une feuille de style SASS. J'utilise l'extension Mindscape Web Workbench pour VS2012, qui recrée le CSS chaque fois que vous enregistrez votre SCSS. J'ai commencé avec un code similaire à ceci:

/* Starting point: */
h1 { font-size: 1.5em; /* 24px ÷ 16px */ }

Puis j'ai essayé de le reformuler en premier à ceci:

/* Recfator: */
h1 { font-size: (24px / 16px)em; }

Mais cela produit malheureusement:

/* Result: */
h1 { font-size: 1.5 em; }              /* doesn't work, gives "1.5 em" */

Remarquez le espace supplémentaire , ce que je ne veux pas là. J'ai essayé plusieurs alternatives, en voici quelques unes:

h1 { font-size: (24/16)em; }           /* doesn't work, gives "1.5 em" */
h2 { font-size: 24 / 16em; }           /* doesn't work, gives "24/16em" */
h3 { font-size: (24px / 16px) * 1em; } /* works but "* 1 em" feels unnecessary */
h4 { font-size: (24em) / 16; }         /* works, but without "px" it's not 
                                          really conveying what I mean to say */

J'ai aussi essayé ces variantes avec des variables (parce que je les veux quand même), mais cela n'a pas beaucoup changé la situation. Pour que les exemples de cette question soient épurés, j'ai omis les variables. Cependant, j'accepterais volontiers une solution reposant sur l'utilisation de variables (de manière propre).

J'ai parcouru la pertinente documentation SASS sur '/' , et j'apprécie qu'il s'agisse d'une tâche difficile pour SASS car le caractère '/' a déjà une signification dans le code CSS de base. Quoi qu'il en soit, j'espérais une solution propre. Est-ce que j'ai râté quelque chose?

PS Cet article de blog n'offre qu'une solution en utilisant une fonction définie par l'utilisateur. Cela semble toutefois un peu lourd, alors je suis intéressé par des solutions "plus propres", conformes à mes tentatives ci-dessus. Si quelqu'un peut expliquer que "l'approche par la fonction" est la meilleure (ou même la seule) solution, j'accepte également cette réponse.

PS Cette question connexe semble être à peu près la même chose, bien que celle-ci veuille spécifiquement faire d'autres calculs. La réponse acceptée ici est mon troisième solution de contournement (en multipliant par 1em), mais j'aimerais savoir s'il existe une méthode différente (plus propre) si je suis prêt à renoncer à la possibilité d'effectuer d'autres calculs. Peut-être que la méthode mentionnée dans cette question ("interpolation") m'est utile?


Bottom Line: _ comment pouvez-vous ajouter proprement le type d'unité (par exemple, em) au résultat d'un calcul dans SASS?

46
Jeroen

Le seul moyen d’ajouter une unité à un nombre est de procéder par l’arithmétique .

Effectuer des opérations telles que la concaténation (par exemple, 1 + px) ou l'interpolation (par exemple - #{1}px) ne créera qu'un string that ressemble semblable à un nombre. Même si vous êtes absolument sûr à 100% de ne jamais utiliser votre valeur dans une autre opération arithmétique, vous ne devriez pas le faire.

Plus important que de ne pas pouvoir effectuer d'opérations arithmétiques, vous ne pourrez pas les utiliser avec d'autres fonctions qui attendent un nombre:

$foo: 1; // a number
$foo-percent: $foo + '%'; // a string

.bar {
    color: darken(blue, $foo-percent); //Error: "1%" is not a number!
}

$ amount: "1%" n'est pas un nombre pour "assombrir"

Il n'y a rien à gagner à attribuer vos numéros à des chaînes. Utilisez toujours l'arithmétique (multiplication par 1 ou addition par 0) pour ajouter une unité:

$foo: 1; // a number
$foo-percent: $foo * 1%; // still a number! //or: $foo + 0%

.bar {
    color: darken(blue, $foo-percent); //works!
}

Sortie:

.bar {
  color: #0000fa;
}

Voici un mixin que j'ai écrit dans le cadre de ma bibliothèque de mixins Flexbox et qui s'étouffera si vous passez une chaîne (pour ceux qui ne sont pas familiers avec Flexbox, la spécification d'origine ne permet que des entiers pour la propriété box-flex. flex: auto ou flex: 30em ne peut pas être rendu compatible avec la propriété comparable box-flex, de sorte que le mixin ne se donne pas la peine d'essayer)

@mixin flex($value: 0 1 auto, $wrap: $flex-wrap-required, $legacy: $flex-legacy-enabled) {
    @if $legacy and unitless(nth($value, 1)) {
        @include legacy-flex(nth($value, 1));
    }

    @include experimental(flex, $value, flex-support-common()...);
}

@mixin legacy-flex($value: 0) {
    @include experimental(box-flex, $value, $box-support...);
}
57
cimmanon

Vous pouvez essayer l'un ou l'autre:

font-size: $size * 1px;

ou

font-size: $size + unquote("px");

$size est le résultat de votre calcul.

32
Naoise Golden

Choisissez la méthode que vous préférez

$font: 24px;
$base: 16px;

Pas de variables

.item1 { font-size: #{(24px / 16px)}em; }

Utiliser uniquement des variables

.item2 { font-size: #{$font / $base}em; }

Une variable

.item3 { font-size: #{$font / 16px}em; }
.item4 { font-size: #{24px / $base}em; }

Sortie pour tous

.item1 { font-size: 1.5em; }
.item2 { font-size: 1.5em; }
.item3 { font-size: 1.5em; }
.item4 { font-size: 1.5em; }

La méthode utilisée s'appelle interpolation # {}

17
electric_g

Je suppose que la raison pour laquelle vous posez cette question est parce que, dans le contexte qui l’entoure, 1 em = 16 px, et que vous souhaitez utiliser cette relation pour convertir la taille de police cible de pixels en ems.

Si c'est le cas, la chose right consiste à multiplier la taille de la police par le facteur de mise à l'échelle 1em/16px, comme suit:

$h1-font-size: 24px;
$body-font-size: 16px;

$body-em-scale: 1em / $body-font-size;

h1 {
  font-size: $h1-font-size * $body-em-scale;  // -> 1.5em
}

ou juste:

h1 {
  font-size: $h1-font-size * (1em / $body-font-size);  // -> 1.5em
}

C’est exactement comme cela que ça marche en physique aussi: si vous avez, disons, 50 moles d’eau et que vous voulez savoir combien cela pèse en grammes , vous multipliez la quantité d’eau que vous avez ( = 50 mol) avec la masse molaire d'eau (18 g/mol) pour déterminer que votre échantillon d'eau pèse 50 mol × 18 g/mol ≈ 900 grammes. La conversion de pixels en ems dans SASS fonctionne de la même manière: commencez par déterminer le nombre d’em par pixel, dans le contexte dans lequel vous souhaitez utiliser la règle, puis multipliez la taille en px avec ce rapport, exprimée en unités de em/px.


Ps. Bien sûr, si les unités que vous convertissiez avaient un ratio fixe que SASS connaissait déjà, vous pouvez simplement le laisser procéder à la conversion automatiquement pour vous, en utilisant le «truc plus zéro». Par exemple, si vous voulez convertir la taille de la police de px en cm, vous pouvez simplement faire:

h1 {
  font-size: 0cm + $h1-font-size;  // -> 0.635cm
}

Cela fonctionne parce que SASS vous permet d’additionner deux valeurs données dans des unités compatibles (comme px et cm) et d’exprimer le résultat dans les mêmes unités que la valeur first de la somme. La raison pour laquelle cette astuce ne fonctionne pas pour px -> em est qu’ici le facteur de conversion n’est pas fixe, mais dépend du contexte, et SASS ne sait donc pas comment effectuer la conversion automatiquement.

6
Ilmari Karonen

La meilleure façon d’ajouter une unité est d’utiliser ... * 1em ou ... + 0em, où em est l’unité que vous souhaitez obtenir:

font-size: (24px/16px) + 0em; // ... + 0px for px
//or
font-size: (24px/16px) * 1em; 
//both produce: font-size: 1.5em;

De cette façon, il restera un nombre que vous pouvez utiliser dans d'autres fonctions ou opérations mathématiques. 

Mais si vous voulez que le résultat soit sous la forme d'une chaîne ou ne vous souciez pas de la valeur numérique du résultat pour une raison quelconque, vous pouvez simplement l'obtenir de cette façon:

font-size: (24px/16px) + em; //font-size: 1.5em; //not em does not include quotations

pas besoin d'utiliser unquote ou #{} ici (comme écrit dans d'autres réponses)!

0
S.Serpooshan