Table of Contents
A brief description of browser support
Pattern 1: Variable
Mode 2: Default
Mode 3: Cascading values
User-based topics
Readability Theme Coverage
Pattern 4: Scope Rule Set
Example: Grayscale link
Example: Custom links
Mode 5: Mixin
Example: Baseline grid foundation
A Tiny Webpage
Pattern 6: Inline properties
Home Web Front-end CSS Tutorial Patterns for Practical CSS Custom Properties Use

Patterns for Practical CSS Custom Properties Use

Apr 15, 2025 am 10:34 AM

Patterns for Practical CSS Custom Properties Use

CSS Variables has reached a point where it can be used in production environments, and I have been exploring its powerful features. I've tried a variety of ways to use it and hope you'll be excited about them as well as I do. They are very practical and powerful!

I found that the use of CSS variables can often be summarized into several categories . Of course, you can use CSS variables as you like, but thinking about them from these different categories may help you understand their different ways of using them.

  • Variables: Basic usage, such as setting brand colors and using them where needed.
  • Default value: For example, set a default border-radius, which can be overwritten afterwards.
  • Cascading values: Based on specific usage clues, such as user preferences.
  • Scope rule set: Deliberate style variations of individual elements such as links and buttons.
  • Mixin: Rule set designed to apply its values ​​to new contexts.
  • Inline properties: The value passed in from the inline style of HTML.

The example we will see is a simplified and concentrated pattern from Cutestrap, the CSS framework I created and maintained.

A brief description of browser support

I often hear two common questions when it comes to custom properties. The first one is about browser support. Which browsers support them? What fallback schemes do we need to use in browsers that do not support them?

The global market share that supports the content described in this article is 85%. Still, it's worth cross-reference to caniuse to determine how much progressive enhancement means and where to use it in your project based on your user base.

The second question is always about how to use custom properties. So let's get a deeper look at its usage!

Pattern 1: Variable

First, we will set a custom attribute variable for the brand color and use it on the SVG element. We will also use a fallback scheme to overwrite users of older browsers.

 html {
  --brand-color: hsl(230, 80%, 60%);
}

.logo {
  fill: pink; /* backup plan*/
  fill: var(--brand-color);
}
Copy after login

Here, we declare a variable named --brand-color in the html rule set. The variable is defined on the always-existing element, so it will be cascading to each element that uses it. In short, we can use this variable in the .logo rule set.

We declared a pink fallback value for the older browser. In the second fill declaration, we pass --brand-color into the var() function, which returns the value we set for that custom property.

The pattern is roughly like this: define the variable (--variable-name) and then use it on the element (var(--variable-name)).

Mode 2: Default

The var() function we used in the first example can also provide default values ​​in case the custom properties it attempts to access are not set.

For example, suppose we provide rounded borders for the button. We can create a variable—we call it --roundness—but we won't define it as before. Instead, we will assign a default value when using variables.

 .button {
  /* --roundness: 2px; */
  border-radius: var(--roundness, 10px);
}
Copy after login

One use case for using default values ​​without custom properties defined is that your project is still in design, but your functionality expires today . If the design changes, this makes it much easier to update the values ​​later.

So you can give the button a nice default value that satisfies your deadline, and when --roundness is finally set to a global custom property, your button will get that update for free without returning to it.

You can edit and uncomment the above code on CodePen to see how the button looks after setting --roundness!

Mode 3: Cascading values

Now that we have the basics, let’s start building the future we deserve. I really miss AIM and MySpace expressing their personality by allowing users to use custom text and background colors on their profile.

Let's bring it back and create a school message board where every student can set their own font, background color and text color for the messages they post.

User-based topics

We are basically having students create custom themes. We will set the topic configuration in the data-attribute rule set so that any child elements that use these topics (in this case the .message element) can access these custom attributes.

 .message {
  background-color: var(--student-background, https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15bfff);
  color: var(--student-color, https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b000);
  font-family: var(--student-font, "Times New Roman", serif);
  margin-bottom: 10px;
  padding: 10px;
}

[data-student-theme="rachel"] {
  --student-background: rgb(43, 25, 61);
  --student-color: rgb(252, 249, 249);
  --student-font: Arial, sans-serif;
}

[data-student-theme="jen"] {
  --student-background: https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15bd55349;
  --student-color: https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b000;
  --student-font: Avenir, Helvetica, sans-serif;
}

[data-student-theme="tyler"] {
  --student-background: blue;
  --student-color: yellow;
  --student-font: "Comic Sans MS", "Comic Sans", cursive;
}
Copy after login

Here is the marker:

<div data-student-theme="chris">
    <p>Chris: I've spoken at events and given workshops all over the world at conferences.</p>
  </div>
  <div data-student-theme="rachel">
    <p>Rachel: I prefer email over other forms of communication.</p>
  </div>
  <div data-student-theme="jen">
    <p>Jen: This is why I immediately set up my new team with Slack for real-time chat.</p>
  </div>
  <div data-student-theme="tyler">
    <p>Tyler: I miss AIM and MySpace, but this message board is OK.</p>
  </div>
Copy after login

We set up all student topics for our student topic ruleset using the [data-student-theme] selector. If you set custom properties for the background, color, and font for this student, these custom properties will be applied to our .message rule set because .message is a child element of a div containing data-attribute, which in turn contains the custom attribute value to use. Otherwise, the default values ​​we provide will be used.

Readability Theme Coverage

While it’s fun and cool to control custom styles for users, the styles that users choose are not always accessible and need to be considered for contrast, color vision flaws, or anyone who likes not bleeding from their eyes while reading. Remember the GeoCities era?

Let's add a class that provides a clearer look and feel and set it on the parent element to overwrite any student topics when the class exists.

 .readable-theme [data-student-theme] {
  --student-background: hsl(50, 50%, 90%);
  --student-color: hsl(200, 50%, 10%);
  --student-font: Verdana, Geneva, sans-serif;
}
Copy after login
 ...
Copy after login

We utilize cascades to cover student topics by setting higher specificity so that backgrounds, colors, and fonts are within range and will be applied to each .message rule set.

Pattern 4: Scope Rule Set

Speaking of scopes, we can scope custom properties and use them to simplify what was originally boilerplate CSS. For example, we can define variables for different link states.

 a {
  --link: hsl(230, 60%, 50%);
  --link-visited: hsl(290, 60%, 50%);
  --link-hover: hsl(230, 80%, 60%);
  --link-active: hsl(350, 60%, 50%);
}

a:link {
  color: var(--link);
}

a: visited {
  color: var(--link-visited);
}

a:hover {
  color: var(--link-hover);
}

a:active {
  color: var(--link-active);
}
Copy after login
 <a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">Link Example</a>
Copy after login
Copy after login

Now we're already<a></a> Custom properties are written globally on the elements and used them on our link state, we don't need to write them again. The scope of these properties is limited to us<a></a> The ruleset of the elements, so they are only set on the anchor tag and its child elements. This allows us not to pollute the global namespace.

Going forward, we can control the links we just created by changing the custom properties of different use cases. For example, let's create a gray link.

 .grayscale {
  --link: LightSlateGrey;
  --link-visited: Silver;
  --link-hover: DimGray;
  --link-active: LightSteelBlue;
}
Copy after login
 <a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">Link Example</a>
Copy after login
Copy after login

We declare a .grayscale rule set with colors for different link states. Since the selector for this rule set is more specific than the default, these variable values ​​will be used and then applied to the pseudo-class rule set of the linked state, rather than in<a></a> Content defined on the element.

If setting four custom properties feels too much work, what if we only set one hue value? This may make management much easier.

 .custom-link {
  --hue: 30;
  --link: hsl(var(--hue), 60%, 50%);
  --link-visited: hsl(calc(var(--hue) 60), 60%, 50%);
  --link-hover: hsl(var(--hue), 80%, 60%);
  --link-active: hsl(calc(var(--hue) 120), 60%, 50%);
}

.danger {
  --hue: 350;
}
Copy after login
 <a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">Link Example</a>
Link Example
Copy after login

By introducing a variable of hue value and applying it to the HSL color value in other variables, we can update all four link states with just one value.

Computing is very powerful in combination with custom properties because they can make your style more expressive without having to put in more effort. Check out this technique by Josh Bader, who uses a similar approach to enforce accessible color contrast of buttons.

Mode 5: Mixin

Regarding custom properties, Mixin is a function declared as a custom property value. The parameters of Mixin are other custom properties that, when these properties change, recalculate the Mixin, which in turn updates the style.

The custom link example we just saw is actually a Mixin. We can set the value of --hue and then all four link states will be recalculated accordingly.

Example: Baseline grid foundation

Let's learn more about Mixin by creating a baseline mesh that helps with vertical rhythms. In this way, our content achieves a pleasant rhythm by using consistent spacing.

 .baseline,
.baseline * {
  --rhythm: 2rem;
  --line-height: var(--sub-rhythm, var(--rhythm));
  --line-height-ratio: 1.4;
  --font-size: calc(var(--line-height) / var(--line-height-ratio));
}

.baseline {
  font-size: var(--font-size);
  line-height: var(--line-height);
}
Copy after login

We apply the ruleset of the baseline mesh to the .baseline class and any descendants.

  • --rhythm: This is the cornerstone of our baseline. Updating it will affect all other properties.
  • --line-height: Set to --rhythm by default, because --sub-rhythm is not set here.
  • --sub-rhythm: This allows us to override --line-height -- followed by --font-size -- while maintaining the overall baseline grid.
  • --line-height-ratio: This helps enforce appropriate spacing between text lines.
  • --font-size: This is calculated by dividing --line-height by --line-height-ratio.

We also set font-size and line-height in the .baseline rule set to use --font-size and --line-height from the baseline grid. In short, whenever the rhythm changes, line height and font size change accordingly, while maintaining a readable experience.

OK, let's use the baseline.

