# css变量

## css变量

### 声明css变量

声明一个css变量和声明一个css属性一样，只不过约定css变量名必须是以`--`开头。

```css
:root{
  --main-color: #ffffff;
  --main-bg: rgb(0, 0, 0);
}
```

css变量具有作用域的概念，同一个 CSS 变量，可以在多个选择器内声明。读取的时候，优先级最高的声明生效。这与 CSS 的"层叠"（cascade）规则是一致的。

```css
<style>
  :root { --color: blue; }
  div { --color: green; }
  #alert { --color: red; }
  * { color: var(--color); }
</style>

<p>蓝色</p>
<div>绿色</div>
<div id="alert">红色</div>
```

上面代码中，三个选择器都声明了`--color`变量。不同元素读取这个变量的时候，会采用优先级最高的规则，因此三段文字的颜色是不一样的。

css变量对大小写敏感，`--blue`和`--Blue`是两个不同的变量

### 使用css变量

`var()`用于读取变量，它接收两个参数，第一个参数是要读取的变量名，第二个参数是默认值，当变量未定义时使用默认值。

```css
color: var(--foo, #333);
```

第二个参数可以出现逗号或空格，这些都被视作参数的一部分。

```css
var(--font-stack, "Roboto", "Helvetica");
var(--padding-trb, 10px 5px 8px);
```

当浏览器遇到无效的css变量时，会使用默认值或继承值。

```css
:root { --text-color: 16px; }
p { color: blue; }
p { color: var(--text-color); }
```

浏览器将 `--text-color` 的值替换给了 `var(--text-color)`，但是 `16px` 并不是 [`color`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/color) 的合法属性值。代换之后，该属性不会产生任何作用。浏览器会执行如下两个步骤：

1. 检查属性 color 是否为继承属性。是，但是 `<p>` 没有任何父元素定义了 color 属性。转到下一步。
2. 将该值设置为它的**默认初始值**，比如 black。

### css变量的作用

css变量适用范围非常广，下面讨论一下一些非常有用的场景。

#### 多主题

css变量可以制作多主题网站，比如网站的暗黑模式，我们将各组件的颜色存放到css变量中，如果要改变网站主题颜色只要改动css变量值就可以了。

```css
--bodyColor: #fff;
--bodyFontColor: #000;
/* 暗色模式 */
--bodyColor: #000;
--bodyFontColor: #fff;
```

通过动态的修改css变量，可以很方便地修改网站主题。

知名的跨平台移动app开发框架——Ionic就是采取这种方式实现。下面是Ionic官网文档的原话和翻译。

> Ionic components are built with [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) for easy customization of an application. CSS variables allow a value to be stored in one place, then referenced in multiple other places. They also make it possible to change CSS dynamically at runtime (which previously required a CSS preprocessor). CSS variables make it easier than ever to override Ionic components to match a brand or theme.
>
> Ionic组件是通过css变量构建的，这使应用程序的定制变得简单。css变量允许在一个地方存储一个值，然后在其他多个地方引用。这也使得动态改变css变为可能(在过去需要借助css预处理器)，css变量让覆盖Ionic组件以匹配品牌或主题变得比以往更容易。

**可见css变量最重要的是可以在不使用css预处理器的前提下动态地修改css。**

#### 响应式

css变量可以实现响应式布局，我们看一下这个网站[Infinity 主页 (inftab.com)](https://inftab.com/)

这个网站定义了很多css变量，并且网站的很多组件都由这些变量来控制，那么这时只要改变了这些css变量就能达到改变css的目的。

![image-20211230225528320](https://raw.githubusercontent.com/const-love-365-10000/cloudImg/master/img/image-20211230225528320.png)

看css变量`--icon-box-width`，当我们拉动缩小窗口时，这个值也会跟着缩小，从而使组件也跟着缩小。

![image-20211230225602438](https://raw.githubusercontent.com/const-love-365-10000/cloudImg/master/img/image-20211230225602438.png)

### 操作css变量

#### 媒体查询

可以借助媒体查询达到修改css变量的目的。

```css
body {
    --primary: #7f583f;
}
@media screen and (min-width: 768px) {
    body {
        --primary: #f7efd2;
    }
}
body {
    background-color: var(--primary);
}
```

![image-20211230225015266](https://raw.githubusercontent.com/const-love-365-10000/cloudImg/master/img/image-20211230225015266.png)

![image-20211230225032144](https://raw.githubusercontent.com/const-love-365-10000/cloudImg/master/img/image-20211230225032144.png)

#### JavaScript操作css变量

可以通过JavaScript读取、设置和修改css变量

JavaScript 操作 CSS 变量的写法如下。

```javascript
// 设置变量
document.body.style.setProperty('--primary', '#7F583F');

// 读取变量
document.body.style.getPropertyValue('--primary').trim();
// '#7F583F'

// 删除变量
document.body.style.removeProperty('--primary');
```

## 参考

[CSS 变量教程 - 阮一峰的网络日志 (ruanyifeng.com)](https://www.ruanyifeng.com/blog/2017/05/css-variables.html)

[使用CSS自定义属性（变量） - CSS（层叠样式表） | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties)

[Open-Source UI Toolkit to Create Your Own Mobile or Desktop Apps (ionicframework.com)](https://ionicframework.com/docs/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://1425816423.gitbook.io/my-knowledge-base/za-xiang/css/css-bian-liang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
