网页
综合
更新时间 2024-10-22 13:57:40
@property | CSS-Tricks
自动蜘蛛
css-tricks.com
正文约 6000 字
The CSS @property at-rule lets you register a custom property. It can be used as an everyday CSS variable inside a var() function or style queries, the difference being that we can better define and validate the type of value the property will hold, its initial value, and whether the property inherits by default.
So, in a way, @property is sort of like defining your very own CSS property just like display, padding, margin, etc. We get to name it (as a dashed-ident, e.g. --my-property), tell the browser how we want it formatted (should it be a number, color, URL, integer… or something else?), what it equals by default as its initial value, and whether child elements can inherit it from their parents or ancestors.
It’s a powerful feature in our CSS toolbox. We’ll look at the syntax, what sort of things we can register as custom properties, and then a bunch of examples of how it can be used.
We can even give a custom property multiple syntaxes at a time to combine things together. We have three ways to chain those types together:
To register a variable, we write the @property at-rule followed by the custom property’s name as a <dashed-ident>.
Inside, we declare three descriptors: syntax, initial-value and inherits.
At its simplest, a variable registered with the @property at-rule can be used just like any other CSS variable. For example, to define basic values that will be used across your stylesheet (color schemes, spacing, default sizes, breakpoints, etc.):
That’s a very basic overview of how to register and use a CSS custom property. Things get way more interesting when we explore what @property can do because it’s more than just styling things with placeholder values.
CSS properties gained support around 2016. To use them at their most basic, we define a custom property starting with two dashes (--property) and then use it inside a var(--property):
Variables defined this way cascade down to their child elements. So, if we want our use a certain variable globally in a way that we can declare it anywhere, we “scope” it to the highest level selector in CSS, the :root element:
This seems like the perfect solution for DRY code in CSS, and while it is a great approach, it still comes with limitations. The main problem is that custom properties can contain anything. It doesn’t have to be a single value, like 20px. It could very well be a unitless number, like 20. That means CSS doesn’t know how to interpret a variable until it is assigned to a property it recognizes. For example, per spec, the following variable is valid:
But CSS considers it a valid statement, all the way up until it is assigned to a property at which time it is evaluated and determined to be invalid.
As a result, CSS can’t animate between a variable with an initial-value of, say, 0deg and an updated value of 360deg. So, even though we are using a valid CSS length unit (deg), CSS doesn’t actually evaluate it until after it is declared.
In this example, CSS doesn’t know that the --turn variable is formatted in deg units until it is declared in the animation @keyframes. That means it doesn’t use 0deg as a starting point for the animation, as it only evaluates the declared 360deg.
This is where @property comes into play. Using @property, we can define the same value but let CSS know it’s formatted in deg units (considered an <angle>).
Now CSS has more information to understand what the variable is all about. We’re telling it that the --turn variable is a custom property formatted as an angle unit that evaluates to 0deg by default and can be passed to child elements. The exact same animation that didn’t work earlier now works like a charm:
The syntax descriptor is handy for other things besides evaluating custom properties in advance. We’re telling CSS what type of unit it is — and if we give that unit a mismatched initial-value
Using the syntax descriptor, we can let CSS know the type of value our custom property will hold. This isn’t just a hint for CSS, but rather an enforcement since trying to assign any other value will invalidate the property.
In that example, we’ve registered a <color> but supplied it with a <percentange> for the initial-value. Whoops!
We can fix that if we reassign the value inside an element.
But notice what’s happening. We haven’t changed the value from the @property at-rule, but have registered a new plain, ol’ CSS variable instead. It effectively overrides @property and we lose all of the goodness that comes with it, like evaluating values in advance.
Remember earlier when we said that syntax can combine multiple types at once? If we add more types to the mix, we can be more permissive about the type of values @property supports. For example, we can create a property that accepts percentages (<percentage>), lengths (<length>) and a list of colors (<color>+) if we concatenate them using the “or” (|) combinator.
OK, now we’re allowed to declare the property as a percentage… or a length… or a color. And we can still interpolate between the initial and final values even if the types do not match:
One of the things we can define inside the @property at-rule is whether the value should cascade down (i.e., be inherited by) other elements using the inherits descriptor. This is very, very cool because we’re influencing how the CSS Cascade treats the property! Do we allow parents to send it down to child, or keep it isolated so that it doesn’t leak out to other elements? We’re masters of our own cascade!
Imagine we’re working with the following markup:
We can define a common custom property for the text color and set it to a value of blue inside a ruleset that selects the section element:
We’ve only registered this as a regular CSS variable rather than running it through @property. And since custom properties that are defined this way are inheritable by default, the --text-color variable sets blue on the children contained in the <section> parent (which is <h1> and <q> in the markup). That’s because we’re passi
本页为82搜索生成的网页快照,内容来自站内索引;演示数据的原文链接仅作示例。