CSS Как с помощью операций min и max сделать сравнение ===

Рейтинг: 0Ответов: 3Опубликовано: 14.02.2023

Я поставил перед собой задачу: хочу в CSS делать сравнения типа ===
У меня есть переменная percent от 0 до 1.
Я хочу создать переменную opacity, которая:

opacity = 1, если percent === 0
opacity = 0, если percent !== 0

Это правило нужно написать один выражением математическим, чтобы в CSS работало оно

Я уже научился делать вычисление модуля числа в CSS
Эту задачу нужно как-то решить с помощью функций min, max, abs (их в CSS я могу применить).
Ещё можно делать умножение, деление, складывать, вычитать.

Приложу пример кода, вот --opacity: max(var(--percent), 1); тут должно быть само вычисление

.card {
  width: 150px;
  height: 150px;
  background-color: red;
  --percent: 0;
  --opacity: max(var(--percent), 1);
  opacity: var(--opacity);
}
<div class="card"></div>

Ответы

▲ 0Принят

Мой прошлый ответ с хаком перестал работать в Chrome. Поэтому вот решение задачи с округлением на чистом CSS.

За чистое округление отвечает новая CSS функция round, которая работает во всех актуальных браузерах.

--percent: 0;
opacity: calc(1 - round(up, min(1, var(--percent)), 1));

min(1, var(--percent)) – ограничивает значение --percent, чтобы оно не превышало 1

round(up, min(1, var(--percent)), 1) - округляет значение вверх до ближайшего целого числа, аналог Math.ceil округления из JavaScript

  • Например, round(up, 0.85, 1) даст 1
  • round(up, 0, 1) даст 0
  • round(up, 1, 1) даст 1

1 - round(...) - вычитается округленное значения

Ниже привёл пример, на котором можно проверить работу этого CSS

const inputSlider = document.querySelector(".input-slider");
const card = document.querySelector(".card");
const outputPercent = document.querySelector('.output__percent');
const outputOpacity = document.querySelector('.output__opacity');

inputSlider.addEventListener("input", () => {
  const percent = inputSlider.value;
  card.style.setProperty("--percent", percent);
  renderOutputInfo();
});

renderOutputInfo();

function renderOutputInfo() {
  const percent = getComputedStyle(card).getPropertyValue("--percent").trim();
  const opacity = parseFloat(getComputedStyle(card).opacity);

  outputPercent.innerText = percent;
  outputOpacity.innerText = opacity;
}
.card {
  width: 120px;
  height: 120px;
  background-color: red;
  --percent: 0;
  opacity: calc(1 - round(up, min(1, var(--percent)), 1));
}
<div class="card"></div>
<input class="input-slider" type="range" min="0" max="1" step="0.1" value="0">
<div class="output">
  <div>
    --percent: 
    <span class="output__percent"></span>
  </div>
  <div>
    opacity:  
    <span class="output__opacity"></span>
  </div>

</div>

UPDATE: Начиная с Chrome 137 можно использовать if в CSS. Теперь решение задачи визуально становится намного понятнее. Поддержка в браузерах

const inputSlider = document.querySelector(".input-slider");
const card = document.querySelector(".card");
const outputPercent = document.querySelector('.output__percent');
const outputOpacity = document.querySelector('.output__opacity');

inputSlider.addEventListener("input", () => {
  const percent = inputSlider.value;
  card.style.setProperty("--percent", percent);
  renderOutputInfo();
});

renderOutputInfo();

function renderOutputInfo() {
  const computedStyle = getComputedStyle(card);
  const percent = computedStyle.getPropertyValue("--percent").trim();
  const opacity = parseFloat(computedStyle.opacity);

  outputPercent.innerText = percent;
  outputOpacity.innerText = opacity;
}
.card {
  width: 120px;
  height: 120px;
  background-color: red;
  --percent: 0;
  opacity: if(style(--percent: 0): 1; else: 0);
}
<div class="card"></div>
<input class="input-slider" type="range" min="0" max="1" step="0.1" value="0">
<div class="output">
  <div>
    --percent: 
    <span class="output__percent"></span>
  </div>
  <div>
    opacity:  
    <span class="output__opacity"></span>
  </div>

</div>

▲ 0

В питоне:

opacity = int(not(percent))
▲ 0

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

В статье описывалось, что можно округлить CSS переменную как ceil, если сделать так:

@property --ceil {
  syntax: '<integer>';
  initial-value: 0;
  inherits: false /* or true depending on context */
}

.my-elem {
  --ceil: calc(var(--a) + 0.5)
}

То есть нужно указать переменной, что она integer, прибавить ей 0.5 и это будет работать как ceil округление. Но по факту у меня это не работало. Хотя может это баги хрома? Я просто прибавил не 0.5, а 0.49 и у меня всё начало работать

Можно это проверить, если в этом примере в браузере изменять CSS переменную percent, всё работает.

opacity = 1, если percent === 0
opacity = 0, если percent !== 0

@property --ceil {
  syntax: '<integer>';
  initial-value: 0;
  inherits: false;
}

.card {
  width: 150px;
  height: 150px;
  background-color: red;
  --percent: 0.1;
  --ceil: calc(var(--percent) + 0.499);
  --opacity: var(--ceil);
  opacity: var(--opacity);
}
<div class="card"></div>