Maison  >  Article  >  interface Web  >  Les détails surprenants des variables CSS - Utilisation de var() et d'exemples sympas

Les détails surprenants des variables CSS - Utilisation de var() et d'exemples sympas

Barbara Streisand
Barbara Streisandoriginal
2024-11-15 05:49:02523parcourir

Voici la seconde moitié de mon article sur les variables CSS, la première moitié est ici.
Dans cet article, nous examinerons les détails de var(). Et deux exemples sympas :

  • Animation utilisant des variables CSS
  • Basculement du mode sombre CSS pur avec détection des paramètres du système

The Surprising Details of CSS Variables - Using var() and Cool Examples

Utiliser var()

Le var() accède aux valeurs des propriétés personnalisées (variables CSS). Sa syntaxe est la suivante :

var( <custom-property-name>, <fallback-value>? )

Règles de base

  1. Le premier paramètre doit être une variable CSS : Les valeurs directes, telles que var(20px), entraîneront une erreur, car var() n'accepte que les noms de propriétés personnalisés.

  2. var() ne peut pas remplacer les noms de propriété : En d'autres termes, vous ne pouvez pas écrire quelque chose comme var(--prop-name): 20px; car var() est limité à une utilisation dans les valeurs de propriété uniquement.

.foo {
  margin: var(20px); /* Error, 20px is not a CSS variable */

  --prop-name: margin-top;
  var(--prop-name): 20px; /* Error, cannot use var() this way */
}

Comportements détaillés

  1. var(--b, fallback_value) Fallbacks : Le deuxième paramètre agit comme une valeur de secours, utilisée lorsque --b n'est pas valide.

  2. var(--c,) Syntaxe avec une valeur de secours vide : Si la valeur de secours est laissée vide, la syntaxe reste valide et prendra par défaut une valeur vide si --c n'est pas valide .

  3. Virgules multiples : Dans var(--d, var(--e), var(--f), var(--g)), tout ce qui suit la première virgule est traité comme une solution de secours, donc si --d n'est pas valide, l'expression var() évalue var(--e), var(--f), var(--g) comme une solution de secours, pour déterminer le résultat.

  4. var() comme jeton CSS complet : La fonction agit comme un jeton CSS complet, comme le ferait 20px. Par conséquent, var(--size)var(--unit) ne créera pas 20px et est considéré comme invalide.

  5. Utiliser initial avec des variables CSS : Attribuer initial à une variable CSS signifie qu'elle n'est pas valide. Pour afficher initial comme valeur, il faut le placer en repli.

  6. url() et var() Utilisation : Puisque url() est traité comme un jeton CSS complet, vous devez définir l'url() complète dans la variable.

