Перейти к содержанию

Арифметические операции

В этой статье мы с Вами рассмотрим еще одну удивительную возможность LESS, позволяющую производить арифметические операции c числами, цветами и даже с переменными! Мы научимся применять такие операции как сложение, вычитание, умножение и деление.

До того как вы перейдете к прочтению статьи, хочу Вас познакомить с нативной функцией calc(), введенной в CSS 3, она позволит частично решать задачи с арифметическими операциями и, возможно, именно она подойдет для решения Вашей задачи. На текущий момент функция calc() поддерживается всеми современными браузерами и даже Internet Explorer 9, ознакомьтесь с ней при случае.

Операции с числами

Рекомендую Вам явно указывать единицы измерения над которыми вы производите математические операции, это сделает Ваш код более прозрачным и позволит Вам каждый раз получать тот результат, который вы ожидаете. Одним из важных моментов при осуществлении математических операций является понимание работы компилятора при их вычислении.

Давайте для начала рассмотрим очевидные на мой взгляд примеры, а затем перейдем к более сложным:

/* инициализируем переменные */
@plus: 2 + 1; // производим операцию сложения
@minus: 2 - 1; // производим операцию вычитания
@multiplication: 2 * 1; // производим операцию умножения
@division: 2 / 1; // производим операцию деления

.plus {
  line-height: @plus; // используем переменную в качестве значения свойства
}
.minus {
  line-height: @minus; // используем переменную в качестве значения свойства
}
.multiplication {
  line-height: @multiplication; // используем переменную в качестве значения свойства
}
.division {
  line-height: @division; // используем переменную в качестве значения свойства
}

В этом примере мы инициализировали четыре переменные, которые использовали в качестве значений для свойств line-height, определяющих междустрочный интервал. Во время компиляции LESS автоматически производит вычисление значений переменных, благодаря чему внутри CSS файла мы увидим уже их вычисленные значения:

.plus {
  line-height: 3;
}
.minus {
  line-height: 1;
}
.multiplication {
  line-height: 2;
}
.division {
  line-height: 2;
}

Давайте рассмотрим еще один простой пример, но в этот раз будем использовать числа уже вместе с единицами измерения:

/* инициализируем переменные */
@plus: 4px + 1px; // производим операцию сложения
@minus: 3px - 1px; // производим операцию вычитания
@multiplication: 2px * 7; // производим операцию умножения
@division: 9px / 2; // производим операцию деления
@width: 100% / 4; // производим операцию деления

.plus {
  border-width: @plus; // используем переменную в качестве значения свойства
  width: @width; // используем переменную в качестве значения свойства
}
.minus {
  border-width: @minus; // используем переменную в качестве значения свойства
  width: @width; // используем переменную в качестве значения свойства
}
.multiplication {
  border-width: @multiplication; // используем переменную в качестве значения свойства
  width: @width; // используем переменную в качестве значения свойства
}
.division {
  border-width: @division; // используем переменную в качестве значения свойства
  width: @width; // используем переменную в качестве значения свойства
}

В этом примере мы создали четыре переменные, которые использовали в качестве значений для свойств border-width, определяющих ширину для границ элемента и одну переменную, которую использовали для всех свойств width, определяющую ширину элемента.

Допустим, наши элементы растягиваются по ширине в одной строке и нам необходимо добавить еще один элемент, в этом случае нам будет достаточно просто поменять делитель внутри переменной с четырех на пять. Согласитесь это достаточно удобно, так как LESS произведет все расчеты ширины элементов за Вас.

Результат компиляции должен быть очевиден для Вас:

.plus {
  border-width: 5px;
  width: 25%;
}
.minus {
  border-width: 2px;
  width: 25%;
}
.multiplication {
  border-width: 14px;
  width: 25%;
}
.division {
  border-width: 4.5px;
  width: 25%;
}

По аналогии с нативной CSS функцией calc() при арифметеских операциях Вы можете использовать различные конвертируемые единицы измерения:

