本文首发于我的博客

一直以来,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. GBDT 梯度提升决策树简述

    首先明确一点,gbdt 无论用于分类还是回归一直都是使用的CART 回归树.不会因为我们所选择的任务是分类任务就选用分类树,这里面的核心是因为gbdt 每轮的训练是在上一轮的训练的残差基础之上进行训练 ...

  2. petite-vue源码剖析-属性绑定`v-bind`的工作原理

    关于指令(directive) 属性绑定.事件绑定和v-modal底层都是通过指令(directive)实现的,那么什么是指令呢?我们一起看看Directive的定义吧. //文件 ./src/dir ...

  3. Springboot循环依赖实践纪实

    测试的Springboot版本: 2.6.4,禁止了循环依赖,但是可以通过application.yml开启(哈哈) @Lazy注解解决循环依赖 情况一:只有简单属性关系的循环依赖 涉及的Bean: ...

  4. HarmonyOS UI组件在线预览,程序员直呼“不要太方便~”

    一.介绍 以往大家如果想查看组件的使用效果,需要打开DevEco Studio构建工程.现在为了便于大家高效开发,文档上线了JS UI组件在线预览功能,无需本地构建工程,在线即可修改组件样式等参数.一 ...

  5. JavaScript面向对象—对象的创建和操作

    JavaScript面向对象-对象的创建和操作 前言 虽然说在JavaScript编程语言中,函数是第一公民,但是JavaScript不仅支持函数式编程,也支持面向对象编程.JavaScript对象设 ...

  6. 基于ESP8266+BY8301语音模块的与山地车捉迷藏的小项目

    基于ESP8266+BY8301语音模块的与山地车捉迷藏的小项目 写在前面: 不知道大家有没有经历过,在茫茫车海中找不到自己山地车情况,针对这个痛点(开玩笑的),我做了个小玩意,纯属娱乐,拿出来,在疫 ...

  7. mysql破解root口令

    破解root口令 [root@centos8 ~]#vim /etc/my.cnf [mysqld] skip-grant-tables #取消密码验证 skip-networking # mysql ...

  8. 巧用 CSS 构建渐变彩色二维码

    今日,群里有个很有意思的问题,问我如何实现一个彩色的,带渐变的二维码,像是这样: 很有意思的问题,我们在百度谷歌,搜索 qrcode,能搜到非常多在线制作二维码的工具,它们其中一些也会带有制作渐变二维 ...

  9. Dapr集成之GRPC 接口

    Dapr 为本地调用实现 HTTP 和 gRPC API . 通常大家第一时间想到的是通过 gRPC 调用 Dapr,更重要的一点是Dapr 也可以通过 gRPC 与应用程序通信. 要做到这一点,原理 ...

  10. centos7下mysql安装

    centos7只包含了mariadb的安装源 我们需要到官方下载社区版:https://dev.mysql.com/downloads/ 下载安装包并上传到服务器 安装出现错误 这个是系统自带的Mar ...