:root {
  /* 1. */
  margin: var(--b, 20px); /* Uses 20px if --b is invalid */

  /* 2. */
  padding: var(--c,) 20px; /* Falls back to 20px if --c is invalid */

  /* 3. */
  font-family: var(--fonts, "lucida grande", tahoma, Arial); /* Uses fallback font stack if --fonts is invalid */

  /* 4. */
  --text-size: 12;
  --text-unit: px;
  font-size: var(--text-size)var(--text-unit); /* Invalid, as it does not resolve to 12px */

  /* 5. */
  --initialized: initial;
  background: var(--initialized, initial); /* Results in background: initial */

  /* 6. */
  --invalid-url: "https://useme.medium.com";
  background: url(var(--invalid-url)); /* Invalid, as url() cannot parse var() */

  --valid-url: url(https://useme.medium.com);
  background: var(--valid-url); /* Correct usage */
}

Résolution et portée variables

Les variables CSS, comme les autres propriétés CSS, suivent les règles spécifiques au CSS en matière de portée et de spécificité. Comprendre comment ces facteurs affectent les variables CSS permet un contrôle plus précis.

Variables globales et étendues :
Les variables définies dans :root sont appliquées globalement, tandis que celles définies dans les sélecteurs ont une portée plus limitée.

   :root {
     --main-color: blue; /* Globally applied */
   }

   .container {
     --main-color: green; /* Scoped, applies only within .container */
   }

Priorité par spécificité :
Une spécificité plus élevée remplacera une spécificité plus faible pour les variables CSS.

   :root {
     --main-color: blue;
   }

   .section {
     --main-color: green; /* Overrides :root definition */
   }

   .section p {
     color: var(--main-color); /* Shows green */
   }

   p {
     color: var(--main-color); /* Shows blue */
   }
   <div>



<p><strong>Calculating Values Based on Specificity Order:</strong> <br>
Like CSS properties, variables are resolved based on specificity in ascending order.<br>
</p>

<pre class="brush:php;toolbar:false">   :root {
     --red: 255;
     --green: 255;
     --blue: 255;
     --background: rgb(var(--red), var(--green), var(--blue));
   }

   .box {
     --green: 0;
     background: var(--background); 
   }

Dans cet exemple, la couleur d'arrière-plan de .box reste blanche, car --background a été résolu en rgb(255, 255, 255) avant que .box ne soit redéfini --green : 0.

Reevaluating Variables with Pseudo-Classes:
Variables change based on pseudo-class states when defined at the same level.

   :root {
     --red: 255;
     --green: 255;
     --blue: 255;
   }

   .box {
     --background: rgb(var(--red), var(--green), var(--blue));
     background: var(--background);
   }

   .box:hover {
     --green: 0; /* Changes background color on hover */
   }

Next, let’s explore some advanced use cases for CSS variables:

Usage Example A: Animations

CSS variables cannot be directly animated because the browser cannot infer the data type. To resolve this, use @property to define the variable's type and initial value, enabling the browser to understand how to animate the variable.

@property --green {
  syntax: "<number>";
  initial-value: 255;
  inherits: false;
}

.section {
  padding: 5em;
  background: rgb(50, var(--green), 50);
  transition: --green 0.5s;
}

.section:hover {
    --green: 50;
}
<div>



<p>In this example, @property is used to declare --green as a <number> type with an initial value of 255. When hovering over .section, --green changes to 50, creating a smooth color transition effect.

<p>CodePen example</p>


<hr>

<h2>
  
  
  Usage Example B: Light/Dark Mode Toggle
</h2>

<p>If you want to implement theme switching for light and dark modes, it’s helpful to extract color values into variables that adjust automatically based on the prefers-color-scheme setting. Here’s how you can manage this using CSS variables.<br>
</p>

<pre class="brush:php;toolbar:false">:root {
  --background-color: #FBFBFB;
  --container-background-color: #EBEBEB;
  --headline-color: #0077EE;
  --text-color: #333333;
}

@media (prefers-color-scheme: dark) {
  :root {    
    --background-color: #121212;
    --container-background-color: #555555;
    --headline-color: #94B2E6;
    --text-color: #e0e0e0;
  }
}

Adding a Manual Toggle that Aligns with System Preferences

While the system setting controls the theme by default, we may want to give users the option to manually toggle between light and dark themes. To achieve this, we can add a checkbox to toggle the state. Ideally, when the checkbox is selected, it indicates dark mode, and when unselected, it represents light mode.

However, CSS cannot automatically detect system settings and change the checkbox state accordingly, especially in dark mode. To handle this limitation, we can use CSS variables and the :has() selector to control theme switching based on the checkbox state.

I wanted to try achieving this entirely with CSS, but since a user’s system may be set to either light or dark mode, CSS alone can’t automatically check the checkbox in dark mode.

If we can’t move the mountain, we’ll route the path. Here’s the workaround:

  • We’ll use CSS to create a toggle switch, where the visual “OFF” state represents light mode, and “ON” represents dark mode.

The Surprising Details of CSS Variables - Using var() and Cool Examples
The Surprising Details of CSS Variables - Using var() and Cool Examples

  • When system sets to light mode: When the checkbox is unselected, it corresponds to the “OFF” state (light mode). When selected, it corresponds to the “ON” state (dark mode).

  • When system sets to dark mode: Since the system preference is reversed, the visual state also inverts. When the checkbox is unselected, it corresponds to “ON” (dark mode). When selected, it corresponds to “OFF” (light mode).

To achieve this effect, we need two main elements:

First: Variables that Change Based on System Setting and Checkbox State

:root {
  --background-color: #FBFBFB;
  --container-background-color: #EBEBEB;
  --headline-color: #0077EE;
  --text-color: #333333;
}

:root:has(input[type="checkbox"]:checked) {
  --background-color: #121212;
  --container-background-color: #555555;
  --headline-color: #94B2E6;
  --text-color: #e0e0e0;
}

@media (prefers-color-scheme: dark) {
  :root {    
    --background-color: #121212;
    --container-background-color: #555555;
    --headline-color: #94B2E6;
    --text-color: #e0e0e0;
  }

  :root:has(input[type="checkbox"]:checked) {
    --background-color: #FBFBFB;
    --container-background-color: #EBEBEB;
    --headline-color: #0077EE;
    --text-color: #333333;
  }
}

Second: Toggle Behavior Based on System Settings for checked State and ON/OFF Representation

The light and dark mode CSS properties are reversed depending on the system setting.

/* Toggle Switch Styles */
.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

/* Hide the checkbox element to style a custom switch */
.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

/* Slider styling for the switch background */
.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--slider-bg, #ccc);
  transition: 0.4s;
  border-radius: 34px;
}