/* инициализируем переменные */
@cm: 1cm + 10mm; // результат 2cm
@cm2: 1 - 3cm - 4mm; // результат -2.4 cm
@inch: 3in - 96px; // результат 2in
@rad: 180deg + 200grad; // результат 360deg
@deg: 90deg + 1turn; // результат 450deg

В этом примере мы создали следующие пять переменных:

  • В первой переменной мы прибавляем 1 сантиметр к 10 миллиметрам. Если вы не пропускали второй класс школьной программы, то вы должны знать, что в одном сантиметре содержится десять миллиметров, значение переменной будет соответствовать двум сантиметрам.
  • Прошу Вас внимательно отнестись к примеру во второй переменной. Важным моментом здесь является то, что при компиляции используется самый левый явно указанный тип единиц измерения. Самый левый явно указанный тип в этой переменной это сантиметры и вычисление будет производиться именно в этих единицах измерения:
    • Первое действие: 1cm - 3 cm = -2 cm.
    • Второе действие: -2cm - 0.4cm = -2.4cm.
  • В третьей переменной использованы при вычислении три дюйма и 96 пикселей, звучит странно, но одному дюйму как раз соответствует 96 пикселей, что при вычислении соответствует результату в 2 дюйма. Если Вы хотите познакомиться со всеми поддерживаемыми единицами измерений, то вы можете перейти к прочтению статьи из учебника CSS - «Единицы измерения CSS, размер шрифта».
  • В четвертой переменной мы использовали такие единицы измерения как градусы (deg) и грады (grad). Оборот окружности составляет 400grad и при вычислении мы получаем, что значение переменной будет соответствовать 360 градусам (180deg + 180deg). Эти единицы измерения используются в основном при трансформации элементов, более подробную информацию об этом вы можете получить в статье учебника CSS - «Трансформация элементов. Часть 1.».
  • В пятой переменной мы использовали градусы (deg) и ключевое слово turn, которое определяет количество оборотов окружности (1turn = 360deg). В результате мы получили 450deg.

Перед тем как мы перейдем к следующим примерам, хочу обратить Ваше внимание, что в официальной документации есть такой пример (дословно):

// conversion is impossible (конвертация невозможна)
@incompatible-units: 2 + 5px - 3cm; // result is 4px

Если бы составитель документа, описывающий особенности метаязыка внимательно прочитал вышеуказанную статью учебника CSS - «Единицы измерения CSS, размер шрифта» то он был бы в курсе, что сантиметры могут быть конвертированы в пиксели (1cm ~ 38.8 пикселей).

Шутки шутками, но корректный результат примера из официальной документации должен быть таким, не смотря, что он некорректен для браузера:

// conversion is possible (конвертация возможна)
@incompatible-units: 2 + 5px - 3cm; // result is -106.38582677px

В следующем примере мы с Вами рассмотрим некоторые нюансы компиляции и увидим как LESS преобразует единицы измерения, которые нельзя явно конвертировать:

/* инициализируем переменные */
@var1: 1px + 1; // результат 2px
@var2: 1px + 1em; // результат 2px
@var3: 1em + 1px; // результат 2em
@var4: 10px * 50%; // результат 50px
@var5: 50% * 10px; // результат 500%
@var6: 3cm * 3mm; // результат 9cm
@var7: 3cm / 3mm; // результат 1cm

Как вы уже поняли, LESS, если это возможно, при арифметических операциях преобразует единицы измерения. А что он делает если преобразование действительно невозможно? Давайте внимательно разберем наши переменные:

  • В первой переменной мы прибавляем к значению в пикселях значение без единиц измерения, в этом случае используется самый левый явно указанный тип единиц измерения, а это у нас пиксели.
  • Во второй и третьей переменной, LESS не может явно преобразовать единицы измерения em в пиксели и пиксели в em, в результате чего при вычислениях используется самый левый явно указанный тип единиц измерения (пиксели во второй переменной и em в третьей).
  • В четвертой и пятой переменной мы производим умножение значений с единицами измерения пиксели на проценты и наоборот. Как вы уже знаете при вычислениях используется самый левый явно указанный тип единиц измерения и результат должен быть для Вас очевиден.
  • При умножении, или делении необходимо знать и помнить, что LESS не производит преобразований. По этой причине в шестой и седьмой переменной LESS не производит преобразований миллиметров в сантиметры. Другими словами LESS использует при вычислении самый левый явно указанный тип единиц измерения, а у второго просто отбрасывает единицы измерения.

