前言
CSS 变量是一项强大的功能,它可以帮助开发人员更好地组织和管理样式表。在本文中,我们将深入探讨 CSS 变量的高级技巧和最佳实践,通过学习如何使用变量作为计算值、媒体查询和动态更改等方面,你将能够更好地利用 CSS 变量的强大功能。
一、概念
CSS
变量(也称为自定义属性)是一种在 CSS
中定义和使用的值,可以在整个样式表中重复使用。它们提供了一种灵活的方式来存储和管理样式中的值,使得样式的修改更加简单和可维护。
二、基本用法
CSS
变量的基本用法包括定义变量、使用变量和修改变量的值。
1. 定义变量
在 CSS
中,使用–前缀来定义变量。变量的命名可以由字母、数字、破折号和下划线组成,但必须以字母开头。变量的定义通常放在选择器的规则集内,或者在根元素(:root
)中定义,以便全局使用。例如:
:root {
--primary-color: #ff0000;
--font-size: 16px;
}
2. 使用变量
使用变量时,需要使用 var()
函数将变量包裹起来。变量可以在任何可以使用 CSS
属性值的地方使用,例如颜色、尺寸、边距等。例如:
.element {
color: var(--primary-color);
font-size: var(--font-size);
}
3. 修改变量的值
变量的值可以在 CSS
中动态修改,以实现样式的变化。可以通过JavaScript或使用伪类(:hover
、:focus
等)来修改变量的值。例如:
.element:hover {
--primary-color: #00ff00;
}
或者使用 JavaScript
来修改变量的值:
document.documentElement.style.setProperty('--primary-color', '#00ff00');
三、命名规范
当我们在 CSS
中使用变量时,为了避免与现有的 CSS
属性冲突,我们可以使用自定义的 CSS
变量,并为它们选择适当的命名规范。以两个横线(--
)开头的属性被视为 CSS
变量。
以下是一些常见的 CSS
变量命名规范:
- 使用有意义的名称:为了增加代码的可读性和可维护性,我们应该选择具有描述性的名称来命名
CSS
变量。这样可以使其他开发人员更容易理解变量的用途和含义; - 使用小写字母和连字符:
CSS
变量的名称应该使用小写字母,并使用连字符(-
)作为单词之间的分隔符。例如,--primary-color
; - 使用命名空间:为了避免与其他变量冲突,可以使用命名空间来对变量进行分组。例如,
--button-primary-color
,其中button
是命名空间; - 避免使用缩写和简写:尽量避免使用缩写和简写的变量名称,因为这可能会导致代码的可读性降低。选择具有描述性的名称,以便其他开发人员能够轻松理解变量的含义;
- 使用一致的命名约定:在整个项目中保持一致的命名约定是很重要的。选择一种命名风格,并在整个项目中坚持使用它,这样可以提高代码的一致性和可读性。
总之,CSS
变量的命名规范应该注重可读性、可维护性和一致性。通过选择有意义的名称、使用小写字母和连字符、使用命名空间以及避免缩写和简写,我们可以更好地组织和管理 CSS
变量。
四、变量值类型
在 CSS
中,CSS
变量的值可以是各种不同的类型。不同的类型在使用上也会有细微的差别。
如果变量值是一个字符串,可以与其他字符串拼接,例如:
<!DOCTYPE html>
<html>
<style>
:root {
--primary-content: 'hello';
}
.box:after {
content: '标题 : ' var(--primary-content)
}
</style>
<body>
<div class="box"></div>
</body>
</html>
- 实现效果
如果变量值是数值,则不能与数值单位直接连用,例如:
在下面的代码中,我们在 box2
盒子使用 calc()
函数来执行数学计算,将变量 --primary-num
的值乘以 1
像素(1px
)。这样,就可以将数值与单位进行结合,以实现正确的样式效果。通过这种方式,我们可以将数值与单位进行拼接,确保样式的正确性。而且 calc()
函数可以执行更复杂的数学计算,例如加法、减法、乘法和除法等。
<!DOCTYPE html>
<html>
<style>
:root {
--primary-num: 40;
}
.box1 {
background: cadetblue;
padding-top: var(--primary-num)px;
}
.box2 {
background: chocolate;
padding-top: calc(var(--primary-num) * 1px);
}
</style>
<body>
<div class="box1">内容1</div>
<div class="box2">内容2</div>
</body>
</html>
- 实现效果
如果变量值带有单位,就不能写成字符串,例如:
在下面的代码中,我们在 box1
盒子将带有单位的变量值定义为字符串。这是无效的,因为 CSS
属性期望的是数值单位,而不是字符串。这样的定义会导致样式无效或产生错误。因此,当变量值带有单位时,应该将其定义为数值,而不是字符串。这样可以确保变量在应用于 CSS
属性时能够正确地与单位进行结合。
<!DOCTYPE html>
<html>
<style>
:root {
--border-radius-box1: '20px';
--border-radius-box2: 20px;
}
.box1 {
background: chocolate;
border-radius: var(--border-radius-box1);
}
.box2 {
background: cornflowerblue;
border-radius: var(--border-radius-box2);
}
</style>
<body>
<div class="box1">内容1</div>
<div class="box2">内容2</div>
</body>
</html>
- 实现效果
五、如何理解理解 :root 和 var()
:root
伪类:
:root
伪类选择器匹配文档树的根元素,通常是<html>
元素;- 在
:root
伪类中定义的CSS
变量可以在整个文档中全局使用; - 通过在
:root
伪类中定义变量,我们可以为整个文档设置全局的CSS
属性值; - 例如,我们可以使用
:root
伪类定义全局的颜色、字体大小、断点值等。
var()
函数:
var()
函数用于引用和使用CSS
变量的值;- 它接受一个参数,即要引用的
CSS
变量的名称; var()
函数可以在任何CSS
属性的值中使用,包括字体大小、颜色、边距等;- 通过使用
var()
函数,我们可以根据需要在不同的元素和选择器中使用相同的CSS
变量值,实现统一的样式管理; - 例如,我们可以使用
var(--primary-color)
来引用全局定义的--primary-color
变量。
CSS
变量的基本用法就是这样。通过定义、使用和修改变量的值,可以实现样式的重用、动态变化和全局控制。这使得 CSS
开发更加灵活和可维护。下面为大家提供三个案例,涵盖了定义变量、使用变量和修改变量的值的示例的完整代码。
案例 1
在这个案例中,我们定义了两个变量 --primary-color
和 --font-size
,并将其应用于 .element
元素的颜色和字体大小。当鼠标悬停在 .element
元素上时,--primary-color
变量的值将变为绿色,--font-size
变量的值将变为 26px
。
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--primary-color: #f88604;
--font-size: 22px;
}
.element {
color: var(--primary-color);
font-size: var(--font-size);
}
.element:hover {
--primary-color: rgb(0, 104, 202);
}
</style>
</head>
<body>
<div class="element">Hello, CSS Variables!</div>
</body>
</html>
- 实现效果
案例 2
在这个案例中,我们使用 JavaScript
来监听窗口的大小变化,并根据窗口宽度动态修改 CSS
自定义属性的值。在 updateStyles
函数中,我们通过 window.getComputedStyle
方法获取了 --breakpoint
的值,并根据窗口宽度判断是否应用响应式样式。
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--breakpoint: 300px;
--font-size: 16px;
--primary-color: #ff0000;
}
.element {
font-size: var(--font-size);
color: var(--primary-color);
}
</style>
<script>
function updateStyles() {
var element = document.querySelector('.element');
var breakpoint = getComputedStyle(document.documentElement).getPropertyValue('--breakpoint');
if (window.innerWidth <= parseInt(breakpoint)) {
element.style.setProperty('--font-size', '14px');
element.style.setProperty('--primary-color', '#00ff00');
} else {
element.style.setProperty('--font-size', '16px');
element.style.setProperty('--primary-color', '#ff0000');
}
}
window.addEventListener('resize', updateStyles);
window.addEventListener('DOMContentLoaded', updateStyles);
</script>
</head>
<body>
<div class="element">Responsive Text</div>
</body>
</html>
- 实现效果
案例 3
在这个案例中,我们定义了一个变量 --primary-color
,并将其应用于 .element
元素的颜色。通过 JavaScript
中的 changeColor
函数,我们可以通过点击按钮来修改 --primary-color
变量的值,从而改变 .element
元素的颜色。
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--primary-color: orange;
}
.element {
color: var(--primary-color);
}
</style>
<script>
function changeColor() {
document.documentElement.style.setProperty('--primary-color', 'blue');
// document.documentElement.style.setProperty('root变量', '更改的值')
}
</script>
</head>
<body>
<div class="element">Click the button to change color</div>
<button onclick="changeColor()">点击改变颜色</button>
</body>
</html>
- 实现效果
案例 4
在这个案例中,通过使用 CSS
变量,我们可以动态地控制按钮的样式,实现了鼠标跟踪效果。
在代码中,我们定义了两个 CSS
变量:--x
和 --y
。这两个变量分别表示鼠标在按钮上的横坐标和纵坐标。通过 JavaScript
中的 setProperty
方法,我们可以根据鼠标移动事件的位置,实时地更新这两个变量的值。在 SCSS
部分,我们使用这两个 CSS
变量来确定鼠标跟踪效果的位置。通过将 --x
和 --y
应用到伪元素 ::before
的 left
和 top
属性上,我们可以让伪元素跟随鼠标的位置而移动。此外,我们还使用了 CSS
变量 --size
来控制伪元素的大小。当鼠标悬停在按钮上时,通过改变 --size
的值,我们可以实现一个渐变背景的动画效果。
<template>
<div class="track-btn" @mousemove="handleMouseMove">
<span>使用 CSS 变量让你的按钮更炫酷</span>
</div>
</template>
<script>
export default {
methods: {
handleMouseMove(e) {
const btnStyle = e.target.style;
btnStyle.setProperty("--x", `${e.offsetX}px`);
btnStyle.setProperty("--y", `${e.offsetY}px`);
},
},
};
</script>
<style lang="scss">
.track-btn {
position: relative;
width: 400px;
height: 50px;
background-color: rgb(102, 219, 255);
cursor: pointer;
line-height: 50px;
text-align: center;
font-weight: bold;
font-size: 18px;
color: #fff;
overflow: hidden;
span {
position: relative;
pointer-events: none;
}
&::before {
--size: 0;
position: absolute;
left: var(--x);
top: var(--y);
width: var(--size);
height: var(--size);
background-image: radial-gradient(
circle closest-side,
rgb(0, 215, 82),
transparent
);
content: "";
transform: translate3d(-50%, -50%, 0);
transition: width 200ms ease, height 200ms ease;
}
&:hover::before {
--size: 400px;
}
}
</style>
- 实现效果
六、变量作用域
CSS
变量的作用域是定义它们的选择器的范围。在选择器内定义的变量只能在该选择器内部使用,而在全局作用域内定义的变量则可以在整个文档中使用。
1. 全局作用域
- 在
:root
伪类中定义的CSS
变量具有全局作用域; :root
伪类选择器匹配文档树的根元素,通常是<html>
元素;- 在
:root
伪类中定义的变量可以在整个文档中全局使用。
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--bg-color: rgb(88, 88, 186);
--color: #33ca63;
}
div {
background-color: var(--bg-color);
color: var(--color);
}
span {
background-color: var(--bg-color);
color: var(--color);
}
</style>
</head>
<body>
<div>
<p>我在div内部</p>
</div>
<span>我在div外部</span>
</body>
</html>
- 实现效果
2. 局部作用域
- 在选择器内部或元素内部定义的
CSS
变量具有局部作用域; - 这些变量只能在定义它们的选择器或元素内部使用;
- 局部作用域的变量会覆盖全局作用域中同名的变量。
<!DOCTYPE html>
<html>
<head>
<style>
div {
--bg-color: rgb(88, 88, 186);
--color: #33ca63;
}
p {
background-color: var(--bg-color);
color: var(--color);
}
span {
background-color: var(--bg-color);
color: var(--color);
}
</style>
</head>
<body>
<div>
<p>我在div内部</p>
</div>
<span>我在div外部</span>
</body>
</html>
- 实现效果
3. vue 中设置 scoped
在 vue
中,当你为组件的 <style>
标签添加了 scoped
属性时,CSS
样式将会被限定在组件的作用域内。这意味着,只有在当前组件中的元素才会受到这些样式的影响,而不会泄漏到其他组件中。然而,CSS
变量在 vue
的 scoped
样式中的行为和普通的选择器样式是不同的。当你在 <style>
标签中使用 scoped
属性时,vue
会自动为每个组件的根元素添加一个唯一的类名,以确保该组件的样式只应用到该组件内部。由于 CSS
变量是全局的,其作用域会超出组件的范围。所以在一个带有 scoped
样式的 vue
组件中,CSS
变量在其他组件中是不生效的。换句话说,你无法在一个组件中定义的 CSS
变量在其他组件中使用。
如果你希望在 vue
组件间共享 CSS
变量,有两种常见的方法:
- 使用
CSS
预处理器,例如Sass
或Less
,它们可以提供变量的作用域和共享功能; - 将
CSS
变量定义在全局样式中(不使用scoped
属性),以便在所有组件中共享。
需要注意的是,如果你选择将 CSS
变量定义在全局样式中,请确保变量的命名是唯一的,以避免可能的冲突。
七、变量优先级
CSS
变量的优先级与其他 CSS
属性的优先级相同,遵循 CSS
层叠规则。下面是 CSS
属性优先级的一般顺序(从高到低):
!important
:使用!important
声明的样式具有最高优先级,会覆盖其他所有样式;- 内联样式:直接在
HTML
元素上使用style
属性定义的样式具有较高的优先级; ID
选择器:使用ID
选择器定义的样式具有较高的优先级;- 类选择器、属性选择器和伪类选择器:这些选择器定义的样式具有中等优先级;
- 元素选择器和伪元素选择器:这些选择器定义的样式具有较低的优先级;
- 继承样式:继承自父元素的样式具有最低优先级。
当涉及到 CSS
变量时,它们的优先级与其他选择器相同。如果在同一个元素上定义了多个相同的 CSS
变量,后面定义的变量会覆盖前面的变量。如果在不同的选择器中定义了相同的 CSS
变量,遵循选择器的优先级规则。例如,如果在内联样式中定义了一个 CSS
变量,它将具有较高的优先级,并且会覆盖其他选择器中定义的相同变量。同样,如果在 ID
选择器中定义了一个 CSS
变量,它将具有较高的优先级,并且会覆盖其他选择器中定义的相同变量。
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--primary-color: blue;
}
.container {
--primary-color: red;
}
.box {
background-color: var(--primary-color);
width: 200px;
height: 200px;
margin: 20px;
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
</div>
</body>
</html>
在这个案例中,我们定义了一个名为 --primary-color
的 CSS
变量,并在 :root
伪类中设置为蓝色。然后,在 .container
类选择器中重新定义了相同的变量,并将其设置为红色。在 .box
类选择器中,我们使用 var()
函数来引用 --primary-color
变量,并将其作为背景颜色。由于 .container
类选择器具有较高的优先级,所以最终 .box
的背景颜色将是红色。
- 实现效果
八、兼容性
CSS
变量在现代的浏览器中其实已经具有良好的兼容性了,但在一些旧版本的浏览器中可能存在一些限制。
浏览器 | 兼容性 |
---|---|
Chrome | 支持自 Chrome 49 版本及以上 |
Firefox | 支持自 Firefox 31 版本及以上 |
Safari | 支持自 Safari 9.1 版本及以上 |
Opera | 支持自 Opera 36 版本及以上 |
Edge | 支持自 Edge 15 版本及以上 |
Internet Explorer | 不支持 CSS 变量 |
九、使用 CSS 变量带来的提升
-
可重用性和易维护性
CSS
变量允许你定义一次样式,并在整个样式表中多次重用。这样可以减少代码的重复性,提高代码的可维护性。通过修改变量的值,可以轻松地更改整个样式的外观,而无需逐个修改每个具体的样式。 -
动态性和灵活性
CSS
变量可以在运行时动态修改,而无需修改样式表。这使得在不同的条件下应用不同的样式变得更加容易。例如,您可以根据用户的选择或主题切换来更改变量的值,从而实现动态的样式变化。 -
响应式设计
CSS
变量可以与媒体查询结合使用,实现响应式设计。通过在不同的媒体查询中定义不同的变量值,可以根据设备的屏幕尺寸和特性来调整样式。这使得网页可以适应不同的屏幕大小和设备类型,提供更好的用户体验。 -
可读性和可维护性
CSS
变量可以使用有意义的名称来定义,使样式表更易于理解和维护。相比于硬编码的数值或颜色,使用变量可以提高代码的可读性,并使样式的意图更加清晰。 -
全局控制
通过在根元素上定义
CSS
变量,可以实现全局的样式控制。这意味着你可以在整个网站中使用相同的变量,从而确保一致的外观和风格。如果需要更改样式,只需修改变量的值,而无需逐个修改每个具体的样式。