搜尋

首頁  >  問答  >  主體

用於計算父作用域中的變數時,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>


#
P粉006847750P粉006847750421 天前687

全部回覆(1)我來回復

  • P粉440453689

    P粉4404536892023-11-02 11:27:45

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

    回覆
    0
  • 取消回覆