css变量的妙用(setProperty()的使用)
<template><div class="box"><div class="circle"></div></div></template><script setup>
// 无需特殊 JSimport { nextTick, onMounted } from "vue";onMounted(() => {nextTick(() => {const box = document.querySelector('.box')const w=box.clientWidthbox.style.setProperty('--w', `${w}px`)})})</script><style scoped>
.box {width: 500px;height: 500px;border: 2px solid #000;margin: 200px auto;position: relative;
}.circle {width: 20px;height: 20px;background: red;border-radius: 50%;position: absolute;top: 50%;animation: tranformA 3s linear infinite;
}@keyframes tranformA {50% {transform: translateX(calc(var(--w) - 100%));}
}</style>
一个红色圆点在一个黑色边框的盒子中水平来回移动。下面是对代码的详细解释:
HTML 部分 (<template>
)
<div class="box"><div class="circle"></div>
</div>
- 创建了一个类名为
box
的容器 div - 内部包含一个类名为
circle
的 div,用于显示红色圆点
JavaScript 部分 (<script setup>
)
import { nextTick, onMounted } from "vue";onMounted(() => {nextTick(() => {const box = document.querySelector('.box')const w = box.clientWidthbox.style.setProperty('--w', `${w}px`)})
})
- 使用 Vue 的 Composition API
- 在组件挂载后 (
onMounted
),等待 DOM 更新完成 (nextTick
) - 获取
.box
元素的宽度,并将其设置为 CSS 变量--w
- 这样做的目的是让动画知道容器的宽度,使圆点能准确移动到容器边缘
CSS 部分 (<style scoped>
)
.box {width: 500px;height: 500px;border: 2px solid #000;margin: 200px auto;position: relative;
}
- 设置容器的样式:
- 固定宽高 500px
- 黑色边框
- 上下边距 200px,水平居中
- 相对定位(为子元素的绝对定位提供参照)
.circle {width: 20px;height: 20px;background: red;border-radius: 50%;position: absolute;top: 50%;animation: tranformA 3s linear infinite;
}
- 设置圆点的样式:
- 宽高 20px 的圆形(通过
border-radius: 50%
) - 红色背景
- 绝对定位,垂直居中 (
top: 50%
) - 应用名为
tranformA
的动画(3秒完成,线性速度,无限循环)
- 宽高 20px 的圆形(通过
@keyframes tranformA {50% {transform: translateX(calc(var(--w) - 100%));}
}
- 定义动画关键帧:
- 在动画的 50% 位置(1.5秒时),圆点移动到容器右侧
translateX(calc(var(--w) - 100%))
计算移动距离:var(--w)
是容器宽度(500px)100%
是圆点自身的宽度(20px)- 因此移动距离为 480px(500-20)
- 由于没有定义 0% 和 100% 的关键帧,它们会保持默认状态(即未移动状态)
- 这样形成了来回移动的效果
动画效果
圆点会在容器内从左到右再回到左,不断循环:
- 开始时在左侧中间位置
- 1.5秒时移动到右侧中间位置
- 3秒时回到左侧中间位置
- 无限循环这个过程
注意事项
- 代码中
tranformA
拼写有误,应为transformA
(少了一个 ‘s’) - 使用 CSS 变量 (
--w
) 动态设置容器宽度,使动画可以适应不同大小的容器 scoped
样式表示这些样式只作用于当前组件
`setProperty()
setProperty()
是 JavaScript 中用于操作 CSS 样式属性的方法,它可以动态地修改 CSS 变量的值或直接设置元素的样式属性。在 Vue 中,我们通常用它来动态更新 CSS 自定义属性(CSS 变量)。
基本语法
element.style.setProperty(propertyName, value, priority);
propertyName
:要设置的 CSS 属性名(如"--w"
或"background-color"
)。value
:要设置的属性值(如"500px"
或"red"
)。priority
(可选):指定 CSS 优先级(如"important"
),通常可以省略。
常见用途
1. 动态修改 CSS 变量(推荐方式)
CSS 变量(自定义属性)通常以 --
开头,可以用 setProperty()
动态修改:
element.style.setProperty('--w', '500px');
然后在 CSS 中使用:
.box {width: var(--w); /* 动态应用变量 */
}
2. 直接修改元素的 CSS 属性
element.style.setProperty('background-color', 'red');
等价于:
element.style.backgroundColor = 'red';
3. 设置带 !important
的样式
element.style.setProperty('color', 'blue', 'important');
在 Vue 中的典型用法
动态调整 CSS 变量
<template><div class="box" ref="box"><div class="circle"></div></div>
</template><script setup>
import { ref, onMounted } from "vue";const box = ref(null);onMounted(() => {// 获取容器宽度并设置为 CSS 变量box.value.style.setProperty('--w', `${box.value.clientWidth}px`);
});
</script><style scoped>
.box {--w: 100px; /* 默认值 */width: 500px;
}.circle {width: 20px;animation: move 3s linear infinite;
}@keyframes move {50% {transform: translateX(calc(var(--w) - 100%));}
}
</style>
与 element.style.property
的区别
方法 | 适用场景 | 示例 |
---|---|---|
setProperty() | 适用于 CSS 变量或带连字符的属性 | el.style.setProperty('--color', 'red') |
element.style.property | 适用于驼峰式命名的标准属性 | el.style.backgroundColor = 'red' |
示例对比:
// 设置 CSS 变量(必须用 setProperty)
element.style.setProperty('--main-color', 'blue');// 设置普通样式(两种方式均可)
element.style.setProperty('background-color', 'red');
element.style.backgroundColor = 'red';
注意事项
-
CSS 变量必须用
setProperty
修改:// ✅ 正确 element.style.setProperty('--size', '20px');// ❌ 错误(不会生效) element.style['--size'] = '20px';
-
Vue 中的
ref
+setProperty
更推荐:
在 Vue 3 中,建议使用ref
绑定 DOM 元素,而不是document.querySelector
:const box = ref(null); box.value.style.setProperty('--w', '500px');
-
适用于响应式布局:
setProperty
常用于动态计算宽度、高度等,使 CSS 能响应 JavaScript 的计算结果。
总结
setProperty()
是动态修改 CSS 变量或样式的标准方法。- 在 Vue 中,结合
ref
使用可以更安全地操作 DOM。 - 适用于响应式动画、主题切换、动态布局等场景。
如果有更具体的需求(如响应式监听宽度变化),可以结合 ResizeObserver
使用。