как сбросить переменную CSS (она же пользовательские свойства) и использовать резервную?

#css #css-variables

#css #css-переменные

Вопрос:

Я пытаюсь использовать переменные CSS для свойств коробочной модели. Я хочу поддерживать как установку значения для всех сторон, так и для отдельных сторон. Я хочу иметь значения по умолчанию, но в любом случае их можно переопределить. Я пытался использовать резервные значения, но без особого успеха.

Что-то вроде:

 :root {
  --border-width-top: 0;
  --border-width-right: 0;
  --border-width-bottom: 0;
  --border-width-left: 0;
  --border-width: 0;
}
div {
  border-color: red;
  border-style: solid;
  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));
}


div {
  --border-width-top: 10px;
}
  

Это не будет работать, как если бы ширина границы имела значение по умолчанию, тогда оно всегда будет иметь приоритет над резервными значениями.
Не уверен, что в настоящее время есть способ сделать это, но я чувствую себя так близко к поиску решения.

Вот stackblitz, с которым я играю: stackblitz

Комментарии:

1. Ответ Куккуза работает для вашего конкретного примера, но, боюсь, вы действительно спрашиваете, есть ли способ «отменить определение» переменных, определенных выше в дереве DOM. Или я слишком много думаю?

2. @MrLister вы правы, смотрите Решение Temani

Ответ №1:

Вы можете отменить значение, используя initial для использования резервной:

 :root {
  --border-width-top: 2px;
  --border-width-right: 2px;
  --border-width-bottom: 2px;
  --border-width-left: 2px;
  --border-width: 0;
}
div {
  margin:5px;
  border-color: red;
  border-style: solid;
  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));
}


div.box {
  --border-width:initial;
  --border-width-top: 10px;
}  
 <div>some content</div>
<div class="box">some content</div>  

из спецификации:

Начальное значение пользовательского свойства — это пустое значение; то есть вообще ничего. Это начальное значение имеет особое взаимодействие с обозначением var(), которое объясняется в разделе определение var() .

и

Чтобы заменить var() в значении свойства:

  1. Если пользовательское свойство, названное первым аргументом функции var(), заражено анимацией, а функция var() используется в свойстве animation или в одном из его длинных символов, обработайте пользовательское свойство как имеющее его начальное значение для остальной части этого алгоритма.
  2. Если значение пользовательского свойства, названного первым аргументом функции var(), не является начальным значением, замените функцию var() значением соответствующего пользовательского свойства. В противном случае,
  3. если функция var() имеет резервное значение в качестве второго аргумента, замените функцию var() на резервное значение. Если в резервной копии есть какие-либо ссылки на var(), замените их также.
  4. В противном случае свойство, содержащее функцию var(), недопустимо во время вычисления значения

Комментарии:

1. Неплохо. Я не знал этого о initial. Ваш пример немного усложняет использование, поскольку я должен убедиться, что я определяю —border-width как начальное, иначе значение side игнорируется. Однако я попытался установить ее в качестве значения по умолчанию внутри корня, и, похоже, она делает именно то, что мне нужно. Есть ли что-то, что я мог бы упустить, идя этим путем?

2. @masimplo нет, это то же самое. Установка initial внутри root или внутри элемента будет делать то же самое, поскольку во время оценки она будет начальной, поэтому нам все равно, где вы устанавливаете начальную. Мы просто заботимся о значении переменной при выполнении оценки.

Ответ №2:

Резервное значение работает, только если переменная --border-width не определена:

Резервное значение пользовательского свойства, которое используется в случае, если пользовательское свойство недопустимо в используемом контексте.

MDN

Смотрите демонстрацию ниже:

 :root {
  --border-width-top: 0;
  --border-width-right: 0;
  --border-width-bottom: 0;
  --border-width-left: 0;
  /*--border-width: 0;*/
}

div {
  border-color: red;
  border-style: solid;
  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));
}

div {
  --border-width-top: 10px;
}  
 <div id="app">
  <h1>TypeScript Starter</h1>
</div>  

Комментарии:

1. Да, это тоже было моим пониманием. Я ищу способ определить переменную, но не присваивать ей значение. Это делается для того, чтобы она присутствовала в документации, но не влияла на границу, если не задана явно. Спасибо за ответ.

Ответ №3:

Как объяснил @Temani, вы можете использовать --varName: initial для установки того, что фактически является пустым, но недопустимым значением для переменной. Тогда будут использоваться любые резервные значения, объявленные var(....) в .

Итак, если вы определяете --text_color: initial , затем используйте селектор: color: var(--text_color, hotpink) ваш текст будет розовым, а не черным (что было бы, если бы вы писали напрямую color: initial ).


Затем я подумал, не мог бы я использовать unset вместо initial . Просто казалось более естественным отменить определение переменной с помощью --text_color: unset . Это более интуитивно понятно, и, поскольку вы, вероятно, редко используете unset , вы запомните свое намерение.

Однако оказывается unset , что это работает не совсем так, как initial , но иногда может быть полезно, если вам нужно наследовать переменные, объявленные выше.

--text_color: initial

  • Устанавливает значение переменной в пустое значение (см. Ссылку на спецификацию в ответе Тамани)
  • Любые установленные узлы-предки --text_color будут переопределены этим объявлением
  • Мне нравится думать об этом так, как если бы вы могли установить --text_color: null

--text_color: unset

  • Эффективно удаляет переменную полностью из этого узла DOM. Он не устанавливает для нее значение magic empty — он ведет себя так же, как если бы вы просто удалили его из своего кода.
  • Это позволяет использовать любое унаследованное значение.
  • Мне нравится думать об этом так, как если бы вы могли установить --text_color: undefined
  • Итак, если какой-либо узел DOM-предка определяет --text_color: green , и ваш узел объявляет --text_color: unset вместе с color: var(--text_color, blue) ним, он будет зеленым, а не синим.

Это было полезно для меня, потому что я динамически устанавливаю множество переменных, и мне нужно было сбросить ее, как если бы она никогда не была установлена.

Независимо от того, является ли это фактическим поведением спецификации, я не могу обещать 🙂

Ответ №4:

Вы также можете сделать это в Javascript:

 element.style.setProperty('--button_icon_active_color', '')
element.style.setProperty('--button_icon_active_color', null)
  

Оба они будут «сбрасывать» значение, как если бы его никогда не было.

Если вы запустите эту команду в консоли браузера, вы увидите, что она исчезнет из стилей.