为了账号安全,请及时绑定邮箱和手机立即绑定

用于计算外部作用域中的变量时,CSS作用域定制属性被忽略

用于计算外部作用域中的变量时,CSS作用域定制属性被忽略

蝴蝶不菲 2019-08-28 15:33:54
用于计算外部作用域中的变量时,CSS作用域定制属性被忽略我试图通过var自定义属性来缩放大小,这种方式可以在没有耦合的情况下构成类。期望的效果是3个列表将是3个不同的比例,但是如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>
查看完整描述

2 回答

?
当年话下

TA贡献1890条经验 获得超9个赞

这很棘手,但在您的情况下,您已经--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-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-*将针对每种情况正确定义。


规格

要在属性值中替换var()

  1. 如果var()函数的第一个参数指定的自定义属性是动画污染的,并且var()函数正在动画属性或其中一个长整数中使用,请将自定义属性视为具有其初始值。其余的这个算法。

  2. 如果var()函数的第一个参数指定的自定义属性的值不是初始值,则将var()函数替换为相应自定义属性的值。除此以外,

  3. 如果var()函数的回退值作为其第二个参数,则用回退值替换var()函数。如果后备中有任何var()引用,也可以替换它们。

  4. 否则,包含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>

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

: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,所以我们已经与他们的价值观取代他们。

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

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

: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 {
  --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树中的最低点,尤其是在变量发生变化之后(或者在同一级别)

这是我们不应该做的

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


查看完整回答
反对 回复 2019-08-28
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

因为CSS从上到下...假设您使用的是继承,父元素是否可以从其子元素继承?不...这里的逻辑相同,根在评估时看不到--scale属性。因此,如果一个子元素改变了一个属性,我们就不会反过来重新评估所有的父属性,这将创建周期并且它将无法工作 

查看完整回答
反对 回复 2019-08-28
  • 2 回答
  • 0 关注
  • 376 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信