Математика CSS трансформаций: ромб

CSS-свойство transform предоставляет front end разработчикам возможность изменять геометрию элементов при помощи методов: matrix, rotate, scale, skew, translate и т.д.. Но даже обладая столь разнообразными инструментами, попытка превратить прямоугольную форму в ромб может оказаться весьма нетривиальной. Давайте попробуем разобраться, в чем кроется проблема?


Прежде всего вспомним, что такое ромб? Это параллелограмм, все стороны которого равны, а углы непрямые. Отсюда вытекает 2 условия:

  • стороны должны быть равны;
  • углы должны быть непрямые.

Skew

Свойства skew, skewX, skewY помогут избавиться от прямоты углов, наклоняя элемент. Однако в их работе не все так просто.

Наклон выполняется на заданный угол, относительно начала координат (верхнего левого угла экрана). Форма записи skew(x, y) позволяет задать наклон сразу по двум осям, но в текущей задаче это не имеет смысла. Я рекомендую вам не использовать отрицательное значение угла, ибо это внесет путаницу в дальнейшие вычисления.

Важно понимать, что при наклоне элемента по одной из осей координат, стороны на перпендикулярной оси искажаются, становятся длиннее. А следовательно нарушается условие задачи: “стороны должны быть равны”.

Выравниваем стороны

Здесь нам придется вспомнить тригонометрию. Для корректировки длины искаженных сторон, нам придется менять высоту элемента, если наклон выполнялся по оси X, или ширину, если наклон выполнялся по оси Y.

В обоих случаях нас интересует катет с прилежащим углом, длину которого можно вычислить по формуле x = c * cos(a), где c — длина неискаженной стороны, а a — угол наклона.

К сожалению, ванильный CSS не может в математику, а значит нам придется прибегнуть к помощи препроцессоров: Sass, Stylus, LESS, … Вот набор необходимых функций для Sass, найденных мной на просторах Codepen.io:

Rotate

Итак, нам таки удалось получить равносторонний параллелограмм с непрямыми углами, иными словами ромб. Но он как будто бы устал и прилег набок (приуныл), а у кого-то сползает по стенке. Надо бы его взбодрить, и в этом нам поможет метод rotate свойства transform. Проблема лишь в том, что мы не знаем, на какой угол требуется повернуть фигуру, чтобы ее оси совпали с осями координат…

Продолжим вспоминать школьную программу.

Мы имеем равнобедренный треугольник, в котором нам известна длина боковой стороны и вершинный угол (90° - угол наклона). Найти угол при основании, а именно он нам и нужен, достаточно просто:

x = (180° - b) / 2 = (180° - 90° + a) / 2 = 45° + 0.5 * a

Вот пример результата и его возможного реального применения

В случае наклона по оси Y угол поворота составляет

x = 45° - 0.5 * a

P.S.

Кстати, как оказывается, порядок следования функций в свойстве transform также очень важен, т.к. все последующие методы учитывают результат выполнения предыдущих, что в случае халатного обращения может привести к нежелательным результатам. И “последующие” в данном контексте стоит понимать как те, что ближе к началу записи, ибо они выполнятся в последнюю очередь.