Собственное свойство CSS-области игнорируется при использовании для вычисления var во внешней области видимости - PullRequest
0 голосов
/ 25 августа 2018

Я пытаюсь масштабировать размер с помощью var пользовательских свойств таким образом, чтобы классы составлялись без связывания.Желаемый эффект состоит в том, что 3 списка будут иметь 3 разных масштаба, но, как показано на на кодовой ручке , все 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>

1 Ответ

0 голосов
/ 25 августа 2018

Это немного сложно, но в вашем случае вы оценили пользовательское свойство --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-* будет определяться правильно для каждого случая.


С спецификацией :

На подставить переменную () в значении свойства:

  1. Если пользовательское свойство, названное первым аргументом функции var (), испорчено анимацией, а функция var () используется в свойстве animation или в одном из его длинных строк, обработайте пользовательское свойствокак имеющее начальное значение для остальной части этого алгоритма.
  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, изменив одну из 3 переменных, определенных на уровне :root, но нет.Мы не можем этого сделать, и приведенный выше код такой же, как этот:

: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, поэтому мы уже можем подставить их значения.

В такой ситуации у нас есть 2 возможности:

  • Изменить переменные внутри :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>
...