用于在外部范围内计算变量时,将忽略CSS范围内的自定义属性 [英] CSS scoped custom property ignored when used to calculate variable in outer scope

查看:60
本文介绍了用于在外部范围内计算变量时,将忽略CSS范围内的自定义属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过var自定义属性缩放大小,以使类无需耦合即可组合.理想的效果是3个列表的缩放比例为3个,但是在CodePen上全部显示了 清单是相同的比例.我正在寻找一种范围界定和CSS定制属性技术的解释,该技术可以通过可组合的松耦合代码来实现这一目标.

I'm attempting to scale size via a var custom property in a way that the classes would compose without being coupled. The desired effect is that the 3 lists would be at 3 different scales but as demonstrated on CodePen all 3 lists are the same scale. I'm looking for an explanation of the scoping and a CSS custom property technique that could achieve this with composable loosely coupled code.

: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;
}

<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>

推荐答案

在您的情况下,您已经在根级别评估了--scale自定义属性以定义--size-*属性,然后定义了--scale .这不会再次触发评估,因为它已经在上级中完成.

In your case you have evaluated the --scale custom property at the root level to define the --size-* properties and then you defined the --scale again inside child elements. This will not trigger evaluation again because it was already done in an upper level.

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

Here is a simple example to illustrate the issue:

.box {
  --color: var(--c, blue);
}

span {
  color: var(--color);
}

<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定义相同的级别:

To fix your issue, you need to move the declaration from :root to the same level as the --scale definition:

.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;
}

<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-*.

In this case, --scale is defined at the same level as its evaluation so --size-* will be defined correctly for each case.

来自规范:

用属性值替换var() :

To substitute a var() in a property’s value:

  1. 如果由var()的第一个参数命名的自定义属性 函数被动画污染,并且var()函数正在 动画属性或其惯用手之一,请对待自定义 属性具有该算法其余部分的初始值.
  2. 如果由第一个参数命名的自定义属性的值 var()函数不是初始值,请替换var() 通过相应的自定义属性的值来实现功能.否则,
  3. 如果var()函数将后备值作为第二个参数, 用后备值替换var()函数.如果有的话 后备版本中的var()引用,也可以替换它们.
  4. 否则,包含var()函数的属性在以下位置无效 计算值时间
  1. If the custom property named by the first argument to the var() function is animation-tainted, and the var() function is being used in the animation property or one of its longhands, treat the custom property as having its initial value for the rest of this algorithm.
  2. If the value of the custom property named by the first argument to the var() function is anything but the initial value, replace the var() function by the value of the corresponding custom property. Otherwise,
  3. if the var() function has a fallback value as its second argument, replace the var() function by the fallback value. If there are any var() references in the fallback, substitute them as well.
  4. Otherwise, the property containing the var() function is invalid at computed-value time

在第一种情况下,您属于 3 ,因为在根级别没有为--scale指定值.在最后一种情况下,我们属于 2 ,因为我们在相同的级别上定义了--scale,并且具有它的值.

In your first situation, you are falling into 3 because there is no value specified for --scale at the root level. In the last case we are falling into 2 because we defined --scale at the same level and we have its value.

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

In all the cases, we should avoid any evaluation at :root level because it's simply useless. The root level is the uppermost level in the DOM so all the elements will inherit the same value and it's impossible to have different values inside the DOM unless we evaluate the variable again.

您的代码与此等效:

:root {
  --size-1: calc(1 * 1 * 1rem);
  --size-2: calc(2 * 1 * 1rem);
  --size-3: calc(3 * 1 * 1rem);
}


再举一个例子:


Let's take another example:

: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);
}

<div>
  some text
</div>
<p>
  some text
</p>

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

Intuitively, we may think that we can change the --color by changing one of the 3 variables defined at :root level but we cannot do this and the above code is the same as this one:

:root {
  --color:rgb(0,0,255)
}
div {
  color:var(--color);
}
p {
  --g:100;
  color:var(--color);
}

<div>
  some text
</div>
<p>
  some text
</p>

:root中对3个变量(--r--g--b)进行了求值,因此我们已经用它们的值替换了它们.

The 3 variables (--r, --g, --b) are evaluated inside :root so we have already substituted them with their values.

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

In such a situation we have 2 possibilities:

  • 使用JS或其他CSS规则更改:root中的变量.这将不允许我们使用不同的颜色:
  • Change the variables inside the :root using JS or another CSS rule. This won't allow us to have different colors:

: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*/
}

<div>
  some text
</div>
<p>
  some text
</p>

  • 再次在所需元素内评估变量.在这种情况下,我们将失去任何灵活性,并且:root中的定义将变得无用(或至少将成为默认值):
  • Evaluate the variable again inside the needed element. In this case, we will lose any kind of flexibility and the definition inside :root will become useless (or at least will become the default value):

: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);
}

<div>
  some text
</div>
<p>
  some text
</p>

考虑到这一点,我们应该始终将评估保持在DOM树中的最低点,尤其是在变量更改后(或处于同一级别)

Considering this, we should always keep the evaluation at the lowest possible point in the DOM tree and especially after the variable changes (or at the same level)

这是我们不应该做的

: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);
}

<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>

这是我们应该做的

: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);
}

<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>

我们也可以这样:

: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);
}

<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>

这篇关于用于在外部范围内计算变量时,将忽略CSS范围内的自定义属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