用于计算外部范围中的变量时忽略CSS范围的自定义属性

1wnzp6jl  于 2023-02-10  发布在  其他
关注(0)|答案(2)|浏览(94)

我尝试通过var自定义属性来缩放大小,这样类就可以在没有耦合的情况下组合。预期的效果是3个列表将处于3个不同的比例,但作为demonstrated on CodePen,所有3个列表都是相同的比例。我正在寻找作用域的解释和CSS自定义属性技术,可以通过可组合的松散耦合代码实现这一点。

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

llmtgqce1#

在您的示例中,您已经在根级别计算了--scale自定义属性以定义--size-*属性,然后在子元素中 * 再次 * 定义了--scale。这不会再次触发计算,因为它已经在更高级别中完成。
下面是一个简单的例子来说明这个问题:

.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定义相同的级别:
一个二个一个一个
在这种情况下,--scale定义在与其求值相同的级别,因此--size-*将在每种情况下正确定义。
根据质量标准:

***替换属性值中的var()***:

1.如果var()函数的第一个参数命名的自定义属性受动画污染,并且var()函数正在animation属性或其一个长柄中使用,则在此算法的其余部分中,将该自定义属性视为具有初始值。
1.如果var()函数的第一个参数所命名的自定义属性的值不是初始值,请将var()函数替换为相应的自定义属性的值。否则,
1.如果var()函数有一个回退值作为它的第二个参数,用回退值替换var()函数。2如果回退中有任何var()引用,也替换它们。
1.否则,包含var()函数的属性在计算值时无效
在第一种情况下,您会陷入3,因为在根级别没有为--scale指定值;在最后一种情况下,我们会陷入2,因为我们在同一级别定义了--scale,并且我们有它的值。
在所有情况下,我们都应该避免在:root级别上求值,因为它根本没用。根级别是DOM中的最高级别,因此所有元素都将继承相同的值,除非我们再次求值,否则DOM中不可能有不同的值。
您的代码等效于以下代码:

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

再举一个例子:

: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,但我们无法做到这一点,上面的代码与以下代码相同:

:root {
  --color:rgb(0,0,255)
}
div {
  color:var(--color);
}
p {
  --g:100;
  color:var(--color);
}
<div>
  some text
</div>
<p>
  some text
</p>

3个变量(--r--g--b)在:root中求值,因此我们已经用它们的值替换了它们。
在这种情况下,我们有3种可能性:

  • 使用JS或其他CSS规则更改:root中的变量。这将不允许我们使用不同的颜色:
: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中的定义将变得无用(或者至少将成为默认值):

一个一个一个一个

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

一个一个三个一个一个
考虑到这一点,我们应该始终将求值保持在DOM树中可能的最低点,尤其是在变量更改之后(或者在同一级别)
这是我们不应该做的

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

我们应该这样做
一个17块一个18块一个
我们也可以这样做:

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

yks3o0rb2#

根据另一个答案中的信息,您可以简单地将[class^="scale-"]与根沿着添加,这样它就可以在以类“scale-”开头的元素上重新计算

:root,
[class^="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);
}

工作:https://codepen.io/gpoitch/pen/YzjoYNX

相关问题