Операции с переменными

Если вы поняли предыдущий раздел, то понимание как происходят операции с переменными к вам придет моментально. Что такое переменная? Это просто контейнер со значением, которое участвует при вычислении. Примеров как происходят вычисления в LESS мы с Вами рассмотрели более чем достаточно, Вам лишь достаточно заменить любое из этих значений переменной и результат будет тот же, что и с использованием переменной.

Давайте закрепим наши знания и рассмотрим следующие примеры:

/* инициализируем переменные */
@a: 10px;
@b: 5px;

// производим операцию сложения переменных
@c: @a + @b; // переменная содержит значение 15px

// производим операцию вычитания переменных
@d: @a - @b; // переменная содержит значение 5px

// производим операцию умножения переменных
@e: @a * @b; // переменная содержит значение 50px

// производим операцию деления переменных
@f: @a / @b; // переменная содержит значение 2px

// производим операцию умножения переменной на процент и наоборот
@g: @b * 10%; // переменная содержит значение 50px
@h: 10% * @b; // переменная содержит значение 50%

Кроме того, вы можете контролировать порядок математических операций с использованием скобок, и даже при необходимости инвертировать значение переменной (изменение положительного значения на отрицательное, или наоборот с положительного на отрицательное):

/* инициализируем переменные */
@a: 10px;
@b: 5px;
@c: 3px;

@d: -@a; // переменная содержит значение -10px
@e: -(@a + @b); // переменная содержит значение -15px
@f: (@a + @b) * @c; // переменная содержит значение 45px

Операции с цветами

В следующем разделе статьи мы с Вами рассмотрим примеры того как производятся операции с цветами.

Операции с HEX цветами

Цвет с использованием шестнадцатеричной системы задается с использованием следующего синтаксиса:

#RRGGBB // шестнадцатиричное значение цвета

Значение, фактически содержит три шестнадцатеричных числа (RR - для красного, GG - для зеленого, BB - для синего). Значение цвета получается при смешивании трех вышеуказанных составляющих. Каждое значение (RR, GG и BB) должно находиться в диапозоне между 00 и FF. В шестнадцатиричной системе счет ведется следующим образом: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.

При проведении арифметических операций в шестнадцатиричной системе, заданная пользователем операция будет проведена отдельно для каждого цвета:

#RRGGBB операция значение

#RR операция значение // новое значение для RR
#GG операция значение // новое значение для GG
#BB операция значение // новое значение для BB

#RRGGBB // новое значение после вычисления значений для каждого цвета

Обратите внимание, что при операциях с шестнадцатиричными цветами результатом всегда будет допустимый цвет, это достигается за счет того, что если результат окажется больше FF, или меньше 00, то значение будет округлено до этих значений.

Давайте рассмотрим несколько примеров арифметических операций с шестнадцатиричными цветами:

@color1: #111111 * 2; // переменная содержит значение #222222 (11 * 2 = 22 для каждого цвета)
@color2: #444444 * 2.5; // переменная содержит значение #aaaaaa (44 * 2,5 = aa для каждого цвета)
@color3: #aaaaaa / 2; // переменная содержит значение #555555 (aa / 2 = 55 для каждого цвета)

/* допускается сокращать шестнадцатеричные числа до трех символов,
в том случае если каждое из трех двухзначных чисел содержит одинаковые символы */

