# CSS自定义属性 - 变量的声明与读取

> 变量这个词在程序开发中基本都会用到，我们可以对其赋值，也可以存储且获取它。如果将其应用在CSS样式表中，又当如何呢？以前大家基本借助SCSS或LESS中变量定义亦或直接定义类。所以，今天看看原生CSS中如何自定义属性（即：CSS变量）应用。

Author: DeathGhost
Published: 2021-09-17 21:19:04
Category: css
Canonical: https://www.deathghost.cn/article/css/102
Keywords: CSS, CSS variable, CSS 自定义属性, CSS变量, var() 函数, calc() 函数, 作用域, 全局变量, 局部变量, 复用

Web前端项目开发过程中都会有大量的CSS代码，通常也会有许多重复的值；许多人在编写过程中都觉得很繁琐。因为产品项目设计过程中字号、颜色、边距及其他都是有一定的统一性，我们会对其预定义；所以为了避免对属性值的重复书写，都会借助外部工具（SCSS/LESS）进行编译处理；优点就是书写方便、好维护；缺点就是得额外配置。

虽然我个人只是简单的借助SCSS编写样式，但不得不说 - 真方便！

![CSS自定义属性 - 变量的声明与读取](https://www.deathghost.cn/public/upload/article/2021/09/17/1631891594177469.jpg)

CSS自定义属性 - 变量的声明与读取

那么，下面了解下关于原生CSS变量的应用。

## 变量声明

声明一个变量（自定义属性）时，属性名需要以两个减号（--）开始。

element {
  --c-999: #999;
}
上述代码中，在某一元素中定义一个变量为 --c-999 ，值为颜色值。当然，变量可以给其赋任何值（字符串、数字、CSS属性值等等）。

全局性预定义的，一般会定义在根节点（根伪类）。

:root{
  --default-width: 50vw;
  --c-primary: #222;
  --c-666: #666;
  --c-999: #999;
  --f-12: 12px;
  --f-14: 14px;
  --f-16: 16px;
  --step: 5;
}
变量设定完毕后，就需要在设定样式中读取它。

## var() 函数读取变量

var() 函数可以代替元素中任何属性中的值的任何部分。var() 函数不能作为属性名、选择器或者其他除了属性值之外的值。

var( <custom-property-name> , <declaration-value>? )
自定义属性的回退值允许使用逗号。即：可以使用第二个参数，表示变量的默认值。如果该变量不存在，就会使用这个默认值。

--c-primary: black;
...
color: var(--non-existent, --c-primary);
自定义属性备用值:: 如果'--non-existent'变量未定义，颜色则为：黑色。

另外，如果声明变量值为数值需要与CSS值进行计算，不能直接使用，如下：

:root{
  --step: 5;
}
假设需要对元素.main设置内边距。

.main{
  padding: var(--step) px;
}
// ❌ 这样设置是无效的
这时，需要CSS中的 calc() 函数进行处理。

.main{
  padding: calc(var(--step) * 1px);
}
// ✔️ 这样设置，方才有效

## 作用域 - 全局定义 与 局部定义

可以在根部定义，也可以在元素内部定义（或变更值）。如上述:root 或 某一元素下定义。

:root{
  --default-width: 50vw;
}
.main{
  --default-width: 40vw;
}
至于优先级，如上述，.main 类下元素引入优先级高，这个和平时写CSS一致。

## 内联样式变量重新赋值

根据上述，可以在元素内部定义变量优先级就相应提升；这里还可以对元素style属性重新对变量进行赋值，优先级则进一步提升。

// 全局定义 --c-999: #999 优先级 +1
// footer 下定义 --c-999: #blue 优先级 +1
// 内联重新赋值 优先级 +1
<footer style="--c-999: red">
    <p>footer</p>
    <p >&copy; 2021 DeathGhost</p>
</footer>
所以，最终颜色值将会是 red （红色），在这里，变量名仅示例，字面意思已不合适😅。

## JavaScript 读取变量与赋值

可以通过JavaScript获取变量值与更改变量值，优先级方面 +1

### 获取 --c-999 变量值

<footer style="--c-999: red">
  <p>footer</p>
  <p >&copy; 2021 DeathGhost</p>
</footer>
const footerVar = document.querySelector('footer');
getComputedStyle(footerVar).getPropertyValue('--c-999');
得到的结果将是 red （红色）。

### 重新对 --c-999 变量赋值 （如：'skyblue' 天蓝色）

footerVar.style.setProperty('--c-999', 'skyblue');
getComputedStyle(footerVar).getPropertyValue('--c-999')
得到的结果将是 skyblue （天蓝色）

### 获取全局 --c-999 变量值

getComputedStyle(document.documentElement).getPropertyValue('--c-999');
则是：#999

## 示例代码

<html>
<head>
  <meta charset="utf-8">
  <title>CSS自定义属性 - 变量</title>
  <style>
    /* 根伪类 */
  :root{
    --default-width: 50vw;
    --c-primary: #222;
    --c-666: #666;
    --c-999: #999;
    --f-12: 12px;
    --f-14: 14px;
    --f-16: 16px;
    --step: 5;
  }

    header,
    main,
    footer{
      width: var(--default-width);
      margin: 0 auto;
    }

    header{
      font-size: var(--f-16);
    }

    main{
      /* 自定义属性备用值:: 如果'--non-existent'变量未定义，颜色则为：黑色 */
      /* 用 var() 函数可以定义多个备用值(fallback value)，当给定值未定义时将会用备用值替换。 */
      color: var(--non-existent, --c-primary);
      font-size: var(--f-14);
      /* 数值变量可通过calc进行处理；不可以var(--step) px; */
      padding: calc(var(--step) * 1px);
    }

    footer{
      /* 内联样式将会覆盖此定义 （e.g. style="--c-999: red"）*/
      font-size: var(--f-12);
      color: var(--c-999);
    }
  </style>
</head>

<body>
  <header>
    <h1>header</h1>
  </header>
  <main>
    <h2>main</h2>
    <p>main content...</p>
  </main>
<footer style="--c-999: red">
  <p>footer</p>
  <p >&copy; 2021 DeathGhost</p>
</footer>
  <script>
    const footerVar = document.querySelector('footer');
    getComputedStyle(footerVar).getPropertyValue('--c-999');
    console.log('内联重新赋值：', getComputedStyle(footerVar).getPropertyValue('--c-999'));
    footerVar.style.setProperty('--c-999', 'skyblue');
    console.log('JS重新赋值：', getComputedStyle(footerVar).getPropertyValue('--c-999'));
    // 获取全局定义变量
    getComputedStyle(document.documentElement).getPropertyValue('--c-999');
    console.log('获取全局定义变量:', getComputedStyle(document.documentElement).getPropertyValue('--c-999'));
    // 附加
    // scss 变量  $c-primary : #222;
    // scss 变量  @c-primary : #222;
  </script>
</body>
</html>

## 应用场景

全局元素边距(内外边距"5px"、"10px"、"15px"...)、颜色（"成功"、"失败"、"警告"、"错误"...）、字号("small"、"middle"、"large"...)、响应式（"PC端"、"移动端"...）等页面变量定义。

## 兼容性

直接点，放弃IE吧，使用现代浏览器均已支持！🙃

## Related

- Previous: [:is() - 告别讨厌的选择器重复](https://www.deathghost.cn/article/css/101)
- Next: [CSS container容器查询](https://www.deathghost.cn/article/css/112)
