css变量: 我真的蛮厉害的~

632 阅读4分钟

先有问题再有答案

  1. css变量设计的目的是什么?
  2. css变量如何声明与使用?
  3. 该如何理解变量的作用域?
  4. css变量的作用域有什么特点?
  5. 有人说css变量是css与js的桥梁 这个理解对嘛?

设计目的

  • 提高代码的可维护性:通过定义变量,可以将常用的值(如颜色、字体大小等)集中管理,便于维护和修改。
  • 增强灵活性:变量可以在多个地方重复使用,减少代码冗余。
  • 支持动态样式:CSS 变量可以通过 JavaScript 动态修改,从而实现动态样式变化。
  • 模块化开发:通过局部变量,可以实现模块化的样式管理,避免全局污染。

使用方式

  1. 声明 CSS 变量 CSS 变量以 -- 开头,定义选择器中。
:root {
  --primary-color: #3498db;
  --font-size: 16px;
}
  1. 使用 CSS 变量 通过 var() 函数使用 CSS 变量。
body {
  color: var(--primary-color);
  font-size: var(--font-size);
}

变量作用域

CSS 变量具有作用域,分为全局变量和局部变量。

全局变量

定义在 :root 中的变量是全局的,可以在整个文档中使用。

:root {
  --global-color: #2ecc71;
}

body {
  color: var(--global-color);
}

局部变量

局部变量可以在任何选择器中定义,例如类选择器、ID 选择器或元素选择器。

局部变量的作用域仅限于定义它的选择器及其子元素。

如果在其他选择器中使用未定义的局部变量,则不会生效。

<div class="container">
  <p>这是一个段落。</p>
</div>

<div class="another-container">
  <p>这是另一个段落。</p>
</div>


.container {
  --local-color: #e67e22;
}

.container p {
  color: var(--local-color); /* 生效 */
}

.another-container p {
  color: var(--local-color); /* 不生效,因为 --local-color 未在 .another-container 中定义 */
}

CSS 变量遵循 CSS 的优先级规则。

如果同一个变量在多个作用域中定义,离目标元素最近的定义会生效。

<div class="container">
  <p>这是一个段落。</p>
  <div class="inner-container">
    <p>这是内部段落。</p>
  </div>
</div>

.container {
  --local-color: #e67e22;
}

.inner-container {
  --local-color: #3498db;
}

.container p {
  color: var(--local-color); /* 外部段落颜色为 #e67e22 */
}

.inner-container p {
  color: var(--local-color); /* 内部段落颜色为 #3498db */
}

局部变量的模块化开发.

局部变量非常适合用于模块化开发,每个模块可以定义自己的变量,避免全局污染。

<div class="module-a">
  <p>模块 A 的段落。</p>
</div>

<div class="module-b">
  <p>模块 B 的段落。</p>
</div>

.module-a {
  --local-color: #e67e22;
}

.module-a p {
  color: var(--local-color);
}

.module-b {
  --local-color: #3498db;
}

.module-b p {
  color: var(--local-color);
}

变量的默认值

在使用 var() 函数时,可以为变量提供默认值。如果变量未定义,则使用默认值。

.container {
  /* --local-color 未定义 */
}

.container p {
  color: var(--local-color, #e67e22); /* 使用默认值 #e67e22 */
}

css&js的桥梁

CSS 变量可以被视为 CSS 与 JavaScript 之间的桥梁。通过 JavaScript 动态修改 CSS 变量,可以实现许多动态样式变化的能力。

js传值给css实现动态变化

录屏2025-02-12 14.26.42.gif

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS 变量与 JS 交互</title>
  <style>
    :root {
      --primary-color: #3498db;
    }

    body {
      background-color: var(--primary-color);
      transition: background-color 0.5s;
    }

    button {
      margin-top: 20px;
    }
  </style>
</head>
<body>
  <button id="changeColor">改变背景颜色</button>

  <script>
    const button = document.getElementById('changeColor');
    const root = document.documentElement;

    button.addEventListener('click', () => {
      const newColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
      root.style.setProperty('--primary-color', newColor);
    });
  </script>
</body>
</html>

点击按钮时,js世界的变量通过注入css变量的方式 动态改变了css的值,实现背景颜色会随机变化。

与animation配合实现强大的动画能力

将一个矩形 通过animation动画移动到一个指定距离嘛 距离是动态获取的可能是50px 可能是200px具体值不定。如果我们想使用animation的keyframes能力 如何实现这个功能?

anivar.gif

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>矩形移动动画</title>
    <style>
        #rectangle {
            width: 100px;
            height: 80px;
            background-color: red;
            position: absolute;
            top: 0;
            left: 0;
        }

        .btn {
            margin-top: 100px;
        }

        @keyframes move {
            20% {
                left: 30px;
            }

            100% {
                /* 使用 CSS 变量动态设置终点 */
                left: var(--target-distance);

            }
        }
    </style>
</head>

<body>
    <div id="rectangle"></div>
    <button id="moveButton">移动矩形</button>
    <button class="btn" id="changeButton">切换状态</button>

    <script>
        // 获取矩形元素和按钮
        const rectangle = document.getElementById('rectangle');
        const moveButton = document.getElementById('moveButton');
        const changeButton = document.getElementById('changeButton');

        function getTargetDistance() {
            const distances = [200, 300];
            return distances[Math.floor(Math.random() * distances.length)] + 'px';
        }

        // 移动矩形
        function moveRectangle() {
            // 获取目标距离
            const targetDistance = getTargetDistance();

            // 设置 CSS 变量
            rectangle.style.setProperty('--target-distance', targetDistance);

            // 应用动画
            rectangle.style.animation = 'move 5s forwards';
        }

        let curState = 'running'
        function changeAni() {
            if (curState === 'running') {
                curState = 'paused';
            } else {
                curState = 'running';
            }
            rectangle.style.animationPlayState = curState;
        }

        // 绑定按钮点击事件
        moveButton.addEventListener('click', moveRectangle);
        changeButton.addEventListener('click', changeAni);
    </script>
</body>

</html>

如上代码 通过css变量我们实现了动画参数动态变化的能力。
而且还可以复用animation动画提供给我们的暂停 重运行的能力。
也避免了过多js的操作导致的性能风险。具体可以参考这里raf:写动画我可能没那么合适...
这也是为什么我们要使用animation动画的原因