本文首发于我的博客

一直以来,CSS作为一种申明式的样式标记语言,很难像如javascript等命令式编程语言一样通过定义和使用变量的方式来维护和追踪某些状态。后来随着scss,less等CSS预处理器的出现,我们可以像优秀的开源框架bootstrap那样,通过维护一个_variables.scss变量文件的方式来维护一个庞大的项目。但预处理需要编译,并非CSS原生支持。而现在,我们可以在原生CSS中使用变量了

先来两个在线demo感受一下:

定义

CSS变量,也称为CSS自定义属性。通过以--开头的自定义属性来设置变量名,存储一些特定值,在需要的地方使用 var() 来访问。如:

p {
--primary-color: #6bc30d;
color: var(--primary-color);
}

如何申明变量

可以像定义任何css属性一样来申明变量,不同的是,变量名必须以--开头。如 --primary-color: #6bc30d

如何使用变量

而要使用一个变量的值,需要使用 var() 函数,并将变量的名称作为参数传入。 如 color: var(--primary-color);

var()函数

var()函数可以代替元素中任何属性中的值的任何部分。

var() 函数接受两个参数,参数一是要替换的自定义属性的名称,参数二是可选的,作为参数一无效时候的回退值(如果第一个参数引用的自定义属性无效,则该函数将使用第二个值)。

var( <custom-property-name> [, <declaration-value> ]? )
/*<custom-property-name> 自定义属性名*/
/*<declaration-value> 声明值(回退值)*/

使用变量的意义

  • 无需多次定义,同样的属性可以重复使用
  • 让CSS文件可读易维护(如主题样式,只需修改一个变量即可,而不再是枯燥的查找替换),灵活性更高

注意点

  • 变量名称必须以 -- 开头
  • 变量只能存储一个属性的值,而不能用来存储一个属性,如下例子是错误的:
/*这样是错误的*/
p {
--primary-color: color;
var(--primary-color) : #6bc30d
}
  • 变量中无法使用加减等数学方法,如果需要使用计算,则可以使用 calc 函数:
/*这样是错误的*/
p {
--font-size : 20px * 2;
font-size: var(--font-size);
}
/*这样是正确的*/
p {
--font-size : calc(20px * 2);
font-size: var(--font-size); /*40px*/
}
/*这样拼接也是无效的*/
p {
--font-size: 20;
font-size: var(--font-size)px; /*无效*/
}
/*这样是有效的:*/
p {
--font-size: 20;
font-size: calc(var(--font-size) * 1px); /*20px*/
}
  • CSS变量是区分大小写的
/*这是两个不同的变量*/
:root {
--color: blue;
--COLOR: red;
}

scss等CSS预处理中变量的区别

  • CSS变量是浏览器原生支持的,不需要经过编译就可以使用
  • CSS变量是DOM的一部分,可以使用JS直接修改

作用域

虽然可以在css的任何地方定义变量,但是css变量也是有作用域的。CSS的变量作用域分为全局作用域和局部作用域。因此在申明一个变量之前,首先要确定这个变量要用在哪里?

全局变量

通过在:root中申明变量,就可以申明一个全局变量,可以在整个文档结构中使用这个变量,因为CSS变量是可继承的。

:root{
--primay-color: #6bc30d;
}
/* 在任何地方都可以使用`:root`中定义的全局变量 */
p, div , a {
color : var(--primay-color);
}
#myDiv, .myDiv {
color : var(--primay-color);
}

局部变量

可以在除:root外的任何地方申明局部变量。但是局部变量只能够在被申明的元素及其子元素中使用。局部变量更多的应用在值覆盖上。

.modal {
--modal-padding-top: 30px;
}
/*当前元素及其子元素中使用*/
.modal,
.modal-content {
padding-top: var(--modal-padding-top); /*30px*/;
}
/*在其他元素上无效*/
body {
padding-top: var(--modal-padding-top); /*无效设置,使用默认值*/
}

变量的继承

与其他CSS属性一样,CSS中的变量也是可以继承的。

:root{
--color: red;
}
P {
--pColor: green;
color: var(--color); /*red*/
}
p > span{
color : var(-pColor); /*green*/
}

多个申明中变量的优先级

同名变量可以重复申明,这样变量就会有了优先级的问题,如下例子:

