CSS变量

CSS变量(也称为“自定义属性”)已经由Web浏览器支持了将近四年。只要有方便,我都会使用它们。这取决于我正在从事的项目以及必须解决的特定任务。使用CSS变量很容易,并且可以为开发人员带来极大的好处。但是,前端程序员经常错误地使用CSS变量,或者不了解使用它们的具体细节。 我写这篇文章是为了编译关于CSS变量的所有知识。在研究过程中,我希望能学到一些新的知识,并简化我已经知道的知识。您将在本教程中找到有关CSS变量所需的所有知识。有许多使用CSS变量的实际示例和场景描述。











准备?如果是这样,让我们​​开始吧。



介绍



CSS变量是在CSS中声明的值,用于两个目的。首先是这些值的重用。二是减少CSS代码量。让我们看一个简单的例子。





样式页面元素



.section {
  border: 2px solid #235ad1;
}

.section-title {
  color: #235ad1;
}

.section-title::before {
  content: "";
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: #235ad1;
}


此CSS示例#235ad1使用该3次。想象一下,这是一个较大项目的一部分。在其中,相似的样式分散在许多CSS文件中。您被要求改变颜色#235ad1。在这种情况下,最好的办法是利用代码编辑器的能力来查找和替换字符串值。



但是,使用CSS变量使这些任务更加容易。让我们谈谈如何声明CSS变量。变量名称前必须有两个连字符。让我们为:root元素伪类声明一个样式变量<html>



:root {
  --color-primary: #235ad1;
}

.section {
  border: 2px solid var(--color-primary);
}

.section-title {
  color: var(--color-primary);
}

.section-title::before {
  /*   */
  background-color: var(--color-primary);
}


在我看来,这段代码看起来比以前的代码干净得多。该变量--color-primary是全局变量,因为它是以伪类的样式声明的:root但是CSS变量也可以在单个元素的级别上声明,从而限制了它们在文档中的范围。



变量命名



CSS变量的命名规则与各种编程语言中使用的规则并没有太大区别。即,有效的CSS变量名称可以包含字母数字字符,下划线和连字符。还值得注意的是,这些变量的名称区分大小写。



/*   */
:root {
  --primary-color: #222;
  --_primary-color: #222;
  --12-primary-color: #222;
  --primay-color-12: #222;
}

/*   */
:root {
  --primary color: #222; /*    */
  --primary$%#%$#
}


可变范围



CSS变量的一个有用功能是可以对它们进行范围调整。这个想法是基于在各种编程语言中应用的相同原理。例如-在JavaScript中:



let element = "cool";

function cool() {
  let otherElement = "Not cool";
  console.log(element);
}


在此示例中,变量element是全局变量,可在函数中使用cool()但是otherElement只能从函数体中访问变量cool()让我们看看应用于CSS变量的想法。



:root {
  --primary-color: #235ad1;
}

.section-title {
  --primary-color: d12374;
  color: var(--primary-color);
}


该变量--primary-color是全局变量,您可以从文档的任何元素中引用它。如果在一个块中覆盖它.section-title,则会导致一个事实,即它的新值只能在该块中使用。



这是解释此想法的图。





CSS变量的范围



这是一个变量,--primary-color用于设置节标题的颜色。我们需要为“特色作者”和“最新文章”部分自定义标题的颜色。因此,在这些部分的样式中,我们将覆盖此变量。变量也会发生同样的事情--unit这是上图所基于的样式。



/*   */
:root {
  --primary-color: #235ad1;
  --unit: 1rem;
}

/*        */
.section-title {
  color: var(--primary-color);
  margin-bottom: var(--unit);
}

/*  ,   */
.featured-authors .section-title {
  --primary-color: #d16823;
}

/*  ,     */
.latest-articles .section-title {
  --primary-color: #d12374;
  --unit: 2rem;
}


使用后备值



通常,“后备值”用于使网站在不支持某些现代CSS机制的浏览器中运行。但是这里我们不会在此谈论,而是在无法使用所需的CSS变量的情况下如何设置所使用的值。考虑以下示例:



