用於計算父作用域中的變數時,CSS 作用域自訂屬性無法辨識
P粉006847750
P粉006847750 2023-11-01 21:53:10
0
1
661

我正在嘗試透過 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>


#
P粉006847750
P粉006847750

全部回覆(1)
P粉440453689

在您的情況下,您已在根層級評估了--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-*


來自規格

在第一種情況下,您會陷入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 內求值code> 因此我們已經用它們的值替換了它們。

在這種情況下,我們有 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 {
  --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>
  • :root 選擇器變更為通用選擇器 *。這將確保我們的函數在所有層級上都得到定義和評估。在某些複雜的情況下,這可能會產生一些不必要的結果

* {
  --r:0;
  --g:0;
  --b:255;
  --color:rgb(var(--r),var(--g),var(--b))
}
div {
  color:var(--color);
}
p {
  --g:200;
  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>
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板