CSS: guide complet des fonctions calc ()

CSS a une fonction spéciale calc()utilisée pour effectuer des calculs simples. Voici un exemple de son utilisation:

.main-content {
  /*  80px  100vh */
  height: calc(100vh - 80px);
}

Ici,calc() vous pouvez expérimenter avec le code CSS dans lequel il est utilisé . L'auteur de l'article, dont nous publions aujourd'hui la traduction, souhaite parler de tout ce qui mérite d'être connu sur cette fonction très utile.





Fonction Calc () et valeurs des propriétés CSS


Le seul endroit où vous pouvez utiliser la fonction calc()est avec les valeurs de propriété CSS. Jetez un œil aux exemples suivants dans lesquels, à l'aide de cette fonction, nous définissons les valeurs de diverses propriétés.

.el {
  font-size: calc(3vw + 2px);
  width:     calc(100% - 20px);
  height:    calc(100vh - 20px);
  padding:   calc(1vw + 5px);
}

La fonction calc()peut également être utilisée pour définir n'importe quelle partie distincte de la propriété:

.el {
  margin: 10px calc(2vw + 5px);
  border-radius: 15px calc(15px / 3) 4px 2px;
  transition: transform calc(1s - 120ms);
}

Cette fonction peut même faire partie d'une autre fonction qui est responsable de faire partie d'une certaine propriété! Par exemple, ici, il est calc()utilisé pour ajuster la position du changement de couleur du dégradé:

.el {
  background: #1E88E5 linear-gradient(
    to bottom,
    #1E88E5,
    #1E88E5 calc(50% - 10px),
    #3949AB calc(50% + 10px),
    #3949AB
  );
}

La fonction calc () est un outil pour travailler avec des propriétés numériques.


