CSS变量

前端的开发工作中,CSS 是不可或缺的部分;实际工作中,我们通过JavaScript 来进行数据和交互工作,CSS 为用户呈现可视化的界面。有时,CSS 来进行部分交互效果是不是会比 JavaScript 更高效、更省事呢?
一、变量使用
(一)命名规范
我们已经很熟悉 JavaScript 中的变量了,在 JavaScript 中:

var a = 'hellow world'

在 CSS 中,以两个横线开头的“属性”都是 CSS 变量,其他没有任何限制;如:

:root {
  --1: red
}
/**
 *  var()函数就是用于读取变量
 * color: var(--深蓝, #fff); //第二个参数就是默认值,
 * 假设--深蓝为空情况下,会使用#fff
 **/
body {
  color: var(--1)
  --深蓝: #fff
  background-color: var(--深蓝, #fff)
}

// 注意:变量值只能用作属性值,不能用作属性名
.foo {
  --style: color
  /* 很显然,下面是无效的 */
  var(--style): black
}

(二)变量值类型
如果变量值是一个字符串,可以与其他字符串拼接;如:

--bar: 'hello'
--foo: var(--bar)' world'

// 示例
body:after {
  content: '--screen-category : 'var(--screen-category)
}

如果变量值是数值,不能与数值单位直接连用;如:

foo {
  --gap: 20;
  /* 下面无效 */
  margin-top: var(--gap)px
 /* 通过calc去计算,下面有效 */
  margin-top: calc(var(--gap) * 1px)
}

如果变量值带有单位,就不能写成字符串;如:

/* 无效 */
.foo {
  --foo: '20px'
  font-size: var(--foo)
}

/* 有效 */
.foo {
  --foo: 20px
  font-size: var(--foo)
}

(三)变量作用域
:root 选择器允许你定位到 DOM 中的最顶级元素或文档树,相当于全局变量;同一个 CSS 变量,可以在多个选择器内声明。读取的时候,优先级最高的声明生效。这与 CSS 的"层叠"(cascade)规则是一致的;如:

<style>
  :root { --color: black }
  div { --color: blue }
  #test{ --color: red }
  * { color: var(--color) }
</style>

<p>黑色</p>
<div>蓝色</div>
<div id="test">红色</div>

二、兼容性处理和 JavaScript 操作
浏览器兼容性自查网站:caniuse
请添加图片描述
(一)兼容性处理
对于不支持 CSS 变量的浏览器有两种方法;如:
方法一:

:root { --color: black; }
div {
  color: #fff;
  color: var(--color) // 如果这里读不出值,那么并不会覆盖上面的color
}

方法二:

div {
  @supports ( (--a: 0)) {
    /* supported */
  }

  @supports ( not (--a: 0)) {
    /* not supported */
  }
}

(二)JavaScript 操作
JavaScript 也可以检测浏览器是否支持 CSS 变量;如:

const isSupported =
  window.CSS &&
  window.CSS.supports &&
  window.CSS.supports('--a', 0)

if (isSupported) {
  /* supported */
} else {
  /* not supported */
}

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

// 设置变量
document.body.style.setProperty('--color', '#7F583F') //局部
document.documentElement.style.setProperty('--color', '#7F583F') //全局

// 读取变量
document.body.style.getPropertyValue('--color').trim() //局部
document.documentElement.style.getPropertyValue('--color').trim() //全局
getComputedStyle(document.documentElement).getPropertyValue('--color') // 全局,如果是在css表中设置的需要这种方式获取

// 删除变量
document.body.style.removeProperty('--color') //局部
document.documentElement.style.removeProperty('--color') //全局

这意味着,JavaScript 可以将任意值存入样式表。同步一个监听事件,将信息被存入 CSS 变量;如:

const docStyle = document.documentElement.style

document.addEventListener('mousemove', (e) => {
  docStyle.setProperty('--mouse-x', e.clientX)
  docStyle.setProperty('--mouse-y', e.clientY)
})

可以看出,CSS 变量提供了 JavaScript 与 CSS 通信的一种途径。
三、趣味案例
(一)打字机(年度报告项目)
实现方式:

<p class="greet-info line-5">
  <span v-for="(item, index) in greetInfoArr" :key="'greet-' + index">
    {{ item }}
  </span>
</p>

export default {
computed: {
    greetInfoArr() {
      return this.greetInfo.split('')
    }
  },
  data() {
    return {
      greetInfo:
        '“开始完成一件事情,比做好它更重要。因为只要开始了,你就有机会把它做的更好”'
    }
  }
}

<style lang="scss">
.greet-info {
  position: absolute;
  z-index: 9;
  left: 18.75%;
  bottom: 7.41%;
  font-size: 24px;
  font-weight: 400;
  color: #ffffff;
  line-height: 33px;
  @keyframes revolveScale {
    60% {
      opacity: 0;
    }

    100% {
      opacity: 1;
    }
  }
  span {
    display: inline-block;
    opacity: 0;
    --time: calc(var(--greet-index) * 0.1s + 2s);
    // forwards当动画完成后,保持最后一帧的状态
    animation: revolveScale 0.4s forwards; 
    animation-delay: var(--time);
  }
}
</style>

效果:
请添加图片描述
(二)自动变色进度条
实现方式:

<!-- 
  当进度小于 30% 时,背景呈红色
  当进度大于 30% 并且 小于 60% 时,背景呈橙色
  当进度大于 60% 并且 小于 90% 时,背景呈蓝色
  当进度大于 90% 时,背景呈绿色 -->
  <div class="bar" style="--percent: 50"></div>

<style lang="scss">
.bar {
  display: flex;
  width: 600px;
  height: 20px;
  background-color: #f5f5f5;
}
.bar::before {
  // 创建或重置一个或多个计数器
  counter-reset: progress var(--percent);
  // counter() 函数以字符串形式返回当前计数器的值, 表示空格
  content: counter(progress) '%\2002';
  display: flex;
  justify-content: end;
  width: calc(var(--percent) * 1%);
  font-size: 12px;
  color: #fff;
  white-space: nowrap;
  // 渐变色
  background-image: linear-gradient(green, green),
    linear-gradient(#2486ff, #2486ff), linear-gradient(orange, orange),
    linear-gradient(red, red);
  background-size: calc((var(--percent) - 90) * 100%) 100%,
    calc((var(--percent) - 60) * 100%) 100%,
    calc((var(--percent) - 30) * 100%) 100%, 100% 100%;
}
</style>

效果:
请添加图片描述
(三)悬浮跟踪按钮
实现方式:

<div class="bruce flex-ct-x">
  <a class="track-btn">
	<span>妙用CSS变量,让你的CSS变得更心动</span>
  </a>
</div>

// js 监听鼠标修改变量值
const btn = document.getElementsByClassName("track-btn")[0];
const btnStyle = btn.style;
btn.addEventListener("mousemove", e => {
  btnStyle.setProperty("--x", `${e.offsetX}px`);
  btnStyle.setProperty("--y", `${e.offsetY}px`);
});
.bruce {
   overflow: hidden;
   height: 100vh;
}
.flex-ct-x {
   display: flex;
   justify-content: center;
   align-items: center;
}
.track-btn {
  overflow: hidden;
  position: relative;
  border-radius: 25px;
  width: 400px;
  height: 50px;
  background-color: #66f;
  cursor: pointer;
  line-height: 50px;
  text-align: center;
  font-weight: bold;
  font-size: 18px;
  color: #fff;
  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, #09f, transparent);
	content: "";
	transform: translate3d(-50%, -50%, 0);
	transition: width 200ms ease, height 200ms ease;
  }
  &:hover::before {
	--size: 400px;
  }
}

效果:
请添加图片描述

四、思考与总结
CSS 变量的美在于其本质是响应式的。一旦 CSS 变量更新了,任意带有 CSS 变量的属性的值也都会随之更新。它的好处有哪些呢?可以减少样式代码的重复性;增加样式代码的扩展性;提高样式代码的灵活性;增加一种CSS与JS的通讯方式;无需深层遍历DOM改变某个样式。在做系统主题切换,风格基调(字体、色系),封装些通用性的动态组件,通过 CSS 变量并结合动画是不是就很方便做到了。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年2月23日
下一篇 2023年2月23日

相关推荐