>웹 프론트엔드 >CSS 튜토리얼 >CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

青灯夜游
青灯夜游앞으로
2021-07-23 19:13:202422검색

이 문서에서는 CSS 변수를 이해하고, CSS 변수의 사용법을 소개하고, CSS 변수를 능숙하게 사용하여 CSS를 더욱 흥미롭고 프로젝트를 더욱 멋지게 만드는 방법을 알아봅니다!

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

CSS 변수CSS 사용자 정의 속성이라고도 합니다. 소수의 사람들이 사용하는 것이 갑자기 언급되는 이유는 무엇입니까? 최근 개인 공식 홈페이지를 개편하다 보니 왜 갑자기 CSS 변수를 사용하게 되는지 모르겠네요. 그 숨겨진 매력에 감탄하게 되는 건지도 모르겠습니다.

CSS에서 변수가 사용되는 이유에 대해 이야기하면, 예를 들어보면 누구나 한 눈에 이해할 수 있을 것입니다.

/* 不使用CSS变量 */
.title {
    background-color: red;
}
.desc {
    background-color: red;
}

/* 使用CSS变量 */
:root {
    --bg-color: red;
}
.title {
    background-color: var(--bg-color);
}
.desc {
    background-color: var(--bg-color);
}

이 글을 읽고 나면 CSS 변수를 사용한 코드의 양이 조금 과하다는 생각이 들 수도 있겠지만, 어느 날 사악한 기획자 형과 디자인 소녀가 갑자기 만들고 싶다고 말한 적이 있습니까? 피부 변화 기능. 일반적인 생각에 따르면 일부 학생들은 아마도 기본 색상 테마에 따라 해당 새 색상 테마 CSS 파일을 추가할 것입니다. 새로운 요구 사항이 있을 때마다 여러 테마 색상 세트를 동시에 유지하는 것은 번거로운 일입니다. 默认颜色主题增加一份对照的新颜色主题CSS文件。这样每次新增需求都同时维护几套主题颜色多麻烦啊。

此时CSS变量就派上用场了,提前跟设计小姐姐规范好各种需要变换的颜色并通过CSS变量进行定义,通过JS批量操作这些定义好的CSS变量即可。这也是变换主题颜色的一种解决方案之一,好处在于只需写一套CSS代码。

["red", "blue", "green"].forEach(v => {
    const btn = document.getElementById(`${v}-theme-btn`);
    btn.addEventListener("click", () => document.body.style.setProperty("--bg-color", v));
});

在此总结下CSS使用变量的好处:

    <li>减少样式代码的重复性 <li>增加样式代码的扩展性 <li>提高样式代码的灵活性 <li>增多一种CSS与JS的通讯方式 <li>不用深层遍历DOM改变某个样式

可能有些同学会问,Sass和Less早就实现了变量这个特性,何必再多此一举呢。可是细想一下,CSS变量对比Sass和Less的变量,又有它的过人之处。

    <li>浏览器原生特性,无需经过任何转译就可直接运行 <li>DOM对象一员,极大便利了CSS与JS之间的联系

认识

本来打算用一半篇幅讲述CSS变量的规范和用法,但是网上一搜一大把就感觉没必要了,贴上阮一峰老师写的教程《CSS变量教程》。同时笔者也对CSS变量的细节地方进行一个整理,方便大家记忆。

    <li>声明:--变量名 <li>读取:var(--变量名, 默认值) <li>类型
      <li>普通:只能用作属性值不能用作属性名 <li>字符:与字符串拼接 "Hello, "var(--name) <li>数值:使用calc()与数值单位连用 var(--width) * 10px
    <li>作用域
      <li>范围:在当前元素块作用域及其子元素块作用域下有效 <li>优先级别:内联样式 > ID选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 = 伪元素选择器

接下来使用几个特别的场景展示CSS变量的魅力。还是那句话,一样东西有使用的场景,那自然就会有它的价值,那么用的人也会越来越多。

使用场景

其实CSS变量有一个特别好用的场景,那就是结合List元素集合使用。如果不明白这是什么,请继续往下看。

以下所有演示代码基于vue文件,但HTML、CSS和JS分开书写,为了简化CSS的书写而使用Sass进行预处理,方便代码演示

条形加载条

