css 变量
Most programming languages have support for variables. But sadly, CSS has lacked support for native variables from the very beginning.
大多数编程语言都支持变量。 但是可悲的是,CSS从一开始就缺乏对本机变量的支持。
You write CSS? Then no variables for you. Well, except if you were using a preprocessor like Sass.
你写CSS吗? 然后,没有适合您的变量。 好吧,除非您使用的是像Sass这样的预处理器。
Preprocessors like Sass sell the use of variables as a big add-on. A reason to try them. And you know what? It’s a pretty darn good reason.
像Sass这样的预处理器将变量的使用作为重要的附件出售。 尝试它们的原因。 你知道吗? 这是一个很好的理由。
Well the web is moving fast. And I’m glad to report that CSS now finally supports variables.
好吧,网络发展很快。 我很高兴地报告CSS现在终于支持变量了 。
While preprocessors support a lot more features, the addition of CSS variables is a good one. This moves the web even closer to the future.
尽管预处理器支持更多功能,但是添加CSS变量是一个很好的选择。 这使网络更加接近未来。
In this guide, I’ll show you how variables work natively in CSS, and how you can use them to make your life a lot easier.
在本指南中,我将向您展示变量如何在CSS中本地工作,以及如何使用它们使您的生活变得更加轻松。
您将学到什么 (What you’ll Learn)
I’ll first walk you through the basics of CSS Variables. I believe any decent attempt at understanding CSS Variables must begin here.
我将首先向您介绍CSS变量的基础知识。 我相信任何了解CSS变量的正当尝试都必须从这里开始。
Learning the fundamentals is cool. What’s even cooler is applying these fundamentals to build real-world apps.
学习基础知识很酷。 更酷的是应用这些基础知识来构建实际的应用程序。
So I’ll wrap things up by showing you how to build 3 projects that show off CSS variables and their ease of use. Here’s a quick preview of these 3 projects.
因此,我将向您展示如何构建3个项目来展示CSS变量及其易用性,以完成本文的总结。 这是这三个项目的快速预览。
项目1:使用CSS变量创建组件变体 (Project 1: Creating Component Variations using CSS Variables)
You may already be building component variations today. Whether you use React, Angular, or Vue, CSS Variables will make this process simpler.
您现在可能已经在构建组件变体。 无论您使用React,Angular还是Vue,CSS变量都会使此过程更加简单。
Check out the project on Codepen.
项目2:带有CSS变量的主题样式 (Project 2: Theme Styles with CSS Variables)
You’ve likely see this somewhere. I’ll show how easy CSS variables make creating site-wide theme styles.
您可能已经在某个地方看到了。 我将展示CSS变量如何使创建站点范围的主题样式变得容易。
Check out the project on Codepen.
项目3:构建CSS变量展台? (Project 3: Building the CSS Variable Booth ?)
This is the final project. Don’t mind the name. I couldn’t come up with a better name.
这是最后的项目。 不要介意这个名字。 我想不出一个更好的名字。
Notice how the colors of the boxes are dynamically updated, and how the box container is rotated in 3D space as the range input is changed.
请注意,框的颜色是如何动态更新的,并且随着范围输入的更改,框容器如何在3D空间中旋转。
This project shows off the ease of updating CSS variables with JavaScript, and the reactive goodies you get with it.
这个项目展示了使用JavaScript更新CSS变量的简便性,以及从中获得的React性好处。
这将会非常好玩! (This is going to be fun!)
Spend some time having fun with it on Codepen.
Note: The article assumes you have a good grasp of CSS. If you don’t know CSS very well, or want to learn to create jaw-dropping UIs, I recommend taking my Advanced CSS Course (paid course that include 85 lessons). This article is an excerpt from the course. </Shameless plug> ?
注意:本文假定您对CSS有很好的了解。 如果您不太了解CSS,或者想学习创建令人jaw目结舌的UI,建议您参加我的高级CSS课程 (收费课程,其中包括85课)。 本文摘录自本课程。 </ shameless plug>吗?
为什么变量如此重要 (Why variables are so important)
If you’re new to variables in preprocessors or native CSS, here are a few reasons why variables are important.
如果您不熟悉预处理器或本机CSS中的变量,则有一些为什么变量很重要的原因。
原因1:更具可读性的代码 (Reason #1: More readable code)
Without saying much, you can quickly tell how readable and more maintainable variables make any code base.
无需多说,您就可以快速分辨出可读性和可维护性强的变量如何构成任何代码库。
原因2:易于在大型文档中进行更改 (Reason #2: Ease of change across large documents)
If you have all your constants saved in a separate file, you don’t have to jump through thousands of lines of code when you want make a change to a variable.
如果将所有常量保存在单独的文件中,则在要更改变量时不必跳过数千行代码。
It becomes super-easy. Just change it in one place, and voilà.
变得超级容易。 只需将其更改为一个位置,然后更改即可。
原因3:您可以更快地发现错别字 (Reason #3: You can spot typos faster)
It’s a pain to search through lines of codes trying to spot an error. It’s even more annoying if the error was due to a simple typo. They are difficult to spot. The good use of variables eliminates these hassles.
搜索所有试图发现错误的代码行是很痛苦的。 如果错误是由于简单的错字引起的,那就更令人讨厌了。 他们很难被发现。 很好地使用变量消除了这些麻烦。
To this end, readability and maintainability are the big wins.
为此,可读性和可维护性是最大的胜利。
Thanks to CSS variables, now we can have these with native CSS too.
多亏了CSS变量,现在我们也可以将它们与本机CSS一起使用。
定义CSS变量 (Defining CSS variables)
Let me start with something you may already be familiar with: variables in JavaScript.
让我从您可能已经熟悉的东西开始:JavaScript中的变量。
A simple JavaScript variable may be declared like so:
可以像这样声明一个简单JavaScript变量:
var amAwesome;
and then you can assign it some value like so:
然后可以为它分配一些值,如下所示:
amAwesome = "awesome string"
In CSS, a CSS variable is any “property” whose name begins with two dashes.
在CSS中,CSS变量是名称以两个破折号开头的任何“属性”。
/*can you spot the variable here? */.block { color: #8cacea;--color: blue}
作用域CSS变量 (Scoping CSS Variables)
There’s one more thing to point your attention to.
还有另一件事需要引起您的注意。
Remember that in JavaScript, variables have a scope. They may either have a global or local scope.
请记住,在JavaScript中,变量具有作用域。 它们可能具有global范围或local范围。
The same may be said of CSS variables.
CSS变量也可以这样说。
Consider the example below:
考虑下面的示例:
:root { --main-color: red}
The :root selector allows you to target the highest-level element in the DOM, or document tree.
:root选择器使您可以定位DOM或文档树中的最高级别元素。
So, variables declared in this way are kind of scoped to the global scope.
因此,以这种方式声明的变量在某种程度上属于全局范围。
Got that?
了解?
例子1 (Example 1)
Assuming you wanted to create a CSS variable that stored the primary color of a themed site.
假设您想创建一个CSS变量来存储主题网站的原色。
How would you go about this?
您将如何处理?
You create the scoped selector. Use
:rootfor a 'global' variable您创建范围选择器。 使用
:root作为“全局”变量
:root { }
2. Define the variable
2.定义变量
:root { --primary-color: red}
Remember, a CSS variable is any “property” whose name begins with two dashes e.g --color
请记住,CSS变量是任何名称以两个破折号开头的“属性”,例如--color
That was simple.
那很简单。
使用CSS变量 (Using CSS Variables)
Once a variable has been defined and assigned a value, you can go ahead and use it within a property value.
一旦定义了变量并为其分配了值,就可以继续在属性值中使用它。
There’s a bit of a gotcha though.
虽然有一些陷阱。
If you’re coming from the world of preprocessors, you must be used to using a variable by just referencing its name. For example:
如果您来自预处理器领域,则必须习惯于仅通过引用变量的名称来使用它。 例如:
$font-size: 20px.test { font-size: $font-size}
With native CSS variables, things are a little different. You reference a variable by using the var() function.
使用本地CSS变量,情况有所不同。 您可以通过使用var()函数来引用变量。
With the example above, using CSS Variables will yield this:
在上面的示例中,使用CSS变量将产生以下结果:
:root { --font-size: 20px}.test { font-size: var(--font-size)}
Quite different.
很不一样。
Once you get that out of the way, you’ll start to love CSS variables - a lot!
一旦解决了这个问题,您将开始喜欢CSS变量-很多!
Another important note is that, unlike variables in Sass (or other preprocessors) — where you can use the variables in a lot of places, and do math like you want — you need to be careful with CSS variables. You’ll mostly have them set as property values.
另一个重要的注意事项是,与Sass(或其他预处理器)中的变量不同(您可以在很多地方使用这些变量并按自己的意愿进行数学运算),您需要注意CSS变量。 您通常会将它们设置为属性值。
/*this is wrong*/.margin {--side: margin-top;var(--side): 20px;}
You also can’t do math. You need the CSS calc() function for that. I’ll discuss examples as we proceed.
你也不能做数学。 为此,您需要CSS calc()函数。 在进行过程中,我将讨论示例。
/*this is wrong */.margin {--space: 20px * 2;font-size: var(--space); //not 40px}
If you must do math, then use the calc() function like so:
如果必须进行数学运算,则使用calc()函数,如下所示:
.margin {--space: calc(20px * 2);font-size: var(--space); /*equals 40px*/}
值得一提的特性 (Properties Worthy of Mention)
Here are some behaviors that are worth mentioning.
这里是一些值得一提的行为。
1.自定义属性是普通属性,因此可以在任何元素上声明它们。 (1. Custom properties are ordinary properties, so they can be declared on any element.)
Declare them on a paragraph element, section, aside, root, or even pseudo elements. They’ll work as expected.
将它们声明为段落元素,节,旁边,根甚至伪元素。 它们将按预期工作。
2. CSS变量使用常规继承和级联规则进行解析 (2. CSS variables are resolved with the normal inheritance and cascade rules)
Consider the block of code below:
考虑下面的代码块:
div { --color: red;}div.test { color: var(--color)}div.ew { color: var(--color)}
As with normal variables, the --color value will be inherited by the divs.
与普通变量一样,-- --color值将由div继承。
3. CSS变量可以使用@media和其他条件规则作为条件 (3. CSS variables can be made conditional with @media and other conditional rules)
As with other properties, you can change the value of a CSS variable within a @media block or other conditional rules.
与其他属性一样,您可以在@media块或其他条件规则中更改CSS变量的值。
For example, the following code changes the value of the variable, gutter on larger devices.
例如,以下代码在大型设备上更改了变量装订线的值。
:root { --gutter: 10px }@media screen and (min-width: 768px) { --gutter: 30px}
4. CSS变量可以在HTML的style属性中使用。 (4. CSS variables can be used in HTML’s style attribute.)
You can choose to set the value of your variables inline, and they’ll still work as expected.
您可以选择设置内联变量的值,它们仍将按预期工作。
<!--HTML--><html style="--color: red"><!--CSS-->;body { color: var(--color)}
CSS variables are case-sensitive. Be careful with this one. I save myself the stress and write variables in the lower case. Your mileage may differ.
CSS变量区分大小写。 小心这一点。 我为自己节省了压力,并以小写形式编写变量。 您的里程可能会有所不同。
/*these are two different variables*/:root { --color: blue;--COLOR: red;}
解决多个声明 (Resolving Multiple Declarations)
As with other properties, multiple declarations are resolved with the standard cascade.
与其他属性一样,使用标准级联可以解析多个声明。
Let’s see an example:
让我们来看一个例子:
/*define the variables*/:root { --color: blue; }div { --color: green; }#alert { --color: red; }/*use the variable */* { color: var(--color); }
With the variable declarations above, what will be the color of the following elements?
使用上面的变量声明,以下元素的颜色是什么?
<;p>What's my color?</p><div>and me?</div><div id='alert'> What's my color too? <p>color?</p></div>
Can you figure that out?
你能弄清楚吗?
The first paragraph will be blue. There is no direct --color definition set on a p selector, so it inherits the value from :root
第一段为blue 。 p选择器上没有设置直接的--color定义,因此它继承了:root的值
:root { --color: blue; }
The first div will be green . That’s pretty clear. There’s a direct variable definition set on the div
第一个div将是green 。 很清楚 div设置了直接变量定义
div { --color: green; }
The div with the ID of alert will NOT be green. It will be red
ID为alert的div不会为绿色。 会变成red
#alert { --color: red; }
The ID has a direct variable scoping. As such, the value within the definition will override the others. The selector #alert is more specific.
该ID具有直接变量作用域。 这样,定义中的值将覆盖其他值。 选择器#alert更具体。
Finally, the p within the #alert will be… red
最后, #alert的p将为... red
There’s no variable declaration on the paragraph element. You may have expected the color to be blue owing to the declaration on the :root element.
在段落元素上没有变量声明。 由于:root元素上的声明,您可能期望颜色为blue 。
:root { --color: blue; }
As with other properties, CSS variables are inherited. The value is inherited from the parent, #alert
与其他属性一样,CSS变量也是继承的。 该值是从父级#alert继承的
#alert { --color: red; }
解决循环依赖性 (Resolving Cyclic Dependencies)
A cyclic dependency occurs in the following ways:
循环依赖性以下列方式发生:
When a variable depends on itself. That is, it uses a
var()that refers to itself.何时变量取决于自身。 也就是说,它使用引用自身的
var()。
:root { --m: var(--m)}body { margin: var(--m)}
2. When two or more variables refer to each other.
2.当两个或多个变量相互引用时。
:root { --one: calc(var(--two) + 10px); --two: calc(var(--one) - 10px);}
Be careful not to create cyclic dependencies within your code.
注意不要在代码内创建循环依赖关系。
无效变量会发生什么? (What Happens with Invalid Variables?)
Syntax errors are discarded, but invalid var() substitutions default to either the initial or inherited value of the property in question.
语法错误将被丢弃,但是无效的var()替换默认为所讨论属性的初始值或继承值。
Consider the following:
考虑以下:
:root { --color: 20px; }p { background-color: red; }p { background-color: var(--color); }
As expected, --color is substituted into var() but the property value, background-color: 20px is invalid after the substitution. Since background-color isn’t an inheritable property, the value will default to its initial value of transparent.
正如所料, --color代入var()但该属性值, background-color: 20px是取代后无效。 由于background-color不是可继承的属性,因此该值将默认为其transparent initial值。
Note that if you had written background-color: 20px without any variable substitutes, the particular background declaration would have been invalid. The previous declaration will then be used.
请注意,如果您编写的background-color: 20px没有任何变量替代,则特定的背景声明将无效。 然后将使用之前的声明。
构建单个令牌时要小心 (Be Careful While Building Single Tokens)
When you set the value of a property as indicated below, the 20px is interpreted as a single token.
如下所示设置属性的值时, 20px被解释为单个标记。
font-size: 20px
A simple way to put that is, the value 20px is seen as a single ‘entity.’
一种简单的输入方法是,将值20px视为单个“实体”。
You need to be careful when building single tokens with CSS variables.
使用CSS变量构建单个标记时,需要小心。
For example, consider the following block of code:
例如,考虑以下代码块:
:root { --size: 20}div { font-size: var(--size)px /*WRONG*/}
You may have expected the value of font-size to yield 20px, but that is wrong.
您可能期望font-size的值产生20px ,但这是错误的。
The browser interprets this as 20 px
浏览器将其解释为20 px
Note the space after the 20
注意20后的空格
Thus, if you must create single tokens, have a variable represent the entire token. For example, --size: 20px, or use the calc function e.g calc(var(--size) * 1px) where --size is equal to 20
因此,如果您必须创建单个令牌,则用一个变量代表整个令牌。 例如--size: 20px ,或使用calc函数,例如calc(var(--size) * 1px) --size calc(var(--size) * 1px) ,其中--size等于20
Don’t worry if you don’t get this yet. I’ll explain it in more detail in a coming example.
如果您还没有得到这个,请不要担心。 我将在接下来的示例中对其进行详细说明。
让我们来构建东西! (Let’s build stuff!)
Now this is the part of the article we’ve been waiting for.
现在,这是我们一直在等待的文章的一部分。
I’ll walk you through practical applications of the concepts discussed by building a few useful projects.
我将引导您构建一些有用的项目,逐步讨论所讨论的概念。
Let’s get started.
让我们开始吧。
项目1:使用CSS变量创建组件变体 (Project 1: Creating Component Variations using CSS Variables)
Consider the case where you need to build two different buttons. Same base styles, just a bit of difference.
考虑需要构建两个不同按钮的情况。 基本样式相同,只是有所不同。
In this case, the properties that differ are the background-color and border-color of the variant.
在这种情况下,不同的属性是变体的background-color和border-color 。
So, how would you do this?
那么,您将如何做呢?
Here’s the typical solution.
这是典型的解决方案。
Create a base class, say .btn and add the variant classes. Here’s an example markup:
创建一个基类,例如.btn并添加变体类。 这是一个示例标记:
<button class="btn">Hello</button><button class="btn red">Hello</button>
.btn would contain the base styles on the button. For example:
.btn将包含按钮上的基本样式。 例如:
.btn { padding: 2rem 4rem; border: 2px solid black; background: transparent; font-size: 0.6em; border-radius: 2px;}
/*on hover */.btn:hover { cursor: pointer; background: black; color: white;}
So, where does the variant come in?
那么,变体出现在哪里呢?
Here:
这里:
/* variations */.btn.red { border-color: red}.btn.red:hover { background: red}
You see how we are duplicating code here and there? This is good, but we could make it better with CSS variables.
您了解我们如何在这里和那里复制代码吗? 很好,但是我们可以使用CSS变量使它更好。
What’s the first step?
第一步是什么?
Substitute the varying colors with CSS variables, and don’t forget to add default values for the variables!
用CSS变量替换各种颜色,不要忘记为变量添加默认值!
.btn { padding: 2rem 4rem; border: 2px solid var(--color, black); background: transparent; font-size: 0.6em; border-radius: 2px; }
/*on hover*/ .btn:hover { cursor: pointer; background: var(--color, black); color: white; }
When you do this: background: var(--color, black) you’re saying, set the background to the value of the variable --color . However, if the variable doesn't exist, use the default value of black
当您执行此操作时: background: var(--color, black) 您是说,将背景设置为变量--color的值。 但是,如果变量不存在,请使用默认值black
This is how you set default variable values. Just like you do in JavaScript or any other programming language.
这是设置默认变量值的方式。 就像使用JavaScript或其他任何编程语言一样。
Here’s the good part.
这是好部分。
With the variants, you just supply the new value of the CSS variable as under:
使用这些变体,只需提供CSS变量的新值,如下所示:
.btn.red { --color: red }
That’s all. Now when the .red class is used, the browser notes the different --color variable value, and immediately updates the appearance of the button.
就这样。 现在,当使用.red类时,浏览器会记录不同的--color变量值,并立即更新按钮的外观。
This is really good if you spend a lot of time building reusable components.
如果您花费大量时间来构建可重复使用的组件,那么这真的很好。
Here’s a side by side comparison:
这是一个并排比较:
Oh, and if you had more variants, you just saved yourself a lot of extra typing.
哦,如果您有更多的变体,您就为自己节省了很多额外的输入。
项目2:带有CSS变量的主题网站 (Project 2: Themed Sites with CSS Variables)
I’m sure you’ve come across them before. Themed sites give the user the feel of customization. Like they are in control.
我敢肯定你以前见过他们。 主题网站使用户感到定制化。 就像他们在控制中。
Below is the basic example we’ll build.
以下是我们将构建的基本示例。
So, how easy do the CSS variables make this?
那么,CSS变量使这变得容易吗?
We’ll have a look.
我们来看一下。
Just before that, I wanted to mention that this example is quite important. With this example, I’ll introduce the concept of updating CSS variables with JavaScript.
在此之前,我想提一下这个例子非常重要。 在此示例中,我将介绍使用JavaScript更新CSS变量的概念。
It is fun!
很好玩!
You’ll love it.
你会爱上它。
我们真正想要做的。 (What we really want to do.)
The beauty of CSS variables is their reactive nature . As soon as they are updated, whatever property has the value of the CSS variable gets updated as well.
CSS变量的优点在于它们的React特性。 一旦它们被更新,具有CSS变量值的任何属性也将被更新。
Conceptually, here’s an image that explains the process with regards to the example at hand.
从概念上讲,这是一张图像,用于说明有关当前示例的过程。
So, we need some JavaScript for the click listener.
因此,我们需要一些JavaScript用于点击监听器。
For this simple example, the background and color of the text of the entire page is based off of CSS variables.
对于此简单示例,整个页面文本的背景和颜色基于CSS变量。
When you click any of the buttons above, they set the CSS variable to some other color. As a result of that, the background of the page is updated.
当您单击上面的任何按钮时,它们会将CSS变量设置为其他颜色。 结果,页面的背景被更新。
Hey, that’s all there is to it.
嘿,仅此而已。
Uh, one more thing.
呃,还有一件事。
When I say the CSS variable is set to some other value, how’s that done?
当我说CSS变量设置为其他值时,该怎么做?
CSS variables will take effect even if they are set inline. With JavaScript, we get a hold of the root document, and we set the new value for the CSS variable inline.
即使将CSS变量设置为内联,它们也会生效。 使用JavaScript,我们可以保留根文档,并为内联CSS变量设置新值。
Got that?
了解?
That’s a lot of talking — let’s do the real thing.
谈论很多-让我们做真实的事情。
初始标记 (The initial markup)
The initial markup needed is this:
所需的初始标记是这样的:
<div class="theme"> <button value="dark">dark</button> <button value="calm">calm</button> <button value="light">light</button></div><article>...</article>
The markup consists of three buttons within a .theme parent element. To keep things short I have truncated the content within the article element. Within this article element is the content of the page.
标记由.theme父元素中的三个按钮组成。 为了简短起见,我将article元素中的内容截短了。 此article元素内包含页面的内容。
样式页面 (Styling the Page)
The success of this project begins with the styling of the page. The trick is simple.
该项目的成功始于页面的样式。 诀窍很简单。
Instead of just setting the background-color and color of the page in stone, we will set them based on variables.
我们将基于变量来设置它们,而不仅仅是用石头设置页面的background-color和color 。
Here’s what I mean.
这就是我的意思。
body { background-color: var(--bg, white); color: var(--bg-text, black)}
The reason for this is kind of obvious. Whenever a button is clicked, we will change the value of both variables within the document.
原因很明显。 每当单击按钮时,我们都会更改文档中两个变量的值。
Upon this change, the overall style of the page will be updated. Easy-peasy.
进行此更改后,页面的整体样式将被更新。 十分简单。
So, let’s go ahead and handle the update from JavaScript.
因此,让我们继续处理来自JavaScript的更新。
进入JavaScript (Getting into the JavaScript)
I’ll go ahead and spit out all the JavaScript needed for this project.
我将继续介绍该项目所需的所有JavaScript。
const root = document.documentElement const themeBtns = document.querySelectorAll('.theme > button')themeBtns.forEach((btn) => { btn.addEventListener('click', handleThemeUpdate)})function handleThemeUpdate(e) { switch(e.target.value) { case 'dark': root.style.setProperty('--bg', 'black') root.style.setProperty('--bg-text', 'white') break case 'calm': root.style.setProperty('--bg', '#B3E5FC') root.style.setProperty('--bg-text', '#37474F') break case 'light': root.style.setProperty('--bg', 'white') root.style.setProperty('--bg-text', 'black') break }}
Don’t let that scare you. It’s a lot easier than you probably think.
不要让那吓到你。 这比您想象的要容易得多。
First off, keep a reference to the root element, const root = document.documentElement
首先,保留对根元素的引用const root = document.documentElement
The root element here is the HTML element. You’ll see why this is important in a bit. If you’re curious, it is needed to set the new values of the CSS variables.
这里的根元素是HTML元素。 您很快就会明白为什么这很重要。 如果您感到好奇,则需要设置CSS变量的新值。
Also, keep a reference to the buttons too, const themeBtns = document.querySelectorAll('.theme > button')
另外,还要保留对按钮的引用, const themeBtns = document.querySelectorAll('.theme > butto n')
querySelectorAll yields an array-like data structure we can loop over. Iterate over each of the buttons and add an event listener to them, upon click.
querySelectorAll产生我们可以循环的类似数组的数据结构。 遍历每个按钮,并在单击时向它们添加事件侦听器。
Here’s how:
这是如何做:
themeBtns.forEach((btn) => { btn.addEventListener('click', handleThemeUpdate)})
Where’s the handleThemeUpdate function? I’ll discuss that next.
handleThemeUpdate函数在哪里? 我接下来再讨论。
Every button being clicked will have the handleThemeUpdate as its callback function. It becomes important to note what button was clicked and then perform the right operation.
每个被单击的按钮都将把handleThemeUpdate作为其回调函数。 重要的是要注意单击了什么按钮,然后执行正确的操作。
In the light of that, a switch operator is used, and some operations are carried out based on the value of the button being clicked.
鉴于此,使用了开关operator器,并且基于被点击的按钮的值来执行一些操作。
Go ahead and take a second look at the block of JavaScript code. You’ll understand it a lot better now.
继续看一下JavaScript代码块。 您现在会更好地了解它。
项目3:构建CSS变量展台? (Project 3: Building the CSS Variable Booth ?)
In case you missed it, here’s what we’ll build:
万一您错过了它,我们将为您提供以下服务:
Remember that the color of the boxes are dynamically updated, and that the box container is rotated in 3d space as the range input is changed.
请记住,框的颜色是动态更新的,并且在更改范围输入时,框容器在3d空间中旋转。
You can go ahead and play with it on Codepen.
您可以继续在Codepen上使用它。
This is a superb example of updating CSS variables with JavaScript and the reactivity that comes with it.
这是一个使用JavaScript更新CSS变量及其附带的React性的绝佳示例。
Let’s see how to build this.
让我们看看如何构建它。
标记 (The Markup)
Here are the needed components.
这是所需的组件。
- A range input 范围输入
- A container to hold the instructions 存放指令的容器
- A section to hold a list of other boxes, each containing input fields 包含其他框列表的部分,每个框包含输入字段
The markup turns out simple.
标记结果很简单。
Here it is:
这里是:
<main class="booth"> <aside class="slider"> <label>Move this ? </label> <input class="booth-slider" type="range" min="-50" max="50" value="-50" step="5"/> </aside> <section class="color-boxes"> <div class="color-box" id="1"><input value="red"/></div> <div class="color-box" id="2"><input/></div> <div class="color-box" id="3"><input/></div> <div class="color-box" id="4"><input/></div> <div class="color-box" id="5"><input/></div> <div class="color-box" id="6">;<input/></div> </section> <footer class="instructions"> ?? Move the slider<br/> ?? Write any color in the red boxes </footer></main>
Here are a few things to point your attention to.
以下是一些需要引起您注意的事项。
The range input represents values from
-50to50with a step value of5Also, the value of the range input is the minimum value,-50范围输入代表从
-50到50的值,步进值为5此外,范围输入的值是最小值-50If you aren’t sure how the range input works, check it out on w3schools
如果不确定范围输入的工作方式,请在w3schools上查看
Note how the section with class
.color-boxescontains other.color-boxcontainers. Within these containers exist input fields.注意类
.color-boxes的部分如何包含其他.color-box容器。 这些容器中存在输入字段。- It is perhaps worth mentioning that the first input has a default value of red. 也许值得一提的是,第一个输入的默认值为红色。
Having understood the structure of the document, go ahead and style it like so:
了解了文档的结构之后,继续进行样式设置,如下所示:
Take the
.sliderand.instructionscontainers out of the document flow. Position them absolutely.从文档流中取出
.slider和.instructions容器。 绝对放置它们。Give the
bodyelement a sunrise background color and garnish the background with a flower in the bottom left corner给
body元素添加日出背景色,并在左下角用一朵花装饰背景Position the
color-boxescontainer in the center将
color-boxes容器放置在中间Style the
color-boxescontainer设置
color-boxes容器的样式
Let’s knock these off.
让我们完成这些。
The following will fix the first task.
以下将解决第一个任务。
/* Slider */.slider,.instructions { position: absolute; background: rgba(0,0,0,0.4); padding: 1rem 2rem; border-radius: 5px}.slider { right: 10px; top: 10px;}.slider > * { display: block;}/* Instructions */.instructions { text-align: center; bottom: 0; background: initial; color: black;}
The code snippet isn’t as complex as you think. I hope you can read through and understand it. If not, drop a comment or tweet.
代码段并不像您想象的那么复杂。 希望您能通读并理解。 如果没有,请发表评论或鸣叫。
Styling the body is a little more involved. Hopefully, you understand CSS well.
造型的body要复杂得多。 希望您对CSS非常了解。
Since we aspire to style the element with a background color and a background image, it’s perhaps the best bet to use the background shorthand property to set multiple backgrounds.
由于我们渴望使用背景颜色和背景图像来设置元素的样式,因此最好使用background速记属性设置多个背景。
Here it is:
这里是:
body { margin: 0; color: rgba(255,255,255,0.9); background: url('http://bit.ly/2FiPrRA') 0 100%/340px no-repeat, var(--primary-color); font-family: 'Shadows Into Light Two', cursive;}
The url bit is the link to the sunrise flower.
url位是指向日出花朵的链接。
The next set of properties 0 100% represent the background position of the image.
下一组属性0 100%表示图像的背景位置。
Here’s an illustration of how CSS background positioning works:
这是CSS背景定位如何工作的说明:
The other bit after the forward slash represents the background-size This has been set to 340px If you made this smaller, the image would be smaller too.
正斜杠后的另一位代表background-size此background-size已设置为340px如果将此尺寸减小,图像也将减小。
no-repeat, you might figure out what that does. It prevents the background from repeating itself.
no-repeat ,您可能会发现这样做的结果。 这样可以防止背景重复。
Finally, anything that comes after the comma is a second background declaration. This time we’ve only set the background-color to var(primary-color)
最后,逗号后面的内容是第二个背景声明。 这次我们仅将background-color设置为var(primary-color)
Oops, that’s a variable.
糟糕,这是一个变量。
The implication of this is that you have to define the variable. Here’s how:
这意味着必须定义变量。 这是如何做:
:root { --primary-color: rgba(241,196,15 ,1)}
The primary color there is the sunrise yellow color. No big deal. We’ll set some more variables in there soon.
那里的原色是日出黄色。 没什么大不了的。 我们很快将在其中设置更多变量。
Now, let’s center the color-boxes
现在,让我们将color-boxes居中
main.booth { min-height: 100vh; display: flex; justify-content: center; align-items: center;}
The main container acts as a flex container and rightly positions the direct child in the center of the page. This happens to be our beloved color-box container
主容器充当弹性容器,并将直接子代正确放置在页面中心。 这恰好是我们钟爱color-box容器
Let’s make the color-boxes container and its children elements pretty.
让我们使color-boxes容器及其子元素变得漂亮。
First, the child elements:
首先,子元素:
.color-box { padding: 1rem 3.5rem; margin-bottom: 0.5rem; border: 1px solid rgba(255,255,255,0.2); border-radius: 0.3rem; box-shadow: 10px 10px 30px rgba(0,0,0,0.4); }
That will do it. There’s a beautiful shadow added too. That’ll get us some cool effects.
这样就可以了。 也添加了一个美丽的阴影。 那会给我们带来一些很酷的效果。
That is not all. Let’s style the overall container-boxes container:
这还不是全部。 让我们为整个container-boxes容器设置样式:
/* Color Boxes */.color-boxes { background: var(--secondary-color); box-shadow: 10px 10px 30px rgba(0,0,0,0.4); border-radius: 0.3rem; transform: perspective(500px) rotateY( calc(var(--slider) * 1deg)); transition: transform 0.3s}
Oh my!
天啊!
There’s a lot in there.
里面有很多东西。
Let me break it down.
让我分解一下。
Here’s the simple bit:
这是简单的一点:
.color-boxes { background: var(--secondary-color); box-shadow: 10px 10px 30px rgba(0,0,0,0.4); border-radius: 0.3rem;}
You know what that does, huh?
你知道那是什么吗?
There’s a new variable in there. That should be taken of by adding it to the root selector.
那里有一个新变量。 应该通过将其添加到根选择器中来解决。
:root { --primary-color: rgba(241,196,15 ,1); --secondary-color: red;}
The secondary color is red. This will give the container a red background.
次要颜色是红色。 这将使容器具有红色背景。
Now to the part that probably confused you:
现在到可能使您困惑的部分:
/* Color Boxes */.color-boxes { transform: perspective(500px) rotateY( calc(var(--slider) * 1deg)); transition: transform 0.3s}
For a moment, we could simplify the value of the transform property above.
暂时,我们可以简化上面的transform属性的值。
For example:
例如:
transform: perspective(500px) rotateY( 30deg);
The transform shorthand applies two different functions. One, the perspective, and the other, the rotation along the Y axis.
转换速记应用两个不同的功能。 一个是透视图,另一个是沿Y轴的旋转。
Hmmm, so what’s the deal with the perspective and rotateY functions?
嗯,那么perspective和rotateY函数有什么关系呢?
The perspective() function is applied to an element that is being transformed in 3D space. It activates the three dimensional space and gives the element depth along the z-axis.
Perspective()函数应用于在3D空间中进行变换的元素。 它激活三维空间,并沿z轴给出元素深度。
You can read more about the perspective function on codrops.
您可以阅读有关codrops的透视功能的更多信息。
The rotateY function, what’s the deal with that?
rotateY函数,该怎么处理?
Upon activation the 3d space, the element has the planes x, y, z. The rotateY function rotates the element along the Y plane.
激活3d空间后,该元素将具有x,y,z平面。 rotateY函数沿Y平面旋转元素。
The following diagram from codrops is really helpful for visualizing this.
以下来自codrops的图表对于可视化确实很有帮助。
I hope that blew off some of the steam.
我希望这能消除一些麻烦。
Back to where we started.
回到我们开始的地方。
When you move the slider, do you know what function affects the rotation of the .container-box?
当您移动滑块时,您是否知道哪个功能会影响.container-box的旋转?
It’s the rotateY function being invoked. The box is rotated along the Y axis.
这是被调用的rotationY函数。 盒子沿Y轴旋转。
Since the value passed into the rotateY function will be updated via JavaScript, the value is represented with a variable.
由于传递给rotateY函数的值将通过JavaScript更新,因此该值用一个变量表示。
So, why multiply by the variable by 1deg?
那么,为什么将变量乘以1deg?
As a general rule of thumb, and for explicit freedom, it is advised that when building single tokens, you store values in your variables without units.
作为一般的经验法则,为了获得明确的自由,建议在构建单个标记时,将值存储在变量中而不使用单位。
You can convert them to any unit you want by doing a multiplication via the calc function.
您可以通过calc函数进行乘法运算,将它们转换为所需的任何单位。
This allows you to do ‘whatever’ you want with these values when you have them. Want to convert to deg or as a ratio of the user’s viewport vw , you can whatever you want.
有了这些值,您就可以对它们进行“任何操作”。 想要将其转换为deg或作为用户视口vw的比例,您可以随心所欲。
In this case, we are converting the number to have a degree by multiplying the “number” value by 1deg
在这种情况下,我们通过将“数字”值乘以1deg将数字转换为度数。
Since CSS doesn’t understand math, you have to pass this arithmetic into the calc function to be properly evaluated by CSS.
由于CSS不懂数学,因此您必须将此算法传递到calc函数中,以便CSS正确评估。
Once that is done, we’re good to go. The value of this variable can be updated in JavaScript as much as we like.
一旦完成,我们就可以开始了。 可以根据需要在JavaScript中尽可能多地更新此变量的值。
Now, there’s just one bit of CSS remaining.
现在,仅剩一点CSS。
Here it is:
这里是:
/* Handle colors for each color box */.color-box:nth-child(1) { background: var(--bg-1)}.color-box:nth-child(2) { background: var(--bg-2)}.color-box:nth-child(3) { background: var(--bg-3)}.color-box:nth-child(4) { background: var(--bg-4)}.color-box:nth-child(5) { background: var(--bg-5)}.color-box:nth-child(6) { background: var(--bg-6)}
So, what’s this voodoo?
那么,这是什么巫毒教?
First off, the nth-child selector selects each of the child boxes.
首先,第n个子选择器选择每个子框。
There’s a bit of foresight needed here. We know we will be updating the background color of each box. We also know that this background color has to be represented by a variable so it is accessible via JavaScript. Right?
这里需要一些先见之明。 我们知道我们将更新每个框的背景色。 我们也知道,此背景色必须由变量表示,因此可以通过JavaScript进行访问。 对?
We could go ahead and do this:
我们可以继续执行以下操作:
.color-box:nth-child(1) { background: var(--bg-1)}
Easy.
简单。
There’s one problem though. If this variable isn’t present, what happens?
不过有一个问题。 如果不存在此变量,会发生什么?
We need a fallback.
我们需要一个后备。
This works:
这有效:
.color-box:nth-child(1) { background: var(--bg-1, red)}
In this particular case, I have chosen NOT to provide any fallbacks.
在这种情况下,我选择不提供任何后备。
If a variable used within a property value is invalid, the property will take on its initial value.
如果在属性值中使用的变量无效,则该属性将采用其初始值。
Consequently, when --bg-1 is invalid or NOT available, the background will default to its initial value of transparent.
因此,当--bg-1无效或不可用时,背景将默认为其透明的初始值。
Initial values refer to the values of a property when they aren’t explicitly set. For example, if you don’t set the background-color of an element, it will default to transparent
未明确设置初始值时,它们是指属性的值。 例如,如果您未设置元素的background-color ,则默认为transparent
Initial values are kind of default property values.
初始值是默认属性值的一种。
让我们写一些JavaScript (Let’s write some JavaScript)
There’s very little we need to do on the JavaScript side of things.
在JavaScript方面,我们几乎不需要做任何事情。
First let’s handle the slider.
首先,让我们处理滑块。
We just need 5 lines for that!
我们只需要5行!
const root = document.documentElementconst range = document.querySelector('.booth-slider')//as slider range's value changes, do something range.addEventListener('input', handleSlider)function handleSlider (e) { let value = e.target.value root.style.setProperty('--slider', value)}
That was easy, huh?
那很容易,对吗?
Let me explain just in case I lost you.
让我解释一下,以防万一我失去了你。
First off, keep a reference to the slider element, const range = document.querySelector('.booth-slider')
首先,保留对滑块元素的引用, const range = document.querySelector('.booth-slider')
Set up an event listener for when the value of the range input changes, range.addEventListener('input', handleSlider)
为范围输入的值更改时设置事件侦听器, range.addEventListener('input', handleSlider)
Write the callback, handleSlider
编写回调, handleSlider
function handleSlider (e) { let value = e.target.value root.style.setProperty('--slider', value)}
root.style.setProperty('--slider', value) says, get the root element (HTML) , grab its style, and set a property on it.
root.style.setProperty('--slider', value)表示,获取root元素(HTML),获取其样式,并为其设置属性。
处理颜色变化 (Handling the color changes)
This is just as easy as handling the slider value change.
这就像处理滑块值更改一样容易。
Here’s how:
这是如何做:
const inputs = document.querySelectorAll('.color-box > input')
//as the value in the input changes, do something.inputs.forEach(input => { input.addEventListener('input', handleInputChange)})function handleInputChange (e) { let value = e.target.value let inputId = e.target.parentNode.id let inputBg = `--bg-${inputId}` root.style.setProperty(inputBg, value)}
Keep a reference to all the text inputs, const inputs = document.querySelectorAll('.color-box > input')
保留对所有文本输入的引用, const inputs = document.querySelectorAll('.color-box > inpu t')
Set up an event listener on all the inputs:
在所有输入上设置事件侦听器:
inputs.forEach(input => { input.addEventListener('input', handleInputChange)})
Write the handleInputChange function:
编写handleInputChange函数:
function handleInputChange (e) { let value = e.target.value let inputId = e.target.parentNode.id let inputBg = `--bg-${inputId}` root.style.setProperty(inputBg, value)}
Phew…
ew ...
That’s it!
而已!
Project’s done.
项目完成。
我怎么想念这个? (How did I miss this?)
I had completed and edited the initial draft of this article when I noticed I didn’t mention browser support anywhere. So, let me fix my mess.
当我发现我在任何地方都没有提到浏览器支持时,我已经完成并编辑了本文的初稿。 所以,让我修复我的烂摊子。
Browser support for CSS variables (aka custom properties) isn’t bad at all. It’s pretty good, with decent support across all modern browsers (over 87% at the time of this writing).
浏览器对CSS变量(也称为自定义属性)的支持一点也不差。 相当不错,所有现代浏览器都提供了不错的支持(在撰写本文时,这一比例超过了87%)。
So, can you use CSS variables in production today? I’ll say yes! Be sure to check what the adoption rate is for yourself, though.
那么,您今天可以在生产中使用CSS变量吗? 我会说是的! 不过,请务必检查自己的采用率。
On the bright side, you can use a preprocessor like Myth. It’ll preprocess your ‘future’ CSS into something you use today. How cool, huh?
从好的方面来说,您可以使用像Myth这样的预处理器。 它将“未来” CSS预处理为您今天使用的东西。 太酷了吧?
If you have some experience using postCSS, that’s equally a great way to use future CSS today. Here’s a postCSS module for CSS variables.
如果您有使用postCSS的经验,那同样是今天使用未来CSS的好方法。 这是CSS变量的postCSS模块 。
That’s it. I’m done here.
而已。 我在这里做完了。
糟糕,但我有问题! (Oops, but I’ve got Questions!)
Get the Ebook for offline reading, and also get a private slack invite where you can ask me anything.
获取电子书以供离线阅读,还获得私人闲暇邀请,在这里您可以问我任何问题。
That’s a fair deal, right?
那是公平的交易,对不对?
Catch you later! ?
待会见! ?
翻译自: https://www.freecodecamp.org/news/everything-you-need-to-know-about-css-variables-c74d922ea855/
css 变量
本文深入讲解CSS变量的使用,包括定义、作用域、更新及在实际项目中的应用,如组件变体创建、主题样式和响应式设计。文章涵盖变量的重要性和易用性,以及与JavaScript的交互。

1984

被折叠的 条评论
为什么被折叠?