Veuillez noter que dans tous les exemples ci-dessus, nous utilisons la fonction calc()lorsque nous travaillons avec des propriétés numériques. Nous parlerons également de certaines caractéristiques du travail avec des propriétés numériques (elles sont associées au fait que parfois l'utilisation d'unités de mesure n'est pas requise). Maintenant, nous notons que cette fonction est conçue pour effectuer des opérations avec des nombres, et non avec des chaînes ou avec autre chose.

.el {
  /* ! */
  counter-reset: calc("My " + "counter");
}
.el::before {
  /* ! */
  content: calc("Candyman " * 3);
}

Il existe de nombreuses unités de mesure qui peuvent être utilisés en CSS pour spécifier la taille des éléments et leurs parties: px, %, em, rem, in, mm, cm, pt, pc, ex, ch, vh, vw, vmin, vmax. Toutes ces unités peuvent être utilisées avec la fonction calc().

Cette fonction peut également fonctionner avec des nombres utilisés sans spécifier d'unités:

line-height: calc(1.2 * 1.2);

Il peut également être utilisé pour calculer des angles:

transform: rotate(calc(10deg * 5));

Cette fonction peut également être utilisée dans les cas où aucun calcul n'est effectué dans l'expression qui lui est passée:

.el {
  /*   ,    */
  width: calc(20px);
}

Calc () ne peut pas être utilisé dans les requêtes multimédias


Bien que cette fonction soit conçue pour définir les valeurs des propriétés CSS, elle ne fonctionne malheureusement pas dans les requêtes multimédias:

@media (max-width: 40rem) {
  /* 40rem   */
}

/*  ! */
@media (min-width: calc(40rem + 1px)) {
  /* ,  40rem */
}

Si une fois que ces constructions s'avèrent réalisables, ce sera très bien, car cela permettra de créer des requêtes multimédias mutuellement exclusives qui semblent très logiques (par exemple, celles illustrées ci-dessus).

Utilisation de différentes unités dans une seule expression


L'admissibilité à l'utilisation de différentes unités de mesure dans une même expression est probablement l'occasion la plus précieuse calc(). Similaire est utilisé dans presque tous les exemples ci-dessus. Ici, juste pour attirer votre attention, un autre exemple qui montre l'utilisation de différentes unités de mesure:

/*      */
width: calc(100% - 20px);

Cette expression se lit comme suit: "La largeur est égale à la largeur de l'élément à partir de laquelle 20 pixels sont soustraits."

Dans une situation où la largeur de l'élément peut changer, il est totalement impossible de calculer à l'avance la valeur souhaitée, en utilisant uniquement des indicateurs exprimés en pixels. En d'autres termes, vous ne pouvez pas prétraiter à l' calc()aide de quelque chose comme Sass et essayer d'obtenir quelque chose comme polyfill. Oui, ce n'est pas nécessaire, étant donné que les navigateurs prennentcalc() très bien en charge . Le point ici est que de tels calculs, dans lesquels les valeurs exprimées en différentes unités sont mélangées, doivent être effectués dans le navigateur (lors de "l'exécution" de la page). À savoir, la capacité d'effectuer de tels calculs est la valeur principale .calc()

Voici quelques autres exemples d'utilisation de valeurs exprimées dans différentes unités:

transform: rotate(calc(1turn + 45deg));

animation-delay: calc(1s + 15ms);

Vous pouvez probablement prétraiter ces expressions, car elles mélangent des valeurs dont les unités ne sont pas liées à tout ce qui est déterminé pendant l'exécution de la page dans le navigateur.

Comparaison de calc () avec les calculs du préprocesseur


Nous venons de dire que la fonctionnalité la plus utile calc()ne se prête pas au prétraitement. Mais le prétraitement offre au développeur des fonctionnalités qui correspondent aux capacités calc(). Par exemple, lorsque vous utilisez Sass, vous pouvez également calculer les valeurs des propriétés:

$padding: 1rem;

.el[data-padding="extra"] {
  padding: $padding + 2rem; //  3rem;
  margin-bottom: $padding * 2; //  2rem; 
}

Ici, des calculs peuvent être effectués en indiquant les unités de mesure, ici vous pouvez ajouter les quantités exprimées dans les mêmes unités de mesure, vous pouvez multiplier certaines valeurs par des valeurs dont les unités ne sont pas indiquées. Mais il n'est pas possible d'effectuer des calculs avec des valeurs exprimées dans différentes unités de mesure. Des restrictions ressemblant à des restrictions sont imposées à ces calculs calc()(par exemple, les nombres par lesquels quelque chose est multiplié ou divisé doivent être des valeurs sans unités).

Divulgation de la signification des valeurs numériques utilisées en CSS


Même si vous ne profitez pas des opportunités qui ne sont réalisables qu'avec de l'aide calc(), cette fonction peut être utilisée pour révéler la signification des valeurs utilisées dans CSS. Supposons que vous souhaitiez que la valeur d'une propriété soit exactement 1/7 de la largeur de l'élément:

.el {
  /*   , */
  width: calc(100% / 7);

  /*   */
  width: 14.2857142857%;
}

Cette approche peut être utile dans quelque chose comme une sorte d'API CSS auto-dénommée:

[data-columns="7"] .col { width: calc(100% / 7); }
[data-columns="6"] .col { width: calc(100% / 6); }
[data-columns="5"] .col { width: calc(100% / 5); }
[data-columns="4"] .col { width: calc(100% / 4); }
[data-columns="3"] .col { width: calc(100% / 3); }
[data-columns="2"] .col { width: calc(100% / 2); }

Opérateurs mathématiques de la fonction calc ()


L'expression à évaluer avec l'aide des calc()opérateurs que vous pouvez utiliser +, -, *et /. Mais dans leur application, il existe certaines fonctionnalités.

Lors de l'ajout ( +) et de la soustraction ( -), vous devez utiliser les valeurs avec les unités spécifiées

.el {
  /*  */
  margin: calc(10px + 10px);

  /*  */
  margin: calc(10px + 5);
}

Veuillez noter que l'utilisation de valeurs incorrectes conduit au fait qu'une annonce particulière devient également incorrecte.

Lors de la division ( /), il est nécessaire que l'unité de mesure ne soit pas indiquée sur le deuxième chiffre

.el {
  /*  */
  margin: calc(30px / 3);

  /*  */
  margin: calc(30px / 10px);

  /*  (   ) */
  margin: calc(30px / 0);
}

Lors de la multiplication ( *), l'un des nombres ne doit pas avoir une unité de mesure:

.el {
  /*  */
  margin: calc(10px * 3);

  /*  */
  margin: calc(3 * 10px);

  /*  */
  margin: calc(30px * 3px);
}

L'importance des espaces


Les espaces utilisés dans les expressions sont importants pour les opérations d'addition et de soustraction:

.el {
  /*  */
  font-size: calc(3vw + 2px);

  /*  */
  font-size: calc(3vw+2px);

  /*  */
  font-size: calc(3vw - 2px);

  /*  */
  font-size: calc(3vw-2px);
}

Ici, il est tout à fait possible d'utiliser des nombres négatifs (par exemple, dans une construction comme calc(5vw — -5px)), mais c'est un exemple de situation dans laquelle les espaces sont non seulement nécessaires, mais également utiles en termes de clarté des expressions.

Tab Atkins m'a dit que la raison pour laquelle les opérateurs d'addition et de soustraction devraient être séparés par des espaces est, en fait, les particularités de l'analyse des expressions. Je ne peux pas dire que j'ai bien compris cela, mais, par exemple, l'analyseur traite l'expression 2px-3pxcomme un nombre 2avec une unité de mesurepx-3px. Et personne n'aura besoin d'une unité de mesure aussi étrange. L'analyse des expressions avec l'opérateur d'addition a ses propres problèmes. Par exemple, un analyseur peut prendre cet opérateur dans le cadre de la syntaxe utilisée pour décrire les nombres. Je pensais qu'un espace était nécessaire pour gérer correctement la syntaxe des propriétés personnalisées ( --), mais ce n'est pas le cas.

Lors de la multiplication et de la division des espaces autour des opérateurs, il n'est pas nécessaire. Mais je crois que vous pouvez recommander d'utiliser des espaces avec ces opérateurs afin d'augmenter la lisibilité du code, et afin de ne pas oublier les espaces et lors de la saisie d'expressions utilisant l'addition et la soustraction.

Les espaces qui séparent les crochets calc()d'une expression ne jouent aucun rôle. L'expression, si vous le souhaitez, peut même être sélectionnée en passant à une nouvelle ligne:

.el {
  /*  */
  width: calc(
    100%     /   3
  );
}

Certes, vous devez être prudent ici. Il calcne doit y avoir aucun espace entre le nom de la fonction ( ) et le premier crochet ouvrant:

.el {
  /*  */
  width: calc (100% / 3);
}

Constructions imbriquées: calc (calc ())


Lorsque vous travaillez avec une fonction calc(), vous pouvez utiliser des constructions imbriquées, mais ce n'est pas vraiment nécessaire. Cela revient à utiliser des crochets sans calc:

.el {
  width: calc(
    calc(100% / 3)
    -
    calc(1rem * 2)
  );
}

Cela n'a aucun sens de construire des constructions imbriquées à partir de fonctions calc(), car celles-ci peuvent être réécrites en utilisant uniquement des crochets:

.el {
  width: calc(
   (100% / 3)
    -
   (1rem * 2)
  );
}

De plus, les parenthèses ne sont pas nécessaires dans cet exemple, car les règles de détermination de la priorité des opérateurs sont appliquées lors du calcul des expressions présentées ici. La division et la multiplication sont effectuées avant l'addition et la soustraction. En conséquence, le code peut être réécrit comme ceci:

.el {
  width: calc(100% / 3 - 1rem * 2);
}

Mais dans le cas où il semble que les crochets supplémentaires rendent le code plus clair, ils peuvent être utilisés. De plus, si sans parenthèses, basée uniquement sur la priorité des opérateurs, l'expression sera calculée incorrectement, alors une telle expression a besoin de parenthèses:

.el {
  /* ,   , */
  width: calc(100% + 2rem / 2);

  /*     ,    */
  width: calc((100% + 2rem) / 2);
}

Propriétés CSS personnalisées et calc ()


Nous avons déjà découvert l'une des grandes fonctionnalités calc(), les calculs qui utilisent des valeurs avec différentes unités. Une autre caractéristique intéressante de cette fonction est la façon dont elle peut être appliquée avec des propriétés CSS personnalisées. Des propriétés personnalisées peuvent se voir attribuer des valeurs pouvant être utilisées dans les calculs:

html {
  --spacing: 10px;
}

.module {
  padding: calc(var(--spacing) * 2);
}

Je suis sûr qu'il est facile d'imaginer un ensemble de styles CSS dans lequel de nombreux paramètres sont définis au même endroit en définissant des valeurs pour les propriétés CSS personnalisées. Ces valeurs seront ensuite utilisées dans tout le code CSS.

De plus, les propriétés personnalisées peuvent se référer les unes aux autres (notez qu'elle n'est calc()pas utilisée ici). Les valeurs obtenues peuvent être utilisées pour définir les valeurs d'autres propriétés CSS (mais ici, vous calc()ne pouvez pas vous en passer).

html {
  --spacing: 10px;
  --spacing-L: var(--spacing) * 2;
  --spacing-XL: var(--spacing) * 3;
}

.module[data-spacing="XL"] {
  padding: calc(var(--spacing-XL));
}

Pour certains, cela peut ne pas sembler très pratique, car lorsque vous accédez à une propriété personnalisée, vous devez vous en souvenir calc(). Mais je trouve cela intéressant en termes de lisibilité du code.

La source des propriétés personnalisées peut être du code HTML. Parfois, cela peut être extrêmement utile. Par exemple, dans Splitting.js, des index sont ajoutés aux mots et symboles.

<div style="--index: 1;"> ... </div>
<div style="--index: 2;"> ... </div>
<div style="--index: 3;"> ... </div>
div {
  /*     HTML (   ) */
  animation-delay: calc(var(--index, 1) * 0.2s);
}

Affectation d'unités à des propriétés personnalisées après avoir déclaré ces propriétés


Supposons que nous soyons dans une situation où il est logique d'écrire un nombre sans unités de mesure dans une propriété personnalisée, ou dans une situation où un tel nombre sera pratique, avant utilisation réelle, d'une manière ou d'une autre, convertir sans utiliser d'unités. Dans de tels cas, une propriété personnalisée peut se voir attribuer une valeur sans spécifier d'unités. Lorsqu'il sera nécessaire de convertir ce nombre en un nouveau, exprimé en certaines unités de mesure, il pourra être multiplié en 1indiquant les unités de mesure souhaitées:

html {
  --importantNumber: 2;
}

.el {
  /*    ,  ,        */
  padding: calc(var(--importantNumber) * 1rem);
}

Travailler avec des fleurs


Lors de la description des couleurs à l'aide de formats tels que RVB et HSL, des nombres sont utilisés. Ces chiffres peuvent être travaillés calc(). Par exemple, vous pouvez définir certaines valeurs HSL de base, puis les modifier selon vos besoins ( voici un exemple):

html {
  --H: 100;
  --S: 100%;
  --L: 50%;
}

.el {
  background: hsl(
    calc(var(--H) + 20),
    calc(var(--S) - 10%),
    calc(var(--L) + 30%)
  )
}

Vous ne pouvez pas combiner calc () et attr ()


La fonction CSS attr()peut sembler assez attrayante. Et la vérité: vous prenez la valeur d'attribut de HTML, puis vous l'utilisez. Mais…

<div data-color="red">...</div>
div {
  /*    */
  color: attr(data-color);
}

Malheureusement, cette fonction ne comprend pas les «types» de valeurs. Par conséquent, il attr()ne convient que pour travailler avec des chaînes et pour définir des propriétés CSS à l'aide de celui-ci content. Autrement dit, une telle conception s'avère très efficace:

div::before {
  content: attr(data-color);
}

Je l'ai dit ici parce que quelqu'un pourrait vouloir extraire un attr()certain nombre du code HTML et l'utiliser dans les calculs:

<div class="grid" data-columns="7" data-gap="2">...</div>
.grid {
  display: grid;

  /*         */
  grid-template-columns: repeat(attr(data-columns), 1fr);
  grid-gap: calc(1rem * attr(data-gap));
}

Cependant, la bonne chose est que cela n'a pas vraiment d'importance, car les propriétés personnalisées en HTML sont parfaites pour résoudre de tels problèmes:

<div class="grid" style="--columns: 7; --gap: 2rem;">...</div>
.grid {
  display: grid;

  /* ! */
  grid-template-columns: repeat(var(--columns), 1fr);
  grid-gap: calc(var(--gap));
}

Outils du navigateur


Les outils de développement de navigateur affichent généralement des expressions avec les calc()mêmes que celles décrites dans le code source CSS.


Outils de développement Firefox, onglet Règles

Si vous avez besoin de savoir ce que la fonction va calculercalc(), vous pouvez vous référer à l'ongletComputed(cet onglet se trouve dans les outils de développement de tous les navigateurs que je connais). Là, la valeur calculée sera affichéecalc().


Onglet Calculé des outils de développement Chrome

Prise en charge du navigateur


Ici , vous pouvez en savoir plus sur calc()navigateur support pour la fonction . Si nous parlons de navigateurs modernes, le niveau de support calc()est supérieur à 97%. Si vous devez prendre en charge des navigateurs assez anciens (comme IE 8 ou Firefox 3.6), ils le font généralement: ajoutez calc()la même propriété avant la propriété pour calculer la valeur qui est définie dans un format que les anciens navigateurs comprennent:

.el {
  width: 92%; /*   */
  width: calc(100% - 2rem);
}

La fonction calc()a de nombreux problèmes connus, mais seuls les anciens navigateurs en souffrent. Sur Caniuse peut trouver une description de 13 de ces problèmes. En voici quelques uns:

  • Le navigateur Firefox sous la version 59 ne prend pas en charge calc()les fonctions utilisées pour définir la couleur. Par exemple: color: hsl(calc(60 * 2), 100%, 50%).
  • IE 9-11 ne rendra pas l'ombre spécifiée par la propriété box-shadowsi elle est utilisée pour déterminer l'une des valeurs calc().
  • Ni IE 9-11 ni Edge ne prennent en charge la conception de la vue width: calc()lorsqu'ils sont appliqués aux cellules du tableau.

Exemples de vie


J'ai demandé à plusieurs développeurs CSS quand ils avaient utilisé la fonction pour la dernière fois calc(). Leurs réponses étaient une petite sélection qui aidera tout le monde à apprendre comment les autres programmeurs utilisent calc()dans leur travail quotidien.

  • Je calc()pour créer la classe d'assistance pour les domaines de la gestion: .full-bleed { width: 100vw; margin-left: calc(50% — 50vw); }. Je peux dire que c'est calc()dans mon top 3 des fonctionnalités CSS les plus utiles.
  • J'ai utilisé cette fonction pour allouer de l'espace pour un "pied de page" fixe de la page.
  • calc() . , font-size, . font-sizecalc() line-height. ( , calc() , , , rem em. , ).
  • , . . — : .margin { width: calc( (100vw — var(--content-width)) / 2); }.
  • calc() - , . : .drop-cap { --drop-cap-lines: 3; font-size: calc(1em * var(--drop-cap-lines) * var(--body-line-height)); }.
  • , .
  • , padding vw/vh.
  • Je demande calc()à contourner les restrictions background-position. Cela est particulièrement vrai pour les restrictions sur l'ajustement des positions de changement de couleur dans les dégradés. Par exemple, cela peut être décrit comme suit: "positionnez la position du changement de couleur, sans atteindre 0.75emle bas".



Chers lecteurs! Utilisez-vous CSS calc()?

All Articles