Минус: расчетное значение

У меня есть следующий кусок меньше:

@image-ui-wave-width: 28px;

[...]
.wave {
    &.saw {
        background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height;
    }
    &.triangle {
        background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height;
    }
}
[...]

Теперь, как я могу добавить правило, согласно которому, если какой-либо из этих элементов .wave также имеет класс .selected, значение x элемента background position должно остаться прежним, а значение y должно быть удвоено?


person pistacchio    schedule 07.10.2015    source источник


Ответы (2)


Вариант 1: (имеет лучшую поддержку браузера)

Less не может получить значение из ранее определенного свойства и выполнить над ним какие-либо математические операции. Из-за этого нам приходится вручную вычислять и присваивать значение свойству. Поскольку вы уже используете переменные, изменение кода должно быть действительно простым (см. ниже):

@image-ui-wave-width: 28px;
@image-ui-tab-height: 28px;
.wave {
  &.saw {
    background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height;
    &.selected{
      background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height * 2;
    }
  }
  &.triangle {
    background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height;
    &.selected{
      background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height * 2;
    }        
  }
}

Его можно еще больше сжать, используя циклы и переменную @index (если значение X увеличивается на один и тот же коэффициент для каждого элемента).

Ниже приведена реализация того, как это будет работать. Как видите, все 4 элемента div имеют градиентное фоновое изображение, где первые 28 пикселей заняты одним цветом, а остальные 28 пикселей — остальными.

Для тех, у кого нет выбранного класса, отображается второй цвет из градиента (поскольку позиция Y равна -28 пикселей), а для тех, у кого есть выбранный класс, отображается первый цвет из градиента (поскольку позиция Y составляет -56 пикселей и градиенты на по умолчанию повторяются).

.wave.saw {
  background-position: -56px -28px;
}
.wave.saw.selected {
  background-position: -56px -56px;
}
.wave.triangle {
  background-position: -84px -28px;
}
.wave.triangle.selected {
  background-position: -84px -56px;
}
.wave.saw {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, red 50%, green 50%);
  background-size: 56px 56px;
}
.wave.triangle {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, yellow 50%, orange 50%);
  background-size: 56px 56px;
}
div {
  margin-bottom: 20px;
}
<div class='wave saw'></div>

<div class='wave saw selected'></div>

<hr>

<div class='wave triangle'></div>

<div class='wave triangle selected'></div>


Вариант 2. (Более плохая поддержка браузеров — доступна диаграмма совместимости браузеров. здесь)

Еще одна вещь, которую мы можем сделать сейчас со Стандартом Фона и Границ Уровня 4, — это разделить все background-position на части x и y, чтобы позицию x не пришлось повторять. Первоначально это было удалено из спецификации CSS3, но, похоже, теперь доступно, как упоминалось здесь.

@image-ui-wave-width: 28px;
@image-ui-tab-height: 28px;

.wave {
    &.saw {
        background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height;
        &.selected{
            background-position-y:  -@image-ui-tab-height * 2;
        }
    }
    &.triangle {
        background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height;
        &.selected{
            background-position-y: -@image-ui-tab-height * 2;
        }        
    }
}

Ниже приведена реализация этого подхода, в которой мы переопределяем только значение background-position-y более конкретным селектором:

.wave.saw {
  background-position: -56px -28px;
}
.wave.saw.selected {
  background-position-y: -56px;
}
.wave.triangle {
  background-position: -84px -28px;
}
.wave.triangle.selected {
  background-position-y: -56px;
}
.wave.saw {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, red 50%, green 50%);
  background-size: 56px 56px;
}
.wave.triangle {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, yellow 50%, orange 50%);
  background-size: 56px 56px;
}
div {
  margin-bottom: 20px;
}
<div class='wave saw'></div>

<div class='wave saw selected'></div>

<hr>

<div class='wave triangle'></div>

<div class='wave triangle selected'></div>

person Harry    schedule 07.10.2015
comment
Похоже, что Firefox - единственный крупный браузер, который не поддерживает это? - person Persijn; 07.10.2015
comment
Да @Persijn, я попробовал это в Chrome, и, кажется, он работает даже в более старых версиях (v38). - person Harry; 07.10.2015
comment
давно рекомендовали в css3, но получили отказ. Предполагается, что он был отклонен, поэтому css3 больше не задерживается. - person Persijn; 07.10.2015

Нельзя ли решить эту проблему добавлением еще одного класса (.selected) в селектор .wave?

.wave {
    [yourcode]
}
.wave.selected {
    &.saw {
        background-position: -@image-ui-tag-height * 2 -@image-ui-tab-height * 2;
    }
    &.triangle {
     background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height * 2;
    }
}

Примечание
.wave.selected должен идти после селектора .wave, поскольку последний переопределяет свойства css.

person Persijn    schedule 07.10.2015
comment
Shure, но идея заключалась в том, чтобы избежать повторного написания позиции x - person pistacchio; 07.10.2015