.section-title {
  color: var(--primary-color, #222);
}


注意将var()多个值传递给该函数第二个#222仅在--primary-color未定义变量的情况下使用指定后备值时,您还可以使用嵌套结构var()



.section-title {
  color: var(--primary-color, var(--black, #222));
}


如果变量的值取决于某些操作,则这种使用变量的方法可能会很有用。如果可能发生的情况是变量中没有值,那么考虑使用后备值很重要。



使用CSS变量的示例和场景



▍元件尺寸控制





不同大小的组件



设计系统通常具有例如不同大小的按钮。通常,我们在谈论三种尺寸(小,常规,大)。使用CSS变量很容易描述此类按钮和其他类似元素。



.button {
  --unit: 1rem;
  padding: var(--unit);
}

.button--small {
  --unit: 0.5rem;
}

.button--large {
  --unit: 1.5rem;
}


通过更改--unit范围内与按钮组件相对应的变量的值,我们创建了按钮的不同变体。



▍CSS变量和HSL颜色



HSL(色相,饱和度,亮度-色相,饱和度,亮度)是一种颜色模型,其中H分量确定颜色,而S和L分量确定颜色的饱和度和亮度。





使用HSL指定的元素颜色



:root {
  --primary-h: 221;
  --primary-s: 71%;
  --primary-b: 48%;
}

.button {
  background-color: hsl(var(--primary-h), var(--primary-s), var(--primary-b));
  transition: background-color 0.3s ease-out;
}

/*   */
.button:hover {
  --primary-b: 33%;
}


注意如何通过减小变量的值使按钮颜色变深--primary-b



如果您对在CSS中使用颜色的主题感兴趣-这是我的文章。



▍在保持比例的同时调整元素大小



如果您使用过Photoshop,Sketch,Figma或Adobe XD等设计程序,那么您可能会知道Shift在调整对象大小时使用该键借助此技术,您可以避免扭曲元素的比例。



在保持纵横比的同时,没有用于调整CSS元素大小的标准机制。但是,可以使用CSS变量来规避此限制。





使用CSS变量调整元素大小



假设我们有一个宽度和高度必须相同的图标。为此,我定义了一个CSS变量--size并将其用于调整元素的宽度和高度。



.icon {
  --size: 22px;
  width: var(--size);
  height: var(--size);
}


结果,事实证明,该技术可Shift在调整对象大小时模拟键的使用更改一个变量的值就足够了--size这里将更详细地介绍该主题



▍基于CSS网格的布局



当基于CSS Grid设计页面布局时,CSS变量非常有用。想象一下,您需要使Grid容器根据元素的预定义宽度呈现其子级。可以使用CSS变量解决此任务,而不是为每个元素表示创建一个类,而这会导致CSS代码重复。





使用CSS变量调整网格元素的大小



.wrapper {
  --item-width: 300px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
  grid-gap: 1rem;
}

.wrapper-2 {
  --item-width: 500px;
}


通过这种方法,您可以创建适合于各种项目的灵活网格布局,并且易于维护。可以将相同的想法应用于设置属性grid-gap



.wrapper {
  --item-width: 300px;
  --gap: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
}

.wrapper.gap-1 {
  --gap: 16px;
}






使用--gap变量设置grid-gap属性



以复杂的结构存储可变值



▍CSS渐变



所谓的``具有复杂结构的值''是指例如渐变之类的东西。如果项目具有在项目中许多地方使用的渐变或背景,则将其描述存储在CSS变量中是有意义的。



:root {
  --primary-gradient: linear-gradient(150deg, #235ad1, #23d1a8);
}

.element {
  background-image: var(--primary-gradient);
}


在这种情况下,可以在变量中存储``复杂''值的各个元素。例如,这可以是渐变的角度:



.element {
  --angle: 150deg;
  background-image: linear-gradient(var(--angle), #235ad1, #23d1a8);
}

.element.inverted {
  --angle: -150deg;
}






通过更改变量--angle创建不同的渐变选项



▍职位背景



如前所述,CSS变量可以存储复杂值。如果您有一个元素,根据发生的情况,可能需要将其放置在页面上的不同位置,则此功能很有用。





使用--pos变量控制元素的位置



.table {
  --size: 50px;
  --pos: left center;
  background: #ccc linear-gradient(#000, #000) no-repeat;
  background-size: var(--size) var(--size);
  background-position: var(--pos);
}


在明暗主题之间切换



现在,几乎没有故障的站点都配备了黑暗与光明的主题。要解决此问题,可以使用CSS变量,在其中存储有关颜色的信息,并在分析用户的系统参数或设置后在它们之间进行切换。





浅色和深色主题



:root {
  --text-color: #434343;
  --border-color: #d2d2d2;
  --main-bg-color: #fff;
  --action-bg-color: #f9f7f7;
}

/* ,    <html> */
.dark-mode {
  --text-color: #e9e9e9;
  --border-color: #434343;
  --main-bg-color: #434343;
  --action-bg-color: #363636;
}


这是上述想法视频演示。



设定默认值



在某些情况下,您需要使用JavaScript设置CSS变量假设我们要为height可以调整大小元素设置属性值我了解到的,这种技术这个文章。



该变量--details-height-open最初为空。计划将其用于描述某些元素的样式。它应包含元素的高度(以像素为单位)。如果由于某种原因无法通过JavaScript设置此变量的值,则必须提供一些默认后备值的使用,这一点很重要。



.section.is-active {
  max-height: var(--details-height-open, auto);
}


在此示例中,默认播放auto如果JavaScript无法设置该变量的值,则将应用该变量--details-height-open



调整容器元素的宽度





控制容器



元素的宽度在不同情况下,网页中使用的容器元素可以具有不同的大小。也许一页可能需要一个小容器,而另一页可能需要一个大容器。在这种情况下,CSS变量可以成功用于控制容器的大小。



.wrapper {
  --size: 1140px;
  max-width: var(--size);
}

.wrapper--small {
  --size: 800px;
}


内联样式



在内联样式中使用CSS变量可以为他们从未存在过的前端开发人员带来大量新的可能性。实际上,我写了整篇文章,但是在这里,我仍将讨论以内联样式使用变量的最有趣的方法。



最好不要在生产中使用这些方法。它们非常适合用于原型设计和探索各种设计思想。



动态网格元素



例如,要调整元素的宽度,可以使用--item-width直接在element属性中声明的变量style在对网格布局进行原型制作时,此方法可能很有用。



这是该元素的HTML:



<div class="wrapper" style="--item-width: 250px;">
  <div></div>
  <div></div>
  <div></div>
</div>


这是应用于此元素的样式:



.wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
  grid-gap: 1rem;
}


在这里,您可以尝试使用本节的示例。



▍用户头像





不同大小的头像



内联样式中CSS变量的另一个有趣用法是创建不同大小的元素。假设我们在不同情况下需要显示各种大小的用户头像。话虽如此,我们想使用一个CSS变量来控制其大小。



这是标记:



<img src="user.jpg" alt="" class="c-avatar" style="--size: 1" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 2" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 3" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 4" />


以下是样式:



.c-avatar {
  display: inline-block;
  width: calc(var(--size, 1) * 30px);
  height: calc(var(--size, 1) * 30px);
}


让我们分析一下这些样式:



  • 我们有一个设计var(--size, 1)它提供一个默认值。如果--size未使用style样式元素的属性设置变量的值,则使用它
  • 最小元素大小设置为30px*30px


媒体查询



一起使用CSS变量和媒体查询可以大大有助于自定义网站所有页面上使用的变量的值。我想到的使用此技术的最简单示例是调整元素之间的间距:



:root {
  --gutter: 8px;
}

@media (min-width: 800px) {
  :root {
    --gutter: 16px;
  }
}


结果,使用该变量的任何元素的属性--gutter将取决于浏览器视口的宽度。对我来说,这是一个巨大的机会。



遗产



CSS变量支持继承。如果在父元素中声明了CSS变量,则后代元素将继承此变量。让我们来看一个例子。



这是HTML:



<div class="parent">
  <p class="child"></p>
</div>


以下是样式:



.parent {
  --size: 20px;
}

.child {
  font-size: var(--size);
}


元素.child继承了--size以元素style声明的变量.parent该项目.child有权访问此变量。我觉得这很有趣。也许您现在想知道它如何使我们受益。我相信以下现实生活中的例子将有助于回答这个问题。





CSS变量继承



有一组按钮,它们具有以下要求:



  • 通过设置单个变量的值来调整所有元素大小的能力。
  • 元素之间的距离应根据其大小动态变化。随着元素的增加,它们之间的距离增加,而随着元素的减少,元素之间的距离减小。


这是此示例的标记:



<div class="actions">
  <div class="actions__item"></div>
  <div class="actions__item"></div>
  <div class="actions__item"></div>
</div>


以下是样式:



.actions {
  --size: 50px;
  display: flex;
  gap: calc(var(--size) / 5);
}

.actions--m {
  --size: 70px;
}

.actions__item {
  width: var(--size);
  height: var(--size);
}


请注意--size,在为gapFlexbox项设置属性时我是如何使用变量的这允许基于变量--size动态更改元素之间的距离,



另一个通过设置CSS动画展示使用CSS变量的继承机制的示例。从这里举这个例子



@keyframes breath {
  from {
    transform: scale(var(--scaleStart));
  }
  to {
    transform: scale(var(--scaleEnd));
  }
}

.walk {
  --scaleStart: 0.3;
  --scaleEnd: 1.7;
  animation: breath 2s alternate;
}

.run {
  --scaleStart: 0.8;
  --scaleEnd: 1.2;
  animation: breath 0.5s alternate;
}


使用这种方法,我们不需要声明两次@keyframes样式.walk.run覆盖继承的变量值。



验证CSS变量



如果发现传递给该函数的CSS变量var()有问题,浏览器将用相应属性的原始(继承)值替换此变量的值。



:root {
  --main-color: 16px;
}

.section-title {
  color: var(--main-color);
}


在此,将值写入--main-color用于设置属性的变量这是完全错误的。该属性是继承的。在这种情况下,浏览器将根据以下算法工作:color16pxcolor



  • 该属性是否可继承?


这是浏览器的工作方式。





检测到无效的CSS变量值时浏览器的工作方式



computation计算过程中出现无效值的概念



从技术角度来看,上面讨论的内容称为“计算值时间无效”。当将var()有效的CSS变量传递给该函数时会出现这种值的情况,该变量的值不适合写入通过其帮助配置的属性。



请看下面的例子,这是我从把这个文章:



.section-title {
  top: 10px;
  top: clamp(5px, var(--offset), 20px);
}


如果浏览器不支持该功能clamp(),它将使用构造中指定的值作为后备top: 10px吗?简短地回答这个问题,不-它不会使用它。这样做的原因是,当浏览器检测到他们试图写入属性的无效值时,它将按照级联样式的顺序丢弃其他值。也就是说,它将完全忽略构造top: 10px



这是CSS规范说明的内容



存在计算期间出现无效值的概念,因为与变量相关联的错误不像其他语法错误那样在系统的早期阶段出现。因此,事实证明,当用户代理发现变量的值不正确时,它已经按照级联样式的顺序丢弃了其他值。



结果,事实证明,如果要使用CSS变量实现的浏览器不广泛支持的CSS功能,则需要应用指令@supports上面的文章就是这样完成的:



@supports (top: max(1em, 1px)) {
  #toc {
    top: max(0em, 11rem - var(--scrolltop) * 1px);
  }
}


有趣的发现



URL将URL存储在变量中 



网页中使用的某些资源可能需要从外部资源下载。在这种情况下,您可以将这些资源的URL存储在CSS变量中。



:root {
  --main-bg: url("https://example.com/cool-image.jpg");
}

.section {
  background: var(--main-bg);
}


此时,可能会出现一个问题,即是否可以var(--main-bg)使用CSS函数处理视图构造url()考虑以下示例:



:root {
  --main-bg: "https://example.com/cool-image.jpg";
}

.section {
  background: url(var(--main-bg));
}


这将不起作用,因为该函数url()将整个结构解释var(--main-bg)为URL,这是错误的。到浏览器计算值时,它已经不正确,所考虑的构造将无法按预期工作。



▍存储多个值



多个值可以存储在CSS变量中。如果这些值看起来像应该在您打算使用该变量的位置查看,那么这种构造将起作用。让我们来看一个例子。





变量值看起来像预期的一样



这是CSS:



:root {
  --main-color: 35, 90, 209;
}

.section-title {
  color: rgba(var(--main-color), 0.75);
}


它具有一个函数rgba()和RGB值,以逗号分隔并存储在CSS变量中。在指定颜色时使用这些值。通过这种使用函数的方法rgba(),开发人员有机会影响与颜色的Alpha通道相对应的值,从而调整各种元素的颜色。



这种方法的唯一缺点是rgba()无法使用浏览器开发人员工具来调整功能分配的颜色。如果在项目上使用此功能很重要,则上述使用该功能的方法可能对您不起作用rgba()



这是一个使用CSS变量设置属性的示例background



:root {
  --bg: linear-gradient(#000, #000) center/50px;
}

.section {
  background: var(--bg);
}

.section--unique {
  background: var(--bg) no-repeat;
}


这显示了网站的两个部分的样式。其中之一的背景不应沿x轴重复y



in在@keyframes规则的主体中更改CSS变量的值



如果您已阅读有关CSS变量的规范,则可能会遇到“动画污染”一词。它描述了CSS变量的值不能使规则平滑变化的事实@keyframes让我们来看一个例子。



这是HTML:



<div class="box"></div>


以下是样式:



.box {
  width: 50px;
  height: 50px;
  background: #222;
  --offset: 0;
  transform: translateX(var(--offset));
  animation: moveBox 1s infinite alternate;
}

@keyframes moveBox {
  0% {
    --offset: 0;
  }
  50% {
    --offset: 50px;
  }
  100% {
    --offset: 100px;
  }
}


在这种情况下,动画将不流畅。该变量仅包含三个值050px100px。 CSS规范指出,规则中使用的任何自定义属性都将@keyframes成为受动画污染的属性,这会影响在为var()元素设置动画时函数如何处理该属性。



如果我们需要在前面的示例中提供平滑的动画,则必须像以前一样进行。也就是说,您需要将变量替换为要设置动画的元素的CSS属性。



@keyframes moveBox {
  0% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(50px);
  }
  100% {
    transform: translateX(100px);
  }
}


这是一个示例,



我想指出,在本文发表后,我被告知@keyframes仍然可以在中为CSS变量设置动画但是为此,必须使用rule注册变量@property到目前为止,仅基于Chromium的浏览器支持此功能。



@property --offset {
  syntax: "<length-percentage>";
  inherits: true;
  initial-value: 0px;
}


在这里,您可以尝试使用此功能的示例。



ulation计算



您可能没有意识到CSS变量可用于计算的事实。让我们看一下讨论化身时已经看过的示例:



.c-avatar {
  display: inline-block;
  width: calc(var(--size, 1) * 30px);
  height: calc(var(--size, 1) * 30px);
}


化身的大小取决于变量的值--size默认值为1这意味着默认头像大小为30px*30px请注意以下样式,更改此变量将更改化身的大小。



.c-avatar--small {
  --size: 2;
}

.c-avatar--medium {
  --size: 3;
}

.c-avatar--large {
  --size: 4;
}


浏览器开发人员工具和CSS变量



使用各种浏览器的开发人员工具时,可以使用一些有用的技巧来简化CSS变量的使用。让我们谈谈他们。



▍查看使用变量定义的颜色



我发现能够看到CSS变量描述的颜色很有用。Chrome和Edge浏览器中提供了此功能。





查看CSS变量指定的颜色



▍计算值



为了查看CSS变量的计算值,取决于浏览器,将鼠标指针移到变量上或单击特殊按钮。





查看计算值



在Safari以外的所有浏览器中,只需将鼠标悬停在变量上即可查看计算值在Safari中,您需要单击带有几个条纹的按钮来执行此操作。



▍自动完成输入



在大型项目上工作时,很难记住其中使用的所有CSS变量的名称。但是,借助Chrome,Firefox和Edge浏览器中的自动完成功能,这不是问题。





为使



该机制起作用,需要完成变量名的填写-只需开始输入变量名即可。



▍禁用CSS变量



如果需要从使用CSS变量的所有元素中禁用CSS变量,则只需在声明它的元素中取消选中该变量旁边的框即可。





复选框以禁用CSS变量



结果



我已经介绍了很多有关CSS变量的内容。我希望您发现今天学到的东西有用。



您是否在项目中使用CSS变量?










All Articles