本帖最后由 neekin 于 2018-4-12 14:45 编辑
大多数编程语言都支持变量。但遗憾的是,CSS从一开始就缺乏对原生变量的支持。如果写CSS的话,那是没有变量的,除非你使用像Sass这样的CSS处理器。 变量是Sass这样处理器的一个非常有用的特性之一。这也是你尝试使用的理由之一。Web技术发展是非常快速的。我很高兴地告诉你,CSS现在终于支持原生的变量了。 虽然CSS处理器还支持更多的特性,但是CSS添加原生的变量是很好的。这些举措使用Web更接近未来的技术。在这篇文章接下来的内容中,我将向你展示如何在CSS使用变量,以及如何使用它们让你的工作变得更轻松。 特别声明:为了能让CSS的原生变量与CSS处理器变量区分出来,我更喜欢将其称为CSS自定义属性。 你将学到首先会向大家介绍CSS自定义属性的基本知识。我相信试图理解CSS自定义属性都必须从这一点开始。学习CSS自定义属性的基本知识是非常有意思的事情。其中更有趣的是,你可以在真实的项目中使用这些基本原理。 因此,我将通过三个简单的项目来向你展示CSS自定义属性的易用性。先来快速预览一下这三个项目: 项目1:使用CSS自定义属性创建组件变量你可能在项目中已经使用到了组件变量。不管是React、Angular或者Vue中,使用CSS自定义属性都会使这个过程变得更简单。
项目2:使用CSS自定义属性实现皮肤切换你可能在某个地方看到过类似的效果。在这个项目中将向你展示使用CSS自定义属性是如何简单的为Web网站实现皮肤切换的效果。
项目3: 创建CSS自定义属性展台(Booth)这是最后一个项目。请不要介意这个名字。说实在的,我想不出一个更好的名字了。
注意如何动态更新容器的颜色,以及如何在input(type="range")控制条的范围内更改外部容器的3D旋转效果。 这个项目演示了使用JavaScript更新CSS自定义属性的便利性,以及即改即得的效果。你可以在上面示例中的input框中输入任意颜色值或者拖动range的进度条,浏览对应的效果变化。 为什么CSS自定义属性如此重要?如果你是第一次接触CSS处理器中的变量或者CSS自定义属性,那么接下来介绍的几个方面将告诉你为什么CSS自定义属性对你而言是多么的重要。 理由1:代码更具可读性不做过多的阐述,直接告诉你,使用CSS自定义属性可以让你的代码变得更具可读性和可维护性。 理由2:在大型项目中更易于修改如果你将所有常量保存在一个单独的文件中,那么你想对一个变量进行更改时,不必跳过数千行代码。它变得很宽松,你可以把它放在任何一个地方。 理由3:更暴打发现输入错误通过代码来查找错误是一件极为痛苦的事情。特别是你的错误是由于一个简单输入引起的,那就更令人恼火了。因为它是极难被人发现。CSS自定义属性的使用将消除这些麻烦。 为此,可读性和可维护性是CSS自定义属性最大的优势。
我们需要感谢 CSS自定义属性,让我们可以在CSS中使用原生的变量,而不再需要借助于类似Sass这样的CSS处理器。 定义CSS自定义属性我们从一些熟悉的东西开始:JavaScript中的变量。 一个简单的JavaScript变量可以像下面这样来声明: var amAwesome;然后你可以给它赋值,比如: amAwesome = "awesome string"在CSS中,一个CSS自定义属性是以两个破折号(--)开始的任何名称。 /* 你可以在这里声明一个CSS自定义属性*/.block { color: #8cacea; --color: blue; /* 可以是常规的CSS属性,但需要以两个破折号(`--`)开始 */}CSS自定义属性作用域还有一件事你需要注意。 请记住,在JavaScript中,变量是有作用域一说。它们可能是全局作用域,也有可能是局部作用域。那么在CSS中,CSS自定义属性也有这样的说法。 比如下面这个示例: :root { --main-color: red}:root选择器可以选择到DOM元素中或document树中最高顶级的元素。因此,在:root选择器是声明的CSS自定义属性,其作用域的范围是全局范围,也就是全局作用域。 明白了? :root { --color: black; /* 全局作用域*/}.block { color: #8cacea; --color: blue; /* 局部作用域;`--color`作用域是`.block`选择器 */}示例假设你想创建一个CSS自定义属性,该自定义属性存储Web网站皮肤的主色(Primary color)。那么你将会怎么做呢? 你将创建选择器范围。使用:root创建一个global自定义属性: :root {}然后声明自定义属性: :root { --primary-color: red;}请记住,CSS自定义属性可以是任何名称,但名称前必须要以两个破折号,比如--color。 这是不是很简单。 使用CSS自定义属性一旦声明了一个CSS自定义属性,并给其指定了一个值,那么你就可以在CSS的属性值中使用它。不过使用还是有点小问题。 如果你是在CSS处理器中使用,那么你必须在属性值中引用这个已声明的变量,例如: $font-size: 20px;.test { font-size: $font-size;}但在CSS中使用已声明的CSS自定义属性,和在CSS处理器中使用声明的变量略有不同。你需要通过var()函数来引用已声明的CSS自定义属性。 比如上面的示例,在CSS中使用已声明的CSS自定义属性,需要像下面这样使用: :root { --font-size: 20px; /* 声明一个全局使用域的CSS自定义属性 */}.test { font-size: var(--font-size); /* 通过var()函数调用已声明的CSS自定义属性--font-size */}一旦你理解了这一点,你就会开始喜欢CSS自定义属性,而且会很喜欢。 不过需要特别注意的是,CSS自定义属性不像Sass(或其他CSS处理器)中的变量,可以在许多地方使用变量,并且可以进行一些数学运算,但使用CSS自定义属性时,只能在CSS属性值中使用CSS自定义属性。 /* 这是一种错误的使用方式 */.margin { --side: margin-top; var(--size): 20px;}也不能像Sass这样的处理器一样直接做一些数学计算。如果你需要做一些数据计算,需要使用CSS的calc()函数。我们将在后续的示例中会聊到这一点。 /* 这是一种错误的使用方式 */.margin { --space: 20px * 2; font-size: var(--space); }使用CSS自定义属性要做一些数学计算时,应该像下面这样通过calc()函数来完成: .margin { --space: calc(20px * 2); font-size: var(--space);}值得注意的地方以下几个点是值得一提的地方。 自定义属性是普通属性,可以在任意元素上声明它们CSS自定义属性可以在任意元素上,比如p、section、aside、根元素,甚至是伪元素上声明。他们都会按照预期进行工作。 p { --color: blue;}section { --color: #bad;}aside { --color: yellow;}:root { --color: teal;}p:before { --color: red;}当你在对应的元素中调用相应的CSS自定义属性时,可以看到他们都能按照你的预期工作:
CSS自定义属性可以通过继承和级联规则来解决比如下面这段示例代码: div { --color: red;}div.test { color: var(--color)}div.ew { color: var(--color)}和正常变量一样,--color将会继承div中的值: CSS自定义属性可以通过@media和其他条件规则来实现和其他属性一样,可以在@media或其他条件规则中更改CSS自定义属性的值。 比如下面这段示例代码,在较大的屏幕设备上将会改变gutter的值: :root { --gutter: 10px;}@media screen and (min-width: 768px) { --gutter: 30px;}CSS自定义属性可以用在HTML元素的style属性中你可以选择在内联样式中声明CSS自定义属性,它同样是可以按照你的预期进行工作。 <!--HTML--><html style="--color: red"><!--CSS-->body { color: var(--color)}值得一提的是:CSS自定义属性是区分大小写的。这一点需要特别的注意。 /* 这是两个不同的CSS自定义属性 */:root { --color: blue; --COLOR: red;}解决多个声明的CSS自定义属性CSS自定义属性和其他CSS属性一样,可以用标准级联解决多个相同声明的CSS自定义属性。比如下面这个示例: /* 声明相同名称的CSS自定义属性 */:root { --color: blue; }div { --color: green; }#alert { --color: red; }/* 使用CSS自定义属性 */* { color: var(--color); }就上面声明的CSS自定义属性,下列元素的文本颜色将会是什么颜色呢? <p>What's my color?</p><div>and me?</div><div id='alert'> What's my color too? <p>color?</p></div>你能基于上述的知识点猜出来结果吗? 第一个<p>元素是blue。因为在p选择器上没有显式定义--color,所以它将继承来自:root中的--color的值。 :root { --color: blue; }第一个<div>元素将是green。这一点非常的明显,因为在div选择器上显示的声明了--color自定义属性的值为green: div { --color: green; }ID名为#alert的div元素,它的颜色不再是green,将会是red,那是因为在#alert选择器中也显式的声明了--color的值为red: #alert { --color: red; }该ID选择器直接声明了一个自定义属性的作用域,其定义的值将会覆盖前面div声明的自定义属性,那是因为#alert选择器的权重高于div选择器。 由于最后一个<p>元素在#alert内,所以它的颜色也将是red。 在p元素上没有显式声明CSS自定义属性,但在:root元素上显式的声明了,因为正如你所期望的一样,其颜色为blue。 :root { --color: blue; }但CSS自定义属性和CSS中的其他属性是类似的,也具有继承这样的特性。所以最后一个<p>元素会继承其父元素#alert中声明的CSS自定义属性值: #alert { --color: red; }解决循环依赖循环依赖的发生方式如下。 当一个变量依赖于它自己。也就是说,它使用的是引用自身的var()。 :root { --m: var(--m)}body { margin: var(--m)}另外一种方式就是两个或多个变量相互引用时: :root { --one: calc(var(--two) + 10px); --two: calc(var(--one) - 10px);}目前唯一可破的方法是:不要在代码中创建具有循环依赖关系的CSS自定义属性。 无效的CSS自定义属性将会发生什么?如果是语法错误,将会直接视为无效,但无效的var()将会被该属性的初始值或继承值替代。比如下面的示例: :root { --color: 20px; }p { background-color: red; }p { background-color: var(--color); /* 设置了一个无效的颜色值 */}如你所预期的一样,--color被var()替换了,但是属性值background-color:20px是一个无效值。由于background-color不是一个可继承的属性,所以该值将默认为background-color的初值值transparent。 请注意,如果你已经写了background-color: 20px没有自定认属性来替换,那么background-clor将是无效的。要是前面有对应的声明,将会使用前面的声明。 在构建单个指令时要小心当你设置如下所示的属性值时,20px被解释为单个指令(Tokens)。 font-size: 20px一个简单的方法是,20px的值被视为一个单独的实体。在使用CSS自定义属性构建单个指令时,需要特别的小心。比如下面这段示例代码: :root { --size: 20}div { font-size: var(--size)px /* 错误使用 */}你可能已经预料到font-size的值会产生20px,但这是错误的使用方式。浏览器会将其解释为20 px。注意20和px之间有一个空格。 因此,如果你必须创建单个指令,则用一个CSS自定义属性来表示整个指令,比如--size:20px或者使用calc()函数,比如calc(var(--size) * 1px)(当--size设置为20时)。 如果你对这一点不怎么理解,没关系,在接下来的示例中会详细的解释这部分内容。 我们来动手做点东西这是我们这篇文章中一直期待的一部分。将能过构建一些有用的项目来实践前面所讨论到的相关概念。还等什么呢?我们开始吧。 使用CSS自定义属性创建组件变量假设我们要创建两个不同的按钮。这两个按钮的样式基本相同,只是略有一些细节不一样。 在这个示例中,只有background-color和border-color样式不同。如果你来做,你将会怎么做呢?这就是典型的解决方案。 创建一个基类,比如说.btn并添加变化的类。这个示例的结构如下: <button class="btn">Hello</button><button class="btn red">Hello</button>.btn基类涵盖了按钮的基本样式。比如: .btn { padding: 2rem 4rem; border: 2px solid black; background: transparent; font-size: 0.6em; border-radius: 2px;}.btn:hover { cursor: pointer; background: black; color: white;}那么,对于略有差异的按钮效果怎么来实现呢?看下面的代码: .btn.red { border-color: red}.btn.red:hover { background: red}你知道我们是如何复制代码的吧。不过我们使用CSS自定义属性来做会做得更好。那么要做的第一步将是什么呢? 使用CSS自定义属性替换不同的颜色,但不要忘记为其添加默认值。 .btn { padding: 2rem 4rem; border: 2px solid var(--color, black); background: transparent; font-size: 0.6em; border-radius: 2px;}.btn:hover { cursor: pointer; background: var(--color, black); color: white;}当你设置background:var(--color,black)时,其意思就是background的值是CSS自定义属性--color的值。当--color不存在时,就会使用其默认值black。 这就是给CSS自定义属性设置默认值的方法。就像JavaScript或其他编程语言一样。这样使用是很有意义的。 对于有差异的按钮,你只需要像下面这样提供CSS自定义属性的新值就可以: .btn.red { --color: red}这就是两个按钮所有的样式代码。现在,当你使用.red类名时,浏览器会解析出不同的颜色值,并立即更新按钮的样式效果。 如果你花大量时间构建可重用的组件,像这样使用CSS自定义属性就会很方便。来看看他们之间对比的截图: 如果在你的组件库中,还有其他风格的按钮效果,使用CSS自定义属性,你就可以省去很多额外的时间: 使用CSS自定义属性切换Web站点的皮肤切换Web网站的皮肤效果,我想你以前肯定有碰到过。比如像下面这样的效果: 那么这样的一个效果,使用CSS自定义属性能有多简单呢?我们来一起看看。 在此之前,我想先提一下,这个例子非常的重要。在这个示例中,将会涉及到使用JavaScript更新CSS自定义属性的一个方法。 我们真正想做的CSS自定义属性美妙之处在于它们的响应性。一旦它们被更新,只要属性的值使用了CSS自定义属性,就将会被更新。 从概念上讲,下面这张图,能很好的解释整个过程。 因此,需要通过JavaScript给按钮添加点击事件的监听。 对于这个简单的示例,都是基于CSS自定义属性来对整个页面的背景颜色和文本颜色做切换。也就是说,当用户点击上面的任一按钮时,他们将CSS自定义属性设置为其他颜色。因此,页面的背景颜色和文本颜色会做相应的变化,从而实现切换皮肤的效果。 模板结构页面所需的模板结果如下: <div class="theme"> <button value="dark">dark</button> <button value="calm">calm</button> <button value="light">light</button></div><article> ...</article>在.theme容器中包含了三个button。另外为了节约篇幅,把article元素中的内容省略了。 页面样式这个项目的成功之处就是页面的样式。而其中的诀窍又很简单。我们没有直接设置background-color和color的值,而是基于CSS自定义属性来给他们设置属性值。下面就是我想要表达的意思: body { background-color: var(--bg, white); color: var(--bg-text, black)}要实现切换皮肤的效果,原因很简单。每当单击一个按钮时,将要更改body中对应的两个CSS自定义属性的值。在更改之后,页面的整体样式将被更新。是不是非常的简单。 接下来,我们看看怎么通过JavaScript来实现CSS自定义属性值的更新。 添加JavaScript代码下面是这个示例效果所需的所有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 }}看到上面这一坨JavaScript代码,千万别吓到你。事实上这比你想像的要简单得多。 首先,通过const root = document.documentElement来获取根元素。这里的根元素指的就是<html>元素。明白这一点是非常重要的。如果你感到好奇,这并奇怪,因为它需要设置CSS自定义属性的新值。 同样的,可以通过const themeBtns = document.querySelectorAll('.theme > button')选到.theme元素下的所有button元素。querySelectorAll会生成一个类似数组的数据结构,需要对这个数组进行循环遍历。遍历每个按钮,并给其添加一个单击事件监听器。具体方法如下: themeBtns.forEach((btn) => { btn.addEventListener('click', handleThemeUpdate)})接下来我们解释一下handleThemeUpdate函数。每个按钮补点击时都会有一个handleThemeUpdate作为它的回调函数。注意,什么按钮被点击,然后执行正确的操作变得非常重要。 在此基础上,使用了一个operator开关器,并根据被单击的按钮的值执行一些操作。现在你再看一下JavaScript代码,你就能很轻易的理解它了。 构建CSS自定义属性展台接下来我们将要构建一个CSS自定义属性展台: 记住,盒子的颜色是动态更新的,并且盒子的容器在三维空间中旋转,而且是随着range输入的值做想应的角度旋转: 你可以在文章前面的示例中体验一下案例的效果。这是使用JavaScript更新CSS自定义属性的典型案例之一。 接下来,咱们一起看看这个案例是怎么实现的。 模板结构以下是所需的组件: - 一个range的输入框
- 存放指令的容器
- 包含其他输入框的容器,以及每个输入框所包含的输入字段
结构很简单: 有几个方面需要注意: - input type=range的值的范围是-50到50,每次移动的值是5,其最小输入值为-50
- 如果你不确定这个range输入是如何工作的,可以先查阅相关的文档
- 请注意如何使用.color-boxes和.color-box容器类名,在这些容器中存在input
- 值得一提的是,第一个input的默认值是red
了解了文档的结构之后,就可以这样做了: - 将.slider和.instructions容器设置为绝对定位,让其脱离文档流
- 给body元素设置一个background-color,并且在其左下角添加一个花的背景图
- 将.color-boxes容器放置在页面的正中心
- 给.color-boxes容器添加样式
先做这些处理吧。 /* 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;}代码并不像你想像的那么复杂。我希望你能理解它。如果你不理解上面的代码,那么你可以通过下面的评论与我一起交流和讨论。 对于body的效果需要更多的代码。由于我们使用background-color和background-image来给body设置样式。所以使用background的简写属性来设置多个背景可能是最好的一种选择。 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;}url指向的是向日葵图片的地址,接下来的一组属性0 100%表示背景图像的位置。接下来的内容简单的介绍了CSS背景图像定位的基本原理。 /后的另一部分表示background-size的值。如果你把这个值缩小,那么背景图像也会相应的缩小。no-repeat你可能知道其意思。它用来防止背景图像不重复铺满body元素。最后,逗号后面的任何东西都是用来声明第二个背景的。在我们这个示例中,第二个背景只设置了一个背景颜色,而且其值是var(--primary-color)。 你一看就知道,它就是一个CSS自定义属性。这也意味着你必须先声明这个CSS自定义属性。比如: :root { --primary-color: rgba(241,196,15 ,1)}--primary-color的原值是yellow。这没什么大不了的,接下来我们很快会在那里设置更多的CSS自定义属性。现在我们要做的是将.color-boxes放到页面的正中间: main.booth { min-height: 100vh; display: flex; justify-content: center; align-items: center;}main容器是一个Flex容器,并正确地将其子元素设置到页面的正中心位置。另外再把.color-boxes和他的子元素做得更好看一点。 .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); }设置了一个阴影效果。效果看上去有一些酷酷的感觉。咱们继续给.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}又是一坨代码,感觉好复杂的样子。事实上将其拆分一下,就会显得简单得多。 .color-boxes { background: var(--secondary-color); box-shadow: 10px 10px 30px rgba(0,0,0,0.4); border-radius: 0.3rem;}你知道这是什么吗?在这里有一个新的CSS自定义属性,我们应该将其添加到:root选择器中。 :root { --primary-color: rgba(241,196,15 ,1); --secondary-color: red;}第二种颜色是red。这将给容器设置一个red背景色。 接下来的代码可能会让部分同学感到困惑: .color-boxes { transform: perspective(500px) rotateY( calc(var(--slider) * 1deg)); transition: transform 0.3s}暂时,我们可以简化上面的transform属性的值。 例如: transform: perspective(500px) rotateY( 30deg);transform使用了两个不同的函数。一个是perspective(),另一个是rotateY()。那么这两个函数有什么作用呢? perspective()函数应用于3D空间中被变换的函数。它将激活三维空间,并在z轴上赋予元素深度。 有关于perspective()这方面更多的资料,你可以点击这里或这里进行了解。
rotateY()函数又是怎么一回事呢?通过perspective()函数激活的三维空间中,元素有x、y、z等平面,其中rotateY()函数会让元素沿着y平面旋转。 下图来自于codrops的图,能更好的帮助你理解这方面相关的知识。 有关于transform方面更多的介绍,可以点击这里进行了解。
我希望这些能帮助你消除一些压力。那我们回到开始的地方吧。 当你移动滑块时,你知道什么函数会影响.container-box的旋转吗? 它会被调用的rotateY()函数,让这个盒子沿着Y轴旋转。由于传入rotateY()函数的值将是通过JavaScript来更新,因此它的值应该用一个CSS自定义属性来表示。 那么为什么用1deg乘以这个CSS自定义属性呢? 从经验上来说,建议构建单一的指令时,将值存储在没有带单位的CSS自定义属性中。然后通过calc()函数将它们转换成任何你想要的单位。 当你有这些值的时候,你可以用这些值做任何你想做的事情。想要转换成deg或vw,你都可以任意选择。 在这种情况下,通过将number值乘以1deg来把数字转换成带有单位的值。 由于CSS是不理解数学计算的,所以你必须通过calc()函数来完成。一旦完成,我们就变得容易多了。这个变量的值可以在JavaScript中进行更新。 对于CSS来说,现在只剩下一点点了。 .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)}首先使用:nth-child选择器来选择每个子元素。 这里你需要有一些远见。我们知道我们将更新每个盒子的背景颜色。我们还知道,这个背景颜色必须由一个CSS自定义属性来表示,所以它可以通过JavaScript来访问。对吧。 因此,我们可以这样做: .color-box:nth-child(1) { background: var(--bg-1)}非常容易的一件事。不过有一个问题。如果这个变量不存在,又会发生什么呢?根据前面介绍的内容,针对这一问题,我们需要做一个降级处理。就是添加一个默认颜色,比如像下面这样: .color-box:nth-child(1) { background: var(--bg-1, red)}在这个特殊的案例中,我选择不提供任何的降级处理。 如果在属性值中使用CSS自定义属性无效,则该属性将接受其初始值。这一点前面已经提到过了。因此,当--bg-1无效或不可用时,background将默认为其初始值transparent. 初始值是指当属性没有显式设置时的值。例如,如果不设置元素的背景颜色,它将默认为transparent。初始值是一种默认的属性值。 加入一些JavaScript代码对于JavaScript代码,我们要做的事情会很少。 首先让我们来处理滑块。仅只需要五行代码就可以了。 const root = document.documentElementconst range = document.querySelector('.booth-slider')range.addEventListener('input', handleSlider)function handleSlider (e) { let value = e.target.value root.style.setProperty('--slider', value)}这对你而言是不是很简单,对吧。 首先,通过const range = document.querySelector('.booth-slider')选到了滑块元素。然后使用range.addEventListener('input', handleSlider)给input元素添加一个监听事件,当input的范围值得到改变时,将会调用handleSlider回调函数。 接下来做的就是编写handleSlider回调函数: function handleSlider (e) { let value = e.target.value root.style.setProperty('--slider', value)}root.style.setProperty('--slider', value)的意思是获取根元素的style样式,然后设置其属性值。 处理颜色变化就像处理滑块值的变化一样简单。 const inputs = document.querySelectorAll('.color-box > input')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)}通过const inputs = document.querySelectorAll('.color-box > input')获取所有input元素。然后给所有input设置一个事件监听器: inputs.forEach(input => { input.addEventListener('input', handleInputChange)})写handleInputChange回调函数: function handleInputChange (e) { let value = e.target.value let inputId = e.target.parentNode.id let inputBg = `--bg-${inputId}` root.style.setProperty(inputBg, value)}唷,唷,唷.......就是这么的简单。全部搞定! 还错过了什么当我注意到我在任何地方都没有提到浏览器对CSS自定义属性的支持时,我已经完成了这篇文章的初稿。现在也该来收拾一下相应的残局了。 浏览器对CSS自定义属性的支持并不坏。可以说相当的不错,到目前为止所有的现代浏览器中都对CSS自定义属性做了良好的支持。在写这篇文章的时候,已经超过87%了。 那么问题来了,我现在可以在项目中使用CSS自定义属性了?我的回答是的!不过,一定要检查一下你自己的用户群体。 值得庆幸的是,你可以使用Myth这样的处理器。它将把一些CSS未来的特性做了相应的处理。言外之意,还未支持的CSS特性,你现在就可以使用,听起来是不是很爽。难道不是吗? 如果你有使用PostCSS的经验,那么这同样是使用未来CSS的一个很好的方法。这里有一个CSS自定义属性的PostCSS模块。 那今天就到这里吧。这就是我要和大家聊的东西,有关于CSS自定义属性,应该掌握的一些知识点。 著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.w3cplus.com/css/everything-you-need-to-know-about-css-variables.html © w3cplus.com |