自定义属性作为状态

Avatar of Chris Coyier
Chris Coyier on

DigitalOcean 提供适合您旅程各个阶段的云产品。立即开始使用 $200 的免费信用额度!

这是 James Stanley 的一个 有趣的想法:一个 CSS 文件(可能每天更新)包含“季节性”颜色的 CSS 自定义属性(例如,春季是绿色,秋季是橙色)。然后,您可以使用这些值来为您的网站设置主题,并知道这些颜色每天都会略有变化。

这是我在写这篇文章时想到的

:root {
  --seasonal-bg: hsl(-68.70967741935485,9.419354838709678%,96%);
  --seasonal-bgdark: hsl(-68.70967741935485,9.419354838709678%,90%);
  --seasonal-fg: hsl(-68.70967741935485,9.419354838709678%,30%);
  --seasonal-hl: hsl(-83.70967741935485,30.000000000000004%,50%);
  --seasonal-hldark: hsl(-83.70967741935485,30.000000000000004%,35%);
}

我认为如果提供的 CSS 文件只是自定义属性,而不是带有主观意见的其他样式(比如设置主体背景),会更有趣。这样,您就可以以任何您选择的方式实现颜色,而不会产生任何副作用。

CSS 作为 API?

这让我想到,像这样的 CDN 托管的 CSS 文件可以包含其他有用的内容,比如今天的日期,用于伪内容,或者其他特殊的时间敏感内容。也许是月相?体育得分?!今日汤品?!

/* <div class="soup">The soup of the day is: </div> */
.soup::after {
  content: var(--soupOfTheDay); /* lol kinda */
}

它几乎就像一个数据 API,非常易于使用。伪内容如今甚至也是可访问的内容——但您无法选择伪元素的文本,所以不要将其理解为使用 CSS 作为内容 API 的实际认可。

自定义属性的灵活性

Will Boyd 刚刚发布了一篇关于 自定义属性中可能出现的内容 的博文。它们非常灵活。几乎任何东西都是有效的自定义属性值,并且用法往往会按您预期的那样工作。

body {
  /* totally fine */
  --rgba: rgba(255, 0, 0, 0.1);
  background: var(--rgba);

  /* totally fine */
  --rgba: 255, 0, 0, 0.1;
  background: rgba(var(--rgba));

  /* totally fine */
  --rgb: 255 0 0;
  --a: 0.1;
  background: rgb(var(--rgb) / var(--a));
}

body::after {
  /* totally fine */
  --song: "I need quotes to be pseudo content \A and can't have line breaks without this weird hack \A but still fairly permissive (💧💧💧) ";
  content: var(--song);
  white-space: pre;
}

Bram Van Damme 在介绍 Will 的文章时,抓住了这种灵活性

这就是为什么您可以使用 CSS 自定义属性来

执行条件计算

将数据从 CSS 传递到 JavaScript

将肤色/头发颜色修饰符注入 Emoji

使用一个自定义属性切换多个值(--foo: ; 黑客技巧)

Bram 指出了自定义属性可以实现的这种“基本”状态翻转功能

:root {
  --is-big: 0;
}

.is-big {
  --is-big: 1;
}

.block {
  padding: calc(
    25px * var(--is-big) +
    10px * (1 - var(--is-big))
  );
  border-width: calc(
    3px * var(--is-big) +
    1px * (1 - var(--is-big))
  );
}

添加几勺复杂性,您就可以得到 The Raven(使用自定义属性的媒体查询)。

我非常希望看到 CSS 中发生一些改变,使这变得更容易。使用 CSS 自定义属性来进行一般状态操作将非常棒。我们可以对 UI 处于任意状态时应用任意样式!想想媒体查询现在有多么有用,或者容器查询将有多么有用,但是由于它是任意状态,而不是这些东西所公开的状态,所以它会更加复杂。

Bram 也涵盖了这一点,他提到了 Lea Verou 所谓的 “高级自定义属性”

/* Theoretical! */

.square {
  width: 2vw;
  padding: 0.25vw;
  aspect-ratio: 1/1;

  @if (var(--size) = big) {
    width: 16vw;
    padding: 1vw;
  }
}

.my-input {
  @if(var(--pill) = on) {
    border-radius: 999px;
   }
}

关于命名

Will 将它们称为“CSS 变量”,这是非常常见且易于理解的。您会经常读到(我也写过)类似“CSS 变量(也称为 CSS 自定义属性)”或“CSS 自定义属性(也称为 CSS 变量)”的句子。Šime Vidas 最近 指出,有一种比较正确的称呼方式:--this-part 是自定义属性,var(--this-part) 是变量,这直接来自 规范 中的用法。

JavaScript 库状态… 自动化?

这让我回想起 这个 Vue 提案。我不确定它是否取得了进展,但想法是组件的状态将自动公开为 CSS 自定义属性。

<template>
  <div class="text">Hello</div>
</template>

<script>
export default {
  data() {
    return {
      color: 'red'
    }
  }
}
</script>

<style vars="{ color }">
.text {
  color: var(--color);
}
</style>

由于此组件的状态包含color,因此--color 将作为状态提供给此组件的 CSS。我认为这是一个好主意。

如果每次在 React 中使用useState 时,CSS 自定义属性都会被放到:root 上并自动更新,会怎么样?例如,如果您这样做

import React, { useState } from 'https://cdn.skypack.dev/react@^16.13.1';
import ReactDOM from 'https://cdn.skypack.dev/react-dom@^16.13.1';

const App = () => {
  const [ activeColor, setActiveColor ] = useState("red");
  return(
    <div className="box">
      <h1>Active Color: {activeColor}</h1>
      <button onClick={() => {setActiveColor("red")}}>red</button>
      <button onClick={() => {setActiveColor("blue")}}>blue</button>
    </div>
  );
}

ReactDOM.render(<App />,
document.getElementById("root"))

并且您知道您可以像这样操作

.box {
  border-color: 2px solid var(--activeColor);
}

因为状态自动映射到自定义属性。有人应该创建一个useStateWithCustomProperties 钩子或类似的东西来实现这一点。#免费想法

像 React 和 Vue 这样的库用于构建 UI。我认为他们管理的状态自动公开给 CSS 是很有意义的。

浏览器可以为我们提供更多页面状态作为环境变量吗?

说到 CSS 应该了解的状态,我已经看到了不少演示,它们通过将鼠标当前位置或滚动位置映射到 CSS 来实现有趣的功能。我认为要求将这些数据以原生方式公开给 CSS 并不完全不合理。我们已经有了环境变量的概念,比如env(safe-area-inset-top),我可以想象它可以用来公开页面状态,比如env(page-scroll-percentage)env(mouseY)