一个条形加载条通常由几条线条组成,并且每条线条对应一个存在不同时延的相同动画,通过时间差运行相同的动画,从而产生加载效果。估计大部分的同学可能会把CSS代码写成以下这样。

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

<ul class="strip-loading flex-ct-x">
    <li v-for="v in 6" :key="v"></li>
</ul>
.loading {
    width: 200px;
    height: 200px;
    li {
        border-radius: 3px;
        width: 6px;
        height: 30px;
        background-color: #f66;
        animation: beat 1s ease-in-out infinite;
        & + li {
            margin-left: 5px;
        }
        &:nth-child(2) {
            animation-delay: 200ms;
        }
        &:nth-child(3) {
            animation-delay: 400ms;
        }
        &:nth-child(4) {
            animation-delay: 600ms;
        }
        &:nth-child(5) {
            animation-delay: 800ms;
        }
        &:nth-child(6) {
            animation-delay: 1s;
        }
    }
}

分析代码发现,每个<li>只是存在animation-delay不同,而其余代码则完全相同,换成其他类似的List元素集合场景,那岂不是有10个<li>就写10个:nth-child

显然这种方法不灵活也不容易封装成组件,如果能像JS那样封装成一个函数,并根据参数输出不同的样式效果,那就更棒了。说到这里,很明显就是为了铺垫CSS变量的开发技巧了。

对于HTML部分的修改,让每个<li>拥有一个自己作用域下的CSS变量。对于CSS部分的修改,就需要分析哪些属性是随着index이때 CSS 변수

가 유용합니다. 변경해야 할 다양한 색상을 미리 디자인 담당자와 함께 지정하고 🎜CSS 변수🎜를 통해 정의하면 됩니다. 정의된 🎜CSS 변수🎜를 통해 일괄 처리할 수 있습니다. JS. 이것은 또한 🎜테마 색상 변경🎜을 위한 솔루션 중 하나입니다. 장점은 CSS 코드 세트만 작성하면 된다는 것입니다. 🎜
<ul class="strip-loading flex-ct-x">
    <li v-for="v in 6" :key="v" :style="`--line-index: ${v}`"></li>
</ul>
🎜다음은 CSS에서 변수를 사용할 때의 이점을 요약한 것입니다: 🎜
    <li>스타일 코드 중복 감소 <li>스타일 코드 확장성 증가 <li>개선 스타일 코드의 확장성 유연성 <li>CSS와 JS 간의 통신 방법 추가 <li>특정 스타일을 변경하기 위해 DOM을 깊게 탐색할 필요가 없음
🎜Some 학생들은 'Sass와 Less가 이미 변수 기능을 구현했는데 굳이 그걸 굳이 할 이유가 있나요?'라고 질문할 수 있습니다. 하지만 잘 생각해보면 🎜CSS 변수🎜는 Sass나 Less의 변수에 비해 장점이 있습니다. 🎜
    <li>번역 없이 직접 실행할 수 있는 브라우저 기본 기능 <li>CSS와 JS 간의 연결을 크게 촉진하는 DOM 개체의 구성원
🎜알아보기🎜🎜원래 글의 절반을 🎜CSS 변수🎜의 사양과 사용법을 설명하려고 했는데, 인터넷에서 많이 검색해본 결과 불필요하다고 느껴서 Ruan Yifeng 선생님이 작성한 튜토리얼 게시"CSS 변수 튜토리얼'. 동시에 저자는 🎜CSS 변수🎜의 세부 사항도 누구나 쉽게 기억할 수 있도록 정리했습니다. 🎜
    <li>선언: --변수 이름 <li>읽기: var(--변수 이름, 기본값) <li>유형
      <li>일반: 속성 값으로만 사용할 수 있고 속성 이름으로 사용할 수 없음 <li>문자: 및 string Splicing "Hello, "var(--name) <li>숫자 값: 숫자 단위 var(-와 함께 <code>calc() 사용 -width ) * 10px
    <li>범위
      <li>범위: 현재 요소 블록 범위 및 해당 하위 요소 블록 범위에서 유효함 <li>우선순위: 인라인 스타일> ID 선택기> 클래스 선택기 = 속성 선택기 = 의사 클래스 선택기> code>
