Frontender Magazine

Погружение в CSS градиенты

Я не могла себе даже представить, насколько мощным инструментом являются градиенты CSS до того, как в конце 2011 года обнаружила галерею паттернов CSS3 созданную Леа Веру (Lea Verou). Возможность создавать различные фигуры, используя градиенты, стала отправной точкой для моих собственных экспериментов с CSS.

Разноцветный круг

Недавно, просматривая демо на CodePen, я наткнулась на разноцветное колесо, построенное на CSS3 и меня посетила мысль: «А ведь для создания такого колеса можно использовать один элемент DOM и градиенты». Сказано — сделано, результат можно увидеть здесь. Давайте я объясню, как мне это удалось.

Разделим на части

Разделяем колесо (можете представлять его себе в виде пирога) по горизонтали на две равных части, затем каждую половину ещё на 5 частей. Таким образом, мы получаем 10 секторов. Центральный угол каждого сектора составляет 360°/10 = 36°.

Ниже можно увидеть, как разные уровни фона накладываются друг на друга. В него добавлена кнопка «Пауза», чтобы избежать проблем с производительностью, которые могут возникнуть из-за повторяющейся анимации.

И в примере, и в демо нас интересует одно:

background:
linear-gradient(36deg, #272b66 42.34%, transparent 42.34%),
linear-gradient(72deg, #2d559f 75.48%, transparent 75.48%),
linear-gradient(-36deg, #9ac147 42.34%, transparent 42.34%) 100% 0,
linear-gradient(-72deg, #639b47 75.48%, transparent 75.48%) 100% 0,
linear-gradient(36deg, transparent 57.66%, #e1e23b 57.66%) 100% 100%,
linear-gradient(72deg, transparent 24.52%, #f7941e 24.52%) 100% 100%,
linear-gradient(-36deg, transparent 57.66%, #662a6c 57.66%) 0 100%,
linear-gradient(-72deg, transparent 24.52%, #9a1d34 24.52%) 0 100%,
#43a1cd linear-gradient(#ba3e2e, #ba3e2e) 50% 100%;
background-repeat: no-repeat;
background-size: 50% 50%;

Мы указываем девять фоновых градиентов, их позиционирование и background-color, используя сокращённый вариант записи background.

Сокращённая запись свойства background

Напомню, что отдельные уровни фона указываются по порядку: начиная с верхнего и вниз, а свойство background-color указывается последним. Для фона указывают следующие свойства:

Если свойство background-position не указано, то и background-size указывать не нужно. Кроме того, для background-origin и background-clip используются похожие значения (например, border-box или content-box), и в случаях когда для background-origin и background-clip значения совпадают, оно указывается один раз. Остальные свойства (кроме background-image) можно не указывать, в таком случае принимают значение по умолчанию.

Так как для всех девяти фоновых слоев, которые мы используем, значения свойств background-repeat и background-size одинаковые и не являются значениями по умолчанию, мы указываем их после сокращённой записи background, чтобы не писать одно и то же девять раз.

У нас ещё одна причина прописывать background-size: Safari и Firefox до 17 версии включительно не поддерживают его в сокращённой записи. Кроме того, если в качестве значения для background-image указан градиент, необходимо прописывать оба значения background-size. Если указано только одно - результат в разных браузерах будет отличаться (исключением является значение 100%, которое можно не указывать, так как оно является значением по умолчанию).

Для background-color задан светло-синий цвет (#43a1cd) и сверху накладываются девять неповторяющихся фоновых изображений (background-repeat: no-repeat), созданных с помощью CSS-градиентов. Размеры всех девяти — в два раза меньше размеров элемента (background-size: 50% 50%).

Нижний градиент — тот, который выровнен по нижней границе (100%) и отцентрирован по горизонтали (50%) — очень прост. Он является переходом от кирпично-красного до того же кирпично-красного цвета (linear-gradient(#ba3e2e, #ba3e2e)), в результате получаем квадрат, который закрашен одним цветом.

В остальных восьми слоях осуществляется переход от transparent (прозрачного) до насыщенного, не прозрачного цвета и наоборот. Четыре из них выглядят как двойной сектор с центральным углом 2*36° = 72°, но половинка каждого такого двойного сектора перекрывается другим одинарным сектором с центральным углом 36°.

Несколько слов о линейных градиентах

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

Угол градиента — это угол между вертикальной осью и линией градиента (синяя линия в демо), значение которого определяется по часовой стрелке. Это установлено новым синтаксисом, который пока не поддерживается браузерами на движке WebKit (уже поддерживается). Согласно старому синтаксису, углы измеряются по тому же принципу, что и в тригонометрической единичной окружности (против часовой стрелки, начиная с горизонтальной оси).

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

Это значит, что у нас почти всегда разные значения углов в основном синтаксисе и в синтаксисе для WebKit. Таким образом, если только мы не используем что-то вроде сервиса -prefix-free (я его использую практически всегда), тогда можно рассчитать значения углов для WebKit, имея значения углов для остальных движков, и наоборот. И, кстати, это довольно легко. Они отсчитываются в противоположные стороны, соответственно, значение угла в одном синтаксисе будет равно значению в другом, но со знаком минус. У них также разница в 90°, рассчитываем мы их так:

newSyntax = 90° — oldSyntax;
oldSyntax = 90° — newSyntax;

Примечание: если угол градиента или сторона, в которую производится отсчет, не указаны (например, linear-gradient(lime, yellow)), противоположное значение угла градиента будет 180°, а не 0°

У всех точек на перпендикуляре к линии градиента — цвет одинаковый. Перпендикуляр опущенный из вершины квадранта противоположного квадранту угла — это линия 0% (линия малинового цвета на изображении ниже), его пересечение с линией градиента — это начальная точка градиента (назовем ее точкой S). Перпендикуляр, опущенный из противоположной вершины (тот, который проходит через квадрант, где находится угол градиента) — это линия 100% (черная линия на изображении ниже), её пересечение с линией градиента - это конечная точка градиента (назовем её точкой E).

Градиент с линией градиента, линией 0%, линией 100%

Чтобы рассчитать процентное значение произвольной точки P, для начала опустим из нее перпендикуляр на линию градиента. Линия градиента и этот перпендикуляр пересекаются в точке, которую мы назовем точкой I. Теперь рассчитываем соотношение длины отрезков SI и SE; процентное значение для точки P равно этому соотношению умноженному на 100%.

Практическое применение

Теперь давайте рассмотрим как применить все это на примере с разноцветным колесом.

Сначала рассмотрим градиент, который создает сектор с углом 36°. Это квадратное изображение (см. ниже) с синим сегментом, у которого угол 36° в основании. Проведем горизонтальную и вертикальную ось через точку O, в которой пересекаются диагонали. С этой точки опустим перпендикуляр на линию, отделяющую темно-синюю часть от прозрачной. Получаем линию градиента. Как показано ниже, между вертикальной осью и линией градиента лежит угол 36°, и значит угол градиента составляет 36°.

Применяем теорию для создания первого сектора

Теперь опустим перпендикуляр из вершины квадрата в квадранте, противоположном тому, в котором расположен угол градиента. Это линия 0%. Затем опустим перпендикуляр из вершины квадрата в квадранте, где расположен угол градиента (первый квадрант) — это линия 100%.

Пересечение диагоналей квадрата разделяет каждую из них на две равные части, значит AO и BO равны. Углы BOE и AOS равны, так как они являются вертикальными углами. Более того, треугольники BOE и AOS прямоугольные. Эти три утверждения доказывают, что треугольники равные. Из этого, в свою очередь, следует, что SO и EO равны, а значит, длина отрезка SE равна длине EO умноженной на два и длине SO умноженной на два.

Прямоугольный треугольник и расчёт синуса и косинуса

Примечание: перед тем как двигаться дальше, вспомним несколько тригонометрических понятий. Самая длинная сторона прямоугольного треугольника лежит напротив прямого угла и называется гипотенузой. Две другие стороны (которые формируют прямой угол) называются катетами прямоугольного треугольника. Синус острого угла прямоугольного треугольника — равен соотношению катета, противоположного этому углу, и гипотенузы. Косинус того же угла — равен соотношению прилежащего катета и гипотенузы.

Рассчитать длину отрезка EO в прямоугольном треугольнике BOE очень просто. Длину стороны квадрата примем за a, тогда длина половины диагонали BO равна a*sqrt(2)/2. Угол BOE равен разнице между углом BOM, который равен 45°, и углом EOM, который равен 36°. Итого угол BOE равен 9°. Поскольку BO является гипотенузой прямоугольного треугольника BOE, длина EO равна (a*sqrt(2)/2)*cos9°. Значит длина SE равна a*sqrt(2)*cos9°.

Треугольник BOE

Теперь опустим из точки A перпендикуляр на линию PI. ASID прямоугольник, значит длина SI равна длине AD. Рассмотрим прямоугольный треугольник APD. В нем сторона AP - гипотенуза с длиной a. Это значит, что длина отрезка AD равна a*sin36°. SI равен AD, значит его сторона также равна a*sin36°.

Треугольник APD

Зная длину отрезков SI и SE, мы можем рассчитать их соотношение. Оно равно sin36°/(sqrt(2)cos9°) = 0.4234*. Значит, процентное значение ограничителя цвета равняется 42.34%.

Таким образом мы получили следующее: linear-gradient(36deg, #272b66 42.34%, transparent 42.34%)

Расчёт процентных значений для остальных фоновых слоёв производится точно так же.

Автоматизация расчётов

Прочитав всё выше изложенное, вы наверное думаете, что слишком трудоемко проводить столько подсчётов. И ещё хуже, если нужно большее количество градиентов с разными углами…

Несмотря на то, что экспериментируя с цветовым колесом, я проводила все подсчёты на бумаге … я полностью c этим согласна! Именно поэтому я создала простенький инструмент, который позволяет определить процентное значение для любой точки в окне с градиентом. Просто кликните по нужной точке на градиенте и процентное значение появится в нижней части блока.

Размеры окна с градиентом можно менять, так же как и сам градиент. Поддерживается новый синтаксис для линейных градиентов, значения углов в градусах, значения to <side> и даже отсутствие указания направления градиента.

Подведем итоги

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

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Ana Tudor
Автор:
Ana Tudor
Сaйт:
http://about.me/thebabydino
Twitter:
@thebabydino
Dabblet:
thebabydino
Codepen.io:
thebabydino
Наталья Фадеева
Переводчик:
Наталья Фадеева
вКонтакте:
natatik_l
Twitter:
@very_busy_girl
GitHub:
NatalieF