/* Slider knob styling */
.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: 0.4s;
  border-radius: 50%;
}

/* Dark mode styles: make the switch look "checked" by default */
@media (prefers-color-scheme: dark) {
  .slider {
    background-color: #94b2e6;
  }
  .slider:before {
    transform: translateX(26px); /* Move knob to the right */
  }

  /* Invert checked state in dark mode to look "unchecked" */
  input:checked + .slider {
    background-color: #ccc;
  }
  input:checked + .slider:before {
    transform: translateX(0); /* Move knob to the left */
  }
}

/* Light mode styles: make the switch look "unchecked" by default */
@media (prefers-color-scheme: light) {
  .slider {
    background-color: #ccc;
  }
  .slider:before {
    transform: translateX(0); /* Knob on the left */
  }

  /* Invert checked state in light mode to look "checked" */
  input:checked + .slider {
    background-color: #94b2e6;
  }
  input:checked + .slider:before {
    transform: translateX(26px); /* Move knob to the right */
  }
}

Simplifying Variable Setup with CSS Variable Tricks

Here we’ll use Space Toggle technique to simplify variable settings. Here’s the code, followed by an explanation of how it works:

:root {
  --ON: initial; /* Default state variable to use for switching colors */
  --OFF: ; /* Alternative state variable for switching colors */

  /* Set default color variables based on light mode */
  --light: var(--ON);
  --dark: var(--OFF);

  /* Define custom properties for colors used in light and dark modes */
  --background-color: var(--light, #fbfbfb) var(--dark, #121212);
  --container-background-color: var(--light, #ebebeb) var(--dark, #555555);
  --headline-color: var(--light, #0077ee) var(--dark, #94b2e6);
  --text-color: var(--light, #333333) var(--dark, #e0e0e0);
}

:root:has(input[type="checkbox"]:checked) {
  --light: var(--OFF);
  --dark: var(--ON);
}

The key here is in the line --background-color: var(--light, #fbfbfb) var(--dark, #121212);. Here, the background color depends on the values of --light and --dark, effectively simulating an if/else in the property.

How does it work? Initially, --light: var(--ON); and --ON: initial; make --ON an invalid state. Meanwhile, --OFF is set as an empty string. When applied to var(--light, #fbfbfb) var(--dark, #121212), the invalid --light variable will default to #fbfbfb, and the valid --dark variable (empty) allows --background-color to equal #fbfbfb.

All the other color variables follow the same logic, adjusting based on the state of --light and --dark. This way, each color variable only needs to be defined once.

Switching states becomes simple. If dark mode is active, use --light: var(--OFF); and --dark: var(--ON);. In light mode, reverse them. Though not immediately intuitive, this method is currently the most effective with CSS. If there are better solutions, they are worth exploring.

Complete example: CodePen Example


Summary

CSS continues to evolve, with CSS variables available in major browsers since 2016. New features like @property and :has() are expanding CSS variables’ flexibility even further. Combined with other new tools, CSS variables are becoming more powerful—for instance, they can now enhance scroll-driven animations to create visually dynamic effects. As a core element for storing state in CSS, much like variables in any programming language, a solid understanding of CSS variables will prove invaluable for more sophisticated styling and design down the road.


References

  • https://stackoverflow.com/questions/42330075/is-there-a-way-to-interpolate-css-variables-with-url/42331003#42331003
  • https://kizu.dev/cyclic-toggles/#was-this-always-possible
  • https://dev.to/afif/what-no-one-told-you-about-css-variables-553o
  • https://hackernoon.com/cool-css-variable-tricks-to-try-uyu35e9
  • https://lea.verou.me/blog/2020/10/the-var-space-hack-to-toggle-multiple-values-with-one-custom-property/

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn