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); }
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); }
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; }
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>
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; }
...
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); }
<a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">Link Example</a>
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.
Example: Grayscale link
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; }
<a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">Link Example</a>
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.
Example: Custom links
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; }
<a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">Link Example</a> Link Example
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); }
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); }
<h2 id="A-Tiny-Webpage"> A Tiny Webpage</h2> <p>This is the tiniest webpage. It has three noteworthy features:</p>
- 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)); }
<div> <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/?x-oss-process=image/resize,p_40" class="lazy" alt="Bill Murray"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468445958706.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Nic Cage"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468446478697.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Nic Cage gray"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/?x-oss-process=image/resize,p_40" class="lazy" alt="Bill Murray gray"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468446644293.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Nic Cage crazy"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174468446996811.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Nic Cage gif"> </div>
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>
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!

With Astro, we can generate most of our site during our build, but have a small bit of server-side code that can handle search functionality using something like Fuse.js. In this demo, we’ll use Fuse to search through a set of personal “bookmarks” th

I wanted to implement a notification message in one of my projects, similar to what you’d see in Google Docs while a document is saving. In other words, a

Some months ago I was on Hacker News (as one does) and I ran across a (now deleted) article about not using if statements. If you’re new to this idea (like I

Since the early days of science fiction, we have fantasized about machines that talk to us. Today it is commonplace. Even so, the technology for making

I remember when Gutenberg was released into core, because I was at WordCamp US that day. A number of months have gone by now, so I imagine more and more of us

The idea behind most of web applications is to fetch data from the database and present it to the user in the best possible way. When we deal with data there

Let's do a little step-by-step of a situation where you can't quite do what seems to make sense, but you can still get it done with CSS trickery. In this

You can make a garden variety anchor link () open up a new email. Let's take a little journey into this feature. It's pretty easy to use, but as with anything


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

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

Hot Article

Hot Tools

SublimeText3 English version
Recommended: Win version, supports code prompts!

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Mac version
God-level code editing software (SublimeText3)

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Atom editor mac version download
The most popular open source editor