🎜 다음으로 몇 가지 특별한 시나리오를 사용하여 🎜CSS 변수🎜의 매력을 보여드리겠습니다. 다시 말하지만, 어떤 것에 사용 시나리오가 있으면 자연스럽게 그 가치가 있게 되고 점점 더 많은 사람들이 그것을 사용할 것입니다. 🎜

사용 시나리오

🎜사실 🎜CSS 변수🎜에는 List 요소 모음과 함께 사용하는 특히 유용한 시나리오가 있습니다. 이것이 무엇인지 모르신다면 계속 읽어보시기 바랍니다. 🎜
.strip-loading {
    width: 200px;
    height: 200px;
    li {
        --time: calc((var(--line-index) - 1) * 200ms);
        border-radius: 3px;
        width: 6px;
        height: 30px;
        background-color: #f66;
        animation: beat 1.5s ease-in-out var(--time) infinite;
        & + li {
            margin-left: 5px;
        }
    }
}
🎜🎜바 로딩 바🎜🎜🎜바 로딩 바는 일반적으로 여러 줄로 구성되며 각 줄은 서로 다른 지연에 해당합니다. 동일한 애니메이션은 시간차를 통해 로딩 효과를 생성합니다. 대부분의 학생들은 다음과 같이 CSS 코드를 작성할 것으로 추정됩니다. 🎜🎜CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!🎜
/* flex属性无效 */
.loading {
    display: flex;
    align-items: center;
    flex: var(--line-index);
}
<div class="heart-loading flex-ct-x">
    <ul style="--line-count: 9;">
        <li v-for="v in 9" :key="v" :class="`line-${v}`" :style="`--line-index: ${v}`"></li>
    </ul>
</div>
🎜 코드를 분석한 결과 각 <li>animation-delay만 다른 것으로 나타났으며, 나머지 코드는 완전히 동일한 것으로 나타났습니다. 다른 유사한 List 요소 수집 시나리오로 대체하면 10개의 <li>가 있는 경우 10개의 :nth-child를 작성하는 대신 어떻게 될까요? 🎜🎜분명히 이 방법은 유연하지 않고 쉽게 컴포넌트로 캡슐화할 수 없습니다. JS와 같은 함수로 캡슐화하고 매개변수에 따라 다양한 스타일 효과를 출력할 수 있다면 더욱 좋을 것입니다. 이렇게 말하면 🎜CSS 변수🎜 개발 기술의 길을 닦는 것이 분명합니다. 🎜🎜HTML 부분을 수정하려면 각 <li>가 자체 범위에 🎜CSS 변수🎜를 갖도록 하세요. CSS 부분을 수정하려면 index가 증가함에 따라 어떤 속성이 정기적으로 변경되는지 분석해야 합니다. 🎜CSS 변수🎜 표현식을 사용하여 정기적으로 변경되는 부분을 교체하세요. 🎜
<ul class="strip-loading flex-ct-x">
    <li v-for="v in 6" :key="v" :style="`--line-index: ${v}`"></li>
</ul>
.strip-loading {
    width: 200px;
    height: 200px;
    li {
        --time: calc((var(--line-index) - 1) * 200ms);
        border-radius: 3px;
        width: 6px;
        height: 30px;
        background-color: #f66;
        animation: beat 1.5s ease-in-out var(--time) infinite;
        & + li {
            margin-left: 5px;
        }
    }
}

代码中的变量--line-index--time使每个<li>拥有一个属于自己的作用域。例如第2个<li>--line-index的值为2,--time的计算值为200ms,换成第3个<li>后这两个值又会不同了。

这就是CSS变量的作用范围所致(在当前元素块作用域及其子元素块作用域下有效),因此在.strip-loading的块作用域下调用--line-index是无效的。

/* flex属性无效 */
.loading {
    display: flex;
    align-items: center;
    flex: var(--line-index);
}

通过妙用CSS变量,也把CSS代码从29行缩减到15行,对于那些含有List元素集合越多的场景,效果就更明显。而且这样写也更加美观更加容易维护,某天说加载效果的时间差不明显,直接将calc((var(--line-index) - 1) * 200ms)里的200ms调整成400ms即可。就无需对每个:nth-child(n)进行修改了。

心形加载条

前段时间刷掘金看到陈大鱼头兄的心形加载条,觉得挺漂亮的,很带感觉。

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