:root {
--color: red;
}
div {
--color: green;
}
#myDiv {
--color: yellow;
--color: blue;
}
* {
color: var(--color);
}
<p>我正常显示红色</p>
<div>我显示绿色</div>
<div id="myDiv">
我显示蓝色
<p>那么我呢?</p>
</div>

如图,div中的局部变量覆盖了:root中设置的值,而特定ID的div元素#myDiv又覆盖了div中的值,最后作为#myDiv的子元素p继承了其父级的值,而不是使用root中申明的值

无效变量

对于变量来讲,CSS属性的有效性并不适用。对于变量这种自定义属性,即便在上下文环境中这个值是无意义的,但是都能够通过var()函数调用。无意义的变量值会导致无效的CSS申明。通过var()函数调用后会被解析为初始值。

:root {
--color: 20px;
}
p {
--font-size: green;
background-color: var(--color);
/* background-color: 20px; 无效,将回退为transparent */
}

在html属性中使用css变量

就像其他CSS属性一样,在html中可以通过内联变量来设置变量的值,并且也能够正常工作

<style>
p {
color: var(--color);
}
</style>
<body>
<p style="--color:red; --font-size: 50px; font-size:var(--font-size);">
我使用内联变量值得方式来设置样式
<!-- 将显示为字号50px,颜色红色 -->
</p>
</body>

在媒体查询中使用css变量

可以根据屏幕宽度的变化来改变变量的值,从而更容易的实现响应式布局。

:root {
--font-size: 30px;
--color: red;
}
html{
color: var(--color);
font-size: var(--font-size);
} @media screen and (min-width: 480px) {
:root {
--font-size: 50px;
--color: green;
}
}
@media screen and (min-width: 760px) {
:root {
--font-size: 100px;
--color: blue;
}
}

在js中使用css变量

css变量是DOM的一部分,这意味着我们可以通过javascript来访问/修改css变量的值,这是scss等css预处理器所做不到的。
要用JavaScript来更新CSS变量,需要调用已声明变量元素上的style对象上的 setProperty 方法。

setProperty()

//语法
element.style.setProperty(propertyName, value, priority);
//propertyName 是一个 DOMString 被更改的CSS属性.
//value <可选> 是一个 DOMString 新的属性值. 如果没有指定, 则当作空字符.不能包含 "!important"
//priority <可选> 是一个 DOMString。允许 "important" CSS 优先被设置. 如果没有指定, 则当作空字符. //在根元素(html)上更新变量值
document.documentElement.style.setProperty(propertyName, value)

示例

:root {
--font-size: 20px;
--background: red;
}
body {
font-size: var(--font-size);
background-color: var(--background);
color: #fff;
}
<h1>使用JavaScript来改变背景色</h1>
<button data-value="red">红色</button>
<button data-value="green">绿色</button>
<button data-value="blue">蓝色</button>
<button data-value="yellow">黄色</button> <script>
let $buttons = document.querySelectorAll('button')
$buttons.forEach(button => {
button.addEventListener('click', () => {
let value = button.dataset.value
document.documentElement.style.setProperty('--background', value)
})
})
</script>

参考文档

本文首发于我的博客