Let's create a small webpage. We will use our --rhythm custom property to set the spacing between all elements.

 .baseline h2,
.baseline p,
.baseline ul {
  padding: 0 var(--rhythm);
  margin: 0 0 var(--rhythm);
}

.baseline p {
  --line-height-ratio: 1.2;
}

.baseline h2 {
  --sub-rhythm: calc(3 * var(--rhythm));
  --line-height-ratio: 1;
}

.baseline p,
.baseline h2 {
  font-size: var(--font-size);
  line-height: var(--line-height);
}

.baseline ul {
  margin-left: var(--rhythm);
}
Copy after login
<h2 id="A-Tiny-Webpage"> A Tiny Webpage</h2>
  <p>This is the tiniest webpage. It has three noteworthy features:</p>
  
Copy after login
  • Tiny
  • Exemplar
  • Identifies as Hufflepuff

We basically use two Mixins here: --line-height and --font-size. We need to set the attributes font-size and line-height to their custom attribute counterparts to set the title and paragraph. Mixin has been recalculated in these rule sets, but they need to be set before the updated styles are applied to them.

It is important to note that when applying Mixin using wildcard selectors, you may not want to use custom attribute values ​​in the rule set itself. It makes these styles more specific than any other inheritance brought by the cascade, making it difficult to overwrite them without using !important.

Pattern 6: Inline properties

We can also declare custom properties inline. Let's build a lightweight grid system to demonstrate.

 .grid {
  --columns: auto-fit;

  display: grid;
  gap: 10px;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
}
Copy after login
<div>
  <img src="/static/imghw/default1.png" data-src="https://img.php.cn/" class="lazy" alt="Bill Murray"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468445958706.jpg" class="lazy" alt="Nic Cage"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468446478697.jpg" class="lazy" alt="Nic Cage gray"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/" class="lazy" alt="Bill Murray gray"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468446644293.jpg" class="lazy" alt="Nic Cage crazy"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468446996811.jpg" class="lazy" alt="Nic Cage gif">
</div>
Copy after login

By default, the grid has columns of equal size that will be automatically arranged into single rows.

To control the number of columns, we can set the --columns custom property inline on the grid element.

<div style="--columns: 3;">
  ...
</div>
Copy after login

We just looked at six different custom attribute use cases – at least the ones I use for the most. Even if you already know and have been using custom properties, you want to see these usages to give you a better idea of ​​when and where to use them effectively.

Have you used different types of patterns using custom properties? Please share them in the comments and link some demos – I would love to see them!

If you are not familiar with custom properties and are looking for promotion, try using the example we covered here, but add media queries. You will see how adaptable these properties are and how many interesting opportunities are when you have the power to change values ​​at any time.

In addition, there are a large number of other excellent resources on CSS-Tricks that can improve your custom attribute skills in the Custom Attribute Guide.

The above is the detailed content of Patterns for Practical CSS Custom Properties Use. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Vue 3 Vue 3 Apr 02, 2025 pm 06:32 PM

It&#039;s out! Congrats to the Vue team for getting it done, I know it was a massive effort and a long time coming. All new docs, as well.

Building an Ethereum app using Redwood.js and Fauna Building an Ethereum app using Redwood.js and Fauna Mar 28, 2025 am 09:18 AM

With the recent climb of Bitcoin’s price over 20k $USD, and to it recently breaking 30k, I thought it’s worth taking a deep dive back into creating Ethereum

Can you get valid CSS property values from the browser? Can you get valid CSS property values from the browser? Apr 02, 2025 pm 06:17 PM

I had someone write in with this very legit question. Lea just blogged about how you can get valid CSS properties themselves from the browser. That&#039;s like this.

Stacked Cards with Sticky Positioning and a Dash of Sass Stacked Cards with Sticky Positioning and a Dash of Sass Apr 03, 2025 am 10:30 AM

The other day, I spotted this particularly lovely bit from Corey Ginnivan’s website where a collection of cards stack on top of one another as you scroll.

A bit on ci/cd A bit on ci/cd Apr 02, 2025 pm 06:21 PM

I&#039;d say "website" fits better than "mobile app" but I like this framing from Max Lynch:

Comparing Browsers for Responsive Design Comparing Browsers for Responsive Design Apr 02, 2025 pm 06:25 PM

There are a number of these desktop apps where the goal is showing your site at different dimensions all at the same time. So you can, for example, be writing

Using Markdown and Localization in the WordPress Block Editor Using Markdown and Localization in the WordPress Block Editor Apr 02, 2025 am 04:27 AM

If we need to show documentation to the user directly in the WordPress editor, what is the best way to do it?

Why are the purple slashed areas in the Flex layout mistakenly considered 'overflow space'? Why are the purple slashed areas in the Flex layout mistakenly considered 'overflow space'? Apr 05, 2025 pm 05:51 PM

Questions about purple slash areas in Flex layouts When using Flex layouts, you may encounter some confusing phenomena, such as in the developer tools (d...

See all articles