Статьи

Углы наклона в Sass

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

Иллюстрация угла наклона в CSS

Есть немало способов реализовать это. Вы можете использовать в качестве фона изображения в кодировке 64, но это затрудняет настройку (цвет, угол и т. Д.).

Другим способом было бы наклонить и / или повернуть абсолютно позиционированный псевдоэлемент, но если есть одна вещь, с которой я не хочу иметь дело, это перекосное преобразование. Боже, нет.

При использовании Sass вы можете использовать библиотеку Angled Edges, которая кодирует динамически генерируемый SVG. Он работает очень хорошо, однако требует фиксированной ширины и высоты, выраженной в пикселях, что меня это беспокоит.

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

В чем идея?

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

background-image: linear-gradient($angle, $color 50%, transparent 50%); 

Это упаковано в mixin, который применяет цвет фона к контейнеру и генерирует псевдоэлемент с правильным градиентом, основанным на данном угле. Достаточно просто. Вы бы использовали это так:

 .container { @include tilted($angle: 3deg, $color: rgb(255, 255, 255)); } 

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

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

Чтобы избежать необходимости угадывать или придумывать хорошие приближения, высота псевдоэлемента вычисляется из заданного угла. Это, конечно, все сделано с небольшим количеством Sass и большим количеством геометрии. Пошли.

Вычисление высоты псевдоэлемента

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

Давайте назовем его ABC, где C — это прямой угол, B — известный угол (аргумент $angle ), и поэтому A — это C - B Как показано на этой диаграмме, мы пытаемся выяснить, что такое b .

Геометрическая диаграмма, отображающая вышеупомянутое объяснение

Чтобы сделать это, нам нужно найти значение c (линия градиента, иначе гипотенуза), которая является длиной a (нижняя сторона, 100%), деленная на синус угла AB = 5° , A будет 85 ° например).

 c = a / sin(C - B) 

Оттуда мы должны использовать теорему Пифагора:

Квадрат гипотенузы (сторона, противоположная прямому углу) равна сумме квадратов двух других сторон.

Следовательно, квадрат другой стороны равен квадрату гипотенузы минус квадрат третьей стороны. Таким образом, квадрат b равен квадрату c минус квадрат a .

 =- 

Наконец, длина b равна квадратному корню квадрата c минус квадрат a .

 b = (-) 

Вот и все. Теперь мы можем построить небольшую функцию Sass, вычисляющую высоту псевдоэлемента на основе заданного угла.

 @function get-tilted-height($angle) { $a: (100% / 1%); $A: (90deg - $angle); $c: ($a / sin($A)); $b: sqrt(pow($c, 2) - pow($a, 2)); @return (abs($b) * 1%); } 

Примечание: функции pow() , sqrt() и sin() могут исходить из Sassy-Math , Compass или из пользовательских источников .

Строим наклонный миксин

Мы сделали самое сложное, поверь мне! Последнее, что нужно сделать, это создать реальный tilted() tilted tilted() . Он принимает угол и цвет в качестве аргумента и генерирует псевдоэлемент.

 @mixin tilted($angle, $color) { $height: get-tilted-height($angle); position: relative; background-color: $color; &::before { content: ''; padding-top: $height; position: absolute; left: 0; right: 0; bottom: 100%; background-image: linear-gradient($angle, $color 50%, transparent 50%); } } 

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

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

Наконец, высота псевдоэлемента должна быть передана через padding-top (или padding-bottom в этом отношении) вместо height . Поскольку высота выражается в процентах на основе ширины родителя, мы не можем полагаться на height (так как она вычисляется из высоты родителя).

Заключительные мысли и дальше

В этой статье я выбрал простую версию миксина, которая может не обладать гибкостью и теоретически может представлять следующие проблемы:

  • Его невозможно использовать для элемента, уже использующего псевдоэлемент its ::before . Эту проблему можно решить, добавив необязательный параметр для указания псевдоэлемента, по умолчанию — before .
  • Невозможно отобразить наклонный край в нижней части контейнера как bottom: 0 в настоящее время жестко запрограммирован в ядре миксина. Это может быть решено путем предоставления дополнительной позиции миксину.

Кроме того, моя существующая версия использует математические функции на основе Sass, как это было в проекте Jekyll, не позволяя мне расширять слой Sass. Если вы используете node-sass, вы можете легко передать эти функции из JavaScript в Sass через Eyeglass или Sassport , что было бы намного лучше.

Надеюсь тебе понравилось! Если вы можете придумать что-нибудь, чтобы улучшить это, пожалуйста, не стесняйтесь поделиться в комментариях. 🙂