在原生CSS中使用变量的更多相关文章

  1. 原生css 中变量的使用

    前两天看到阮大神的一篇在css中使用变量的文章,整理了一下. 这个重要的 CSS 新功能,所有主要浏览器已经都支持了.本文全面介绍如何使用它,你会发现原生 CSS 从此变得异常强大. 一.变量的声明 ...

  2. 如何在CSS中使用变量

    前言 CSS变量(官方称为自定义属性)是用户定义的值,它可以在你的代码库中设置一次并多次使用.它们使管理颜色.字体.大小和动画值变得更加容易,并确保整个web应用的一致性. 举个例子,你可以将品牌颜色 ...

  3. css中定义变量

    css中定义变量 定义变量可分多种情况: 1.定义全局变量 :root { --borderColor: #ccc;} 2.定义某元素下的变量 .look{ --borderColor: #ccc;} ...

  4. css中使用变量

    2017年3月,微软宣布 Edge 浏览器将支持 CSS 变量.这个重要的 CSS 新功能,所有主要浏览器已经都支持了. 声明css变量的时候,变量名前面要加两根连词线(--).变量名大小写敏感,-- ...

  5. CSS中的变量使用,var()语法

    参考博客:https://blog.csdn.net/qq_34206361/article/details/53690414

  6. 关于原生js中函数的三种角色和jQuery源码解析

    原生js中的函数有三种角色: 分两大种: 1.函数(最主要的角色)2.普通对象(辅助角色):函数也可以像对象一样设置属于本身的私有属性和方法,这些东西和实例或者私有变量没有关系两种角色直接没有必然的关 ...

  7. 原生 CSS 网格布局学习笔记

    下是来自Oliver Williams的帖子. Oliver已经学习了相当长时间的原生CSS网格,可以说是在CSS网格方面有一定的发言权.在这篇文章中,他将以非同寻常的思路分析自己的CSS网格布局学习 ...

  8. 使用CSS中的meta实现web定时刷新或跳转的方法

    这篇文章主要介绍了使用CSS中的meta实现web定时刷新或跳转的方法,比使用JavaScript脚本实现起来更加简单一些,需要的朋友可以参考下 meta源信息功能之页面定时跳转与刷新 几乎所有的网页 ...

  9. 1:CSS中一些@规则的用法小结 2: @media用法详解

    第一篇文章:@用法小结 第二篇文章:@media用法 第一篇文章:@用法小结 这篇文章主要介绍了CSS中一些@规则的用法小结,是CSS入门学习中的基础知识,需要的朋友可以参考下     at-rule ...

随机推荐

  1. kibana实现条件查询和修改

    GET jyb_report_index_preprod/_search { "query": { "match": { "report_id&quo ...

  2. 走进第四范式:决策类AI企业的生存之道

    根据不同的应用领域,人工智能行业可以分为视觉类人工智能.语音及语义类人工智能和决策类人工智能. 通常,我们接触的都是视觉类.语音类的人工智能,它们主要用来帮助人类执行具体任务,例如人脸识别,语音控制等 ...

  3. Qt:如何生成可执行文件

    参考 (18条消息) QT5的程序打包发布(将QT5的工程项目打包成一个exe程序)_kslly的专栏-CSDN博客 环境配置 Windows 10系统 MSVC 2017编译器 工具 Qt 5自带的 ...

  4. linux作业--第二周

    1.显示/etc目录下,以非字母开头,后面跟了一个字母以及其它任意长度任意字符的文件或目录 ls /etc/ | grep ^[^[:alpha:]][[:alpha:]].* 2.复制/etc目录下 ...

  5. 记录一次docker容器内修改my.cnf配置文件max_allowed_packet参数的过程

    1. 问题背景 在一次新版本功能开发完毕,配合测试的过程中,测试反馈某个XxlJob定时任务一直执行失败,在分析了日志之后,找到了报错的原因: Packet for query is too larg ...

  6. PhpStrom 常用的插件

    .env files support 可以在env函数使用是提示.env文件中所有的key值的自动完成功能 Markdown support 在编写.md文件时有预览的功能 PHP composer. ...

  7. Re:《Unity Shader入门精要》13.3全局雾效--如何从深度纹理重构世界坐标

    如何从深度纹理重构世界坐标 游戏特效,后处理是必不可少的,而后处理经常需要我们得到当前画面的像素对应世界空间的所有信息. 思路 通过深度纹理取得NDC坐标,然后再通过NDC坐标还原成世界空间坐标 // ...

  8. python的matplotlib.pyplot绘制甘特图

    博主本来就想简单地找一下代码,画一幅甘特图,结果百度之后发现甘特图的代码基本都不是用matplotlib库,但是像柱状图等统计图通常都是用这个库进行绘制的,所以博主就花了一些时间,自己敲了一份代码,简 ...

  9. 说说UI自动化中的PO模式

    PO模式,全称PageObject模式,即页面对象模式.将页面定位与业务操作分离. po模式有以下几个优点: 1.易读性好 2.扩展性高 3.复用性强 4.维护性好 5.代码冗余率低 了解了po模式及 ...

  10. 【freertos】002-posix模拟器设计与cortex m3异常处理

    目录 前言 posix 标准接口层设计 模拟器的系统心跳 模拟器的task底层实质 模拟器的任务切换原理 cortex M3/M4异常处理 双堆栈指针 双操作模式 栈帧 EXC_RETURN 前言 如 ...