首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于计算外部作用域变量时忽略的CSS作用域自定义属性。

用于计算外部作用域变量时忽略的CSS作用域自定义属性。
EN

Stack Overflow用户
提问于 2018-08-25 09:15:01
回答 1查看 3.8K关注 0票数 21

我试图通过var自定义属性进行缩放,使类可以在不耦合的情况下进行组合。所期望的效果是,这3个列表将在3个不同的规模,但作为在CodePen上演示,所有3个列表是相同的规模。我正在寻找关于作用域和CSS自定义属性技术的解释,它可以通过可组合的松散耦合代码来实现这一点。

代码语言:javascript
复制
:root {
  --size-1: calc(1 * var(--scale, 1) * 1rem);
  --size-2: calc(2 * var(--scale, 1) * 1rem);
  --size-3: calc(3 * var(--scale, 1) * 1rem);
}

.size-1 { font-size: var(--size-1) }
.size-2 { font-size: var(--size-2) }
.size-3 { font-size: var(--size-3) }

.scale-1x { --scale: 1 }
.scale-2x { --scale: 2 }
.scale-3x { --scale: 3 }

html {
  font: 1em sans-serif;
  background: papayawhip;
}

ol {
  float: left;
  list-style: none;
  margin: 1rem;
}
代码语言:javascript
复制
<ol class="scale-1x">
  <li class="size-1">size 1</li>
  <li class="size-2">size 2</li>
  <li class="size-3">size 3</li>
</ol>
<ol class="scale-2x">
  <li class="size-1">size 1</li>
  <li class="size-2">size 2</li>
  <li class="size-3">size 3</li>
</ol>
<ol class="scale-3x">
  <li class="size-1">size 1</li>
  <li class="size-2">size 2</li>
  <li class="size-3">size 3</li>
</ol>

EN

回答 1

Stack Overflow用户

发布于 2018-08-25 09:24:16

在您的示例中,您已经在根级别评估了--scale自定义属性以定义--size-*属性,然后在子元素中再次定义--scale。这不会再次触发评估,因为它已经在高级中完成了。

下面是一个简单的例子来说明这个问题:

代码语言:javascript
复制
.box {
  --color: var(--c, blue);
}

span {
  color: var(--color);
}
代码语言:javascript
复制
<div>
  <div class="box"><!-- --c is evaluated at this level -->
    <span style="--c:red">I will not be red because the property is already evaluated and --color is set to blue using the default value</span>
  </div>
</div>

<div style="--c:red">
  <div class="box"><!-- --c is evaluated at this level -->
    <span>I will be red because at the time of the evaluation --c is red (inherited from the upper div)</span>
  </div>
</div>

要解决问题,需要将声明从:root移到与--scale定义相同的级别:

代码语言:javascript
复制
.scale {
  --size-1: calc(1 * var(--scale, 1) * 1rem);
  --size-2: calc(2 * var(--scale, 1) * 1rem);
  --size-3: calc(3 * var(--scale, 1) * 1rem);
}

.size-1 { font-size: var(--size-1) }
.size-2 { font-size: var(--size-2) }
.size-3 { font-size: var(--size-3) }

.scale-1x { --scale: 1 }
.scale-2x { --scale: 2 }
.scale-3x { --scale: 3 }


html {
  font: 1em sans-serif;
  background: papayawhip;
}

ol {
  float: left;
  list-style: none;
  margin: 1rem;
}
代码语言:javascript
复制
<ol class="scale-1x scale">
  <li class="size-1">size 1</li>
  <li class="size-2">size 2</li>
  <li class="size-3">size 3</li>
</ol>
<ol class="scale-2x scale">
  <li class="size-1">size 1</li>
  <li class="size-2">size 2</li>
  <li class="size-3">size 3</li>
</ol>
<ol class="scale-3x scale">
  <li class="size-1">size 1</li>
  <li class="size-2">size 2</li>
  <li class="size-3">size 3</li>
</ol>

在这种情况下,--scale被定义在与其计算级别相同的级别上,因此将为每个案例正确地定义--size-*

来自规格

若要替换属性值中的var(),请执行以下操作:

  1. 如果var()函数的第一个参数命名的自定义属性是动画污染的,并且var()函数正在动画属性或其一个长数字中使用,则将该自定义属性视为该算法其余部分的初始值。
  2. 如果var()函数的第一个参数命名的自定义属性的值不是初始值,则将var()函数替换为相应的自定义属性的值。否则,
  3. 如果var()函数的第二个参数为回退值,则将var()函数替换为回退值。如果回退中有var()引用,也可以替换它们。
  4. 否则,包含var()函数的属性在计算值时无效。

在第一种情况下,您将陷入3,因为在根级没有为--scale指定值。在最后一个例子中,我们进入了2,因为我们在相同的级别上定义了--scale,并且我们有它的值。