@color4: #222 - #111; // переменная содержит значение #111111 (22 - 11 = 11 для каждого цвета)
@color5: #222 - #555; // переменная содержит значение #000000 (22 - 55  00 (округление) для каждого цвета)
@color6: #aaa + #999; // переменная содержит значение #ffffff (aa + 99  FF (округление) для каждого цвета)
@color7: #112233 + #111; // переменная содержит значение #223344 (11 + 11 = 22 для красного, 22 + 11 = 33 для зеленого, 33 + 11 = 44 для синего)

Операции с RGB цветами

Чтобы указать значение в системе RGB необходимо использовать следующий синтаксис:

rgb(R,G,B); // значение цвета в системе RGB

Каждый параметр определяет интенсивность цвета и может быть целым числом от 0 до 255. По аналогии с операциями с шестнадцатиричными цветами, заданная пользователем операция будет проведена отдельно для каждого цвета:

rgb(R,G,B) операция значение

R операция значение // новое значение для R
G операция значение // новое значение для G
B операция значение // новое значение для B

rgb(R,G,B) // новое значение после вычисления значений для каждого цвета

Обратите внимание, что при операциях с RGB цветами результатом всегда будет допустимый цвет, это достигается за счет того, что если результат окажется больше 255, или меньше 0, то значение будет округлено до этих значений.

Давайте рассмотрим несколько примеров арифметических операций с цветами в системе RGB:

@color8: rgb(35, 35, 35) * 2; // переменная содержит значение #464646 (rgb(70, 70, 70) --> HEX)
@color9: rgb(35, 35, 35) / 5; // переменная содержит значение #070707 (rgb(7, 7, 7) --> HEX)
@color10: rgb(150, 150, 150) + rgb(150, 150, 150); // переменная содержит значение #ffffff (округление до 255 для каждого цвета)
@color11: rgb(0, 0, 255) + #110; // переменная содержит значение #1111ff (rgb(0,0,255) --> #00F + #110)

Операции с HSL цветами

HSL это аббревиатура, которая объединяет в себе первые буквы трех следующих признаков:

  • Hue — тон.
  • Saturation — насыщенность.
  • Lightness — осветленность.

Система HSL использует следующий синтаксис:

hsl(от 0° до 360°, от 0 до 100%, от 0% до 100%);

Обратите внимание, что при проведении арифметической операции с HSL цветом только значение, определяющее осветленность участвует при этом:

hsl(h, s, l операция значение):

Давайте рассмотрим несколько примеров арифметических операций с цветами в системе HSL:

@color10: hsl(240, 100%, 20%) * 2; // переменная содержит значение  #0000cc (hsl(240, 100%, 20%) --> hsl(240, 100%, 40%) --> HEX)
@color11: hsl(240, 100%, 20%) / 2; // переменная содержит значение #000033 (hsl(240, 100%, 10%) --> HEX)
@color12: hsl(240, 100%, 20%) * 5; // переменная содержит значение #0000ff
@color13: hsl(240, 100%, 20%) * 6; // переменная содержит значение #0000ff (округление до 100)
@color14: hsl(240, 100%, 50%) + #010; // переменная содержит значение #0011ff

Операции с HSLA и RGBA цветами

В настоящее время LESS не умеет проводить операции с альфа-каналом (степень смешивания с фоном). Это означает, что альфа-канал определяется как undefined (неопределенный) и операции с цветовыми моделями RGBA и HSLA проводятся точно так же как и в цветовых моделях RGB и HSL.

@color15: rgb(35, 35, 35) * 2; // переменная содержит значение   #464646 (rgb(70, 70, 70) --> HEX)
@color16: rgba(35, 35, 35, 0.3) * 2; // переменная содержит значение  #464646 (альфа-канал не учитывается)
@color17: hsl(240, 100%, 20%) / 2; // переменная содержит значение #000033 (hsl(240, 100%, 10%)) --> HEX)
@color18: hsla(240, 100%, 20%, 0.6) / 2; // переменная содержит значение #000033 (hsla(240, 100%, 20%, undefined) --->  hsl(240, 100%, 20%) --> hsl(240, 100%, 10%) --> HEX)