通过动图分析,发现每条线条的背景色和动画时延不一致,另外动画运行时的高度也不一致。细心的你可能还会发现,第1条和第9条的高度一致,第2条和第8条的高度一致,依次类推,得到高度变换相同类的公式:对称index = 总数 + 1 - index

背景色使用了滤镜的色相旋转hue-rotate函数,目的是为了使颜色过渡得更加自然;动画时延的设置和上面条形加载条的设置一致。下面就用CSS变量根据看到的动图实现一番。

<div class="heart-loading flex-ct-x">
    <ul style="--line-count: 9;">
        <li v-for="v in 9" :key="v" :class="`line-${v}`" :style="`--line-index: ${v}`"></li>
    </ul>
</div>
.heart-loading {
    width: 200px;
    height: 200px;
    ul {
        display: flex;
        justify-content: space-between;
        width: 150px;
        height: 10px;
    }
    li {
        --Θ: calc(var(--line-index) / var(--line-count) * .5turn);
        --time: calc((var(--line-index) - 1) * 40ms);
        border-radius: 5px;
        width: 10px;
        height: 10px;
        background-color: #3c9;
        filter: hue-rotate(var(--Θ));
        animation-duration: 1s;
        animation-delay: var(--time);
        animation-iteration-count: infinite;
    }
    .line-1,
    .line-9 {
        animation-name: line-move-1;
    }
    .line-2,
    .line-8 {
        animation-name: line-move-2;
    }
    .line-3,
    .line-7 {
        animation-name: line-move-3;
    }
    .line-4,
    .line-6 {
        animation-name: line-move-4;
    }
    .line-5 {
        animation-name: line-move-5;
    }
}

一波操作后就有了下面的效果。和陈大鱼头兄的心形加载条对比一下,颜色、波动曲线和跳动频率有点不一样,在暖色调的蔓延和肾上腺素的飙升下,这是一种心动的感觉。想起自己曾经写的一首诗:我见犹怜,爱不释手,雅俗共赏,君子好逑

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

标签导航栏

上面通过两个加载条演示了CSS变量在CSS中的运用以及一些妙用技巧,现在通过标签导航栏演示CSS变量在JS中的运用。

JS中主要有3个操作CSS变量的API,看上去简单易记,分别如下:

    <li>读取变量:elem.style.getPropertyValue() <li>设置变量:elem.style.setProperty() <li>删除变量:elem.style.removeProperty()

先上效果图,效果中主要是使用CSS变量标记每个Tab的背景色和切换Tab的显示状态。

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

<div class="tab-navbar">
    <nav>
        <a v-for="(v, i) in list" :key="v" :class="{ active: index === i }" @click="select(i)">标题{{i + 1}}</a>
    </nav>
    <div>
        <ul ref="tabs" :style="`--tab-count: ${list.length}`">
            <li v-for="(v, i) in list" :key="v" :style="`--bg-color: ${v}`">内容{{i + 1}}</li>
        </ul>
    </div>
</div>
.tab-navbar {
    display: flex;
    overflow: hidden;
    flex-direction: column-reverse;
    border-radius: 10px;
    width: 300px;
    height: 400px;
    nav {
        display: flex;
        height: 40px;
        background-color: #f0f0f0;
        line-height: 40px;
        text-align: center;
        a {
            flex: 1;
            cursor: pointer;
            transition: all 300ms;
            &.active {
                background-color: #66f;
                font-weight: bold;
                color: #fff;
            }
        }
    }
    div {
        flex: 1;
        ul {
            --tab-index: 0;
            --tab-width: calc(var(--tab-count) * 100%);
            --tab-move: calc(var(--tab-index) / var(--tab-count) * -100%);
            display: flex;
            flex-wrap: nowrap;
            width: var(--tab-width);
            height: 100%;
            transform: translate3d(var(--tab-move), 0, 0);
            transition: all 300ms;
        }
        li {
            display: flex;
            justify-content: center;
            align-items: center;
            flex: 1;
            background-color: var(--bg-color);
            font-weight: bold;
            font-size: 20px;
            color: #fff;
        }
    }
}
export default {
    data() {
        return {
            index: 0,
            list: ["#f66", "#09f", "#3c9"]
        };
    },
    methods: {
        select(i) {
            this.index = i;
            this.$refs.tabs.style.setProperty("--tab-index", i);
        }
    }
};

<ul></ul>上定义--tab-index表示Tab当前的索引,当点击按钮时重置--tab-index的值,就可实现不操作DOM来移动<ul></ul>的位置显示指定的Tab。不操作DOM而可移动<ul></ul>是因为定义了--tab-move,通过calc()计算--tab-index--tab-move的关系,从而操控transform: translate3d()来移动<ul></ul>

另外在<li>上定义--bg-color表示Tab的背景色,也是一种比较简洁的模板赋值方式,总比写<li :style="backgroundColor: ${color}">要好看。如果多个CSS属性依赖一个变量赋值,那么使用CSS变量赋值到style上就更方便了,那些CSS属性可在CSS文件里进行计算与赋值,这样可帮助JS分担一些属性计算工作。

当然,这个标签导航栏也可通过纯CSS实现,有兴趣的同学可看看笔者之前一篇文章里的纯CSS标签导航栏

悬浮跟踪按钮

通过几个栗子实践了CSS变量在CSS和JS上的运用,相信大家已经掌握了其用法和技巧。之前在某个网站看过一个比较酷炫的鼠标悬浮特效,好像也是使用CSS变量实现的。笔者凭着记忆也使用CSS变量实现一番。

其实思路也比较简单,先对按钮进行布局和着色,然后使用伪元素标记鼠标的位置,定义--x--y表示伪元素在按钮里的坐标,通过JS获取鼠标在按钮上的offsetLeftoffsetLeft分别赋值给--x--y,再对伪元素添加径向渐变的背景色,大功告成,一个酷炫的鼠标悬浮跟踪特效就这样诞生了。

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

<a class="track-btn pr tac" @mousemove="move">
    <span>妙用CSS变量,让你的CSS变得更心动</span>
</a>
.track-btn {
    display: block;
    overflow: hidden;
    border-radius: 100px;
    width: 400px;
    height: 50px;
    background-color: #66f;
    line-height: 50px;
    cursor: pointer;
    font-weight: bold;
    font-size: 18px;
    color: #fff;
    span {
        position: relative;
    }
    &::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: all 200ms ease;
    }
    &:hover::before {
        --size: 400px;
    }
}
export default {
    name: "track-btn",
    methods: {
        move(e) {
            const x = e.pageX - e.target.offsetLeft;
            const y = e.pageY - e.target.offsetTop;
            e.target.style.setProperty("--x", `${x}px`);
            e.target.style.setProperty("--y", `${y}px`);
        }
    }
};

其实可结合鼠标事件来完成更多的酷炫效果,例如动画关联事件响应等操作。没有做不到,只有想不到,尽情发挥你的想象力啦。

之前在CodePen上还看到一个挺不错的栗子,一个悬浮视差按钮,具体代码涉及到一些3D变换的知识。看完源码后,按照其思路自己也实现一番,顺便对代码稍加改良并封装成Vue组件,存放到本课件示例代码中。感觉录制的GIF有点别扭,显示效果不太好,有兴趣的同学可下载本课件示例代码,自己运行看看效果。

6-CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

兼容

对于现代浏览器来说,CSS变量的兼容性其实还是蛮好的,所以大家可放心使用。毕竟现在都是各大浏览器厂商快速迭代的时刻,产品对于用户体验来说是占了很大比重,因此在条件允许的情况下还是大胆尝新,不要被一些过去的所谓的规范所约束着。

CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!

试问现在还有多少人愿意去维护IE6~IE9的兼容性,如果一个产品的用户体验受限于远古浏览器的压制(可能政务Web应用和金融Web应用除外吧),相信这个产品也不会走得很远。

我们在完成一个产品的过程中,不仅仅是为了完成工作任务,如果在保证进度的同时能花点心思点缀一下,可能会有意外的收获。用心写好每一段代码,才是享受写代码的真谛

总结

本文通过循序渐进的方式探讨了CSS变量的运用和技巧,对于一个这么好用的特性,当然是不能放过啦。其实多多思考,就能把CSS变量用在很多场景上。

更多编程相关知识,请访问:编程入门!!

위 내용은 CSS 변수를 능숙하게 사용하여 프로젝트를 더욱 멋지게 만드세요!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제