在所有情况下,我们都应该避免在:root级别上进行任何评估,因为它根本没用。根级别是DOM中的最上层,所以所有元素都将继承相同的值,除非我们再次计算变量,否则在DOM中不可能有不同的值。

您的代码与此代码等效:

代码语言:javascript
复制
:root {
  --size-1: calc(1 * 1 * 1rem);
  --size-2: calc(2 * 1 * 1rem);
  --size-3: calc(3 * 1 * 1rem);
}

让我们再举一个例子:

代码语言:javascript
复制
:root {
  --r:0;
  --g:0;
  --b:255;
  --color:rgb(var(--r),var(--g),var(--b))
}
div {
  color:var(--color);
}
p {
  --g:100;
  color:var(--color);
}
代码语言:javascript
复制
<div>
  some text
</div>
<p>
  some text
</p>

从直觉上讲,我们可能认为可以通过更改在--color级别上定义的三个变量中的一个来更改:root,但我们不能这样做,而且上面的代码与这个相同:

代码语言:javascript
复制
:root {
  --color:rgb(0,0,255)
}
div {
  color:var(--color);
}
p {
  --g:100;
  color:var(--color);
}
代码语言:javascript
复制
<div>
  some text
</div>
<p>
  some text
</p>

三个变量(--r--g--b)在:root中进行计算,因此我们已经用它们的值替换了它们。

在这种情况下,我们有三种可能性:

  • 使用JS或其他CSS规则更改:root中的变量。这将不允许我们有不同的颜色:

代码语言:javascript
复制
:root {
  --r:0;
  --g:0;
  --b:255;
  --color:rgb(var(--r),var(--g),var(--b))
}
div {
  color:var(--color);
}
p {
  --g:200; /*this will not have any effect !*/
  color:var(--color);
}

:root {
  --g:200; /*this will work*/
}
代码语言:javascript
复制
<div>
  some text
</div>
<p>
  some text
</p>

  • 在所需的元素中重新计算变量。在这种情况下,我们将失去任何类型的灵活性,:root中的定义将变得毫无用处(或者至少会成为默认值):

代码语言:javascript
复制
:root {
  --r:0;
  --g:0;
  --b:255;
  --color:rgb(var(--r),var(--g),var(--b))
}
div {
  color:var(--color);
}
p {
  --g:200;
  --color:rgb(var(--r),var(--g),var(--b));
  color:var(--color);
}
代码语言:javascript
复制
<div>
  some text
</div>
<p>
  some text
</p>

  • 使用通用选择器:root *更改*选择器。这将确保在所有级别上定义和评估我们的函数。在某些复杂的情况下,这可能会产生一些不必要的结果。

代码语言:javascript
复制
* {
  --r:0;
  --g:0;
  --b:255;
  --color:rgb(var(--r),var(--g),var(--b))
}
div {
  color:var(--color);
}
p {
  --g:200;
  color:var(--color);
}
代码语言:javascript
复制
<div>
  some text
</div>
<p>
  some text
</p>

考虑到这一点,我们应该始终将求值保持在DOM树中的最低可能点,特别是在变量更改后(或在同一级别)。

以下是我们不该做的事

代码语言:javascript
复制
:root {
  --r: 0;
  --g: 0;
  --b: 0;
}
.color {
  --color: rgb(var(--r), var(--g), var(--b))
}
.green {
  --g: 255;
}
.red {
  --r: 255;
}
p {
  color: var(--color);
}

h1 {
  border-bottom: 1px solid var(--color);
}
代码语言:javascript
复制
<div class="color">
  <h1 class="red">Red </h1>
  <p class="red">I want to be red :(</p>
</div>
<div class="color">
  <h1 class="green">Green </h1>
  <p class="green">I want to be green :(</p>
</div>

以下是我们应该做的

代码语言:javascript
复制
:root {
  --r:0;
  --g:0;
  --b:0;
}
.color {
  --color:rgb(var(--r),var(--g),var(--b));
}

.green {
  --g:255;
}

.red {
  --r:255;
}

p {
  color:var(--color);
}
h1 {
  border-bottom: 1px solid var(--color);
}
代码语言:javascript
复制
<div class="red">
  <h1 class="color">Red title</h1>
  <p class="color">Yes I am red :D</p>
</div>
<div class="green">
  <h1 class="color">Green title</h1>
  <p class="color">Yes I am green :D</p>
</div>

我们也可以这样做:

代码语言:javascript
复制
:root {
  --r:0;
  --g:0;
  --b:0;
}
.color {
  --color:rgb(var(--r),var(--g),var(--b));
}

.green {
  --g:255;
}

.red {
  --r:255;
}

p {
  color:var(--color);
}
h1 {
  border-bottom: 1px solid var(--color);
}
代码语言:javascript
复制
<div class="red color">
  <h1 >Red title</h1>
  <p >Yes I am red :D</p>
</div>
<div class="green color">
  <h1>Green title</h1>
  <p >Yes I am green :D</p>
</div>

票数 29
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52015737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档