Как сделать эффект загнутого уголка

Оцените материал
(0 голосов)

Проблема

Стилизация одного угла элемента (обычно верхнего правого или нижнего правого) так, чтобы он выглядел загнутым, с разной степенью реализма — это дизайнерский прием, не теряющий своей популярности вот уже много лет. Сегодня в его применении нам помогают несколько решений на чистом CSS, первое из которых было опубликовано еще в 2010 году мастером работы с псевдоэлементами Николасом Галлахером. Основной путь решения — добавить два треугольника в верхнем правом углу: один для представления загнутого уголка страницы и второй — закрывающий собой угол главного элемента. Эти треугольники чаще всего создаются с помощью проверенного временем трюка с рамкой. В свое время эти решения смотрелись весьма впечатляюще, но сегодня мы понимаем, насколько они ограниченны. В некоторых ситуациях они попросту неприменимы: ‰ когда фон, находящийся позади нашего элемента, не залит сплошным цветом, а оформлен с использованием узора, текстуры, фотографии, градиента или фонового изображения любого другого типа; ‰ когда мы хотим загнуть уголок под другим углом, отличным от 45°, или же добавить легкое вращение.

В нескольких ранних версиях дизаqна веб-саqта http://css-tricks.com загнутые уголки исgользовались для оформления верхнего правого угла полей, содержащих отдельные статьи сайта
Существует ли более гибкое решение для создания загнутых уголков с помощью CSS, которое не буксует в подобных случаях?

Решение для угла 45°

Для начала создадим элемент со скошенным верхним правым углом, воспользовавшись для этого решением на основе градиента из секрета «Срезанные углы». Следующий код определяет скошенный угол размером  1em , а графическое представление того, что должно получиться, вы видите на рисунке:


background: #58a; /* Резервное решение */
background:
linear-gradient(-135deg, transparent 2em, #58a 0);
Дело наполовину сделано: все, что нам осталось, — это добавить чуть более темный треугольник, представляющий загнутый уголок страницы. Мы сделаем это с помощью еще одного градиента, а затем подгоним его размеры под наши требования с помощью  background-size и поместим в верхний правый угол. Для создания треугольника нам нужен расположенный под углом линейный градиент с двумя границами перехода цвета, встречающимися в середине:
background: linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em;
Как выглядит результат, когда присутствует только этот фон, вы видите на рисунке. На последнем шаге мы должны объединить эти два фрагмента кода, и на этом можно будет закончить, так? Давайте попробуем сделать это, убедившись, что треугольник, представляющий загнутый уголок, находится поверх градиента, создающего срезанный угол:
background: #58a; /* Резервное решение */
background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-135deg, transparent 2em, #58a 0);
Как подтверждает рисунок, результат не совсем такой, как ожидалось. Почему же размер не совпадает?


Ведь высота обоих градиентов равна  2em! Причина заключается в том, что размер угла, равный  2em , в случае второго градиента относится к позиции границы перехода цвета и, следовательно, отмеряется по градиентной линии, то есть по диагонали. С другой стороны,  2em для  background-size — это ширина и высота фоновой плитки, которые измеряются соответственно по горизонтали и по вертикали. Для того чтобы совместить эти два градиента, необходимо сделать одно из следующего, в зависимости от того, какой размер вы хотите сохранить: ‰ чтобы диагональ все так же была равна  2em , мы можем умножить  background-size на  2; ‰ чтобы сохранить ширину и высоту, равные  2em, можно разделить позицию границы перехода цвета нашего градиента для срезанного угла на  2. Так как  background-size повторяется дважды, а большинство других измерений в CSS делается не по диагонали, второй вариант обычно предпочтительнее. Позиция границы перехода цвета примет значение  что мы округлим до  1.5em :
background: #58a; /* Резервное решение */
background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-135deg, transparent 1.5em, #58a 0);
Как видно на рисунке  это наконец-то позволяет получить приятный глазу, гибкий и минималистичный загнутый уголок.


ПОПРОБУЙТЕ САМИ!
http://play.csssecrets.io/folded-corner

Решение для других углов

В реальности уголки страниц редко загибаются под углом 45°. Если нам требуется нечто более реалистичное, то мы могли бы попробовать указать другое значение угла, например  -150deg для угла 30°. Но это всего лишь изменит угол наклона срезанного угла, а треугольник, представляющий загнутую часть страницы, останется на своем месте, полностью исказив эффект. Однако скорректировать размеры этого треугольника не так просто, как может показаться.

Его размер определяется не углом, а шириной и высотой. Как же нам понять, какую ширину и высоту указать для нужного эффекта? Что ж, пришло время — о нет! — тригонометрии! В настоящее время код выглядит так:

background: #58a; /* Резервное решение */
background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-150deg, transparent 1.5em, #58a 0);
Убедитесь, что ширина забивки  по меньшей  мере равна величине угла, иначе текст будет наползать на угол (ведь это всего лишь фон), разрушая иллюзию загнутого уголка страницы.
Как показано на рисунке, по сути, нам нужно вычислить длину гипотенузы прямоугольного треугольника с углами 30, 60 и 90 градусов, при условии, что нам известна длина одного из катетов.


Тригонометрический круг  напоминает, что если нам известны углы и длина одной из сторон прямоугольного треугольника, то мы можем вычислить длины остальных двух сторон, используя синусы, косинусы и теорему Пифагора. Из курса математики (или сверившись с калькулятором) мы знаем, что cos30 = √3/2, а sin 30 = 1/2. Также тригонометрический круг подсказывает, что в нашем случае sin 30 = 1.5/x, a cos 30=1.5/y.
 Следовательно:


Синусы и косинусы gомогают вычислять длины катетов gрямоугольных треугольников, когда известны значения углов и длина гиgотенузы

Теперь мы можем с помощью теоремы Пифагора вычислить значение  z:

А теперь соответствующим образом изменим размер треугольника:
background: #58a; /* Резервное решение */
background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 3em 1.73em, linear-gradient(-150deg, transparent 1.5em, #58a 0);
Сейчас угол выглядит как на рисунке.

Вы видите, что край треугольника совпадает со срезанным углом, но результат выглядит еще менее реалистичным! Хотя конкретная причина становится понятна не сразу, мы в своей жизни видели достаточно загнутых уголков и мгновенно понимаем, что что-то здесь не так. Помочь своему сознанию разобраться в происходящем можно, попробовав загнуть уголок настоящего листа бумаги примерно под таким же углом. Вы быстро поймете, что не существует способа загнуть его так, чтобы он хотя бы приблизительно напоминал показанное на рисунке выше. Как доказывает настоящий загнутый уголок из реальной жизни, например показанный на рисунке ниже, нужный нам треугольник должен быть слегка повернут и обладать теми же габаритными размерами, что и треугольник, «отрезанный» от угла элемента.


Поскольку поворачивать фоны мы не можем, настало время применить эффект к псевдоэлементу:
.note {
position: relative;
background: #58a; /* Резервное решение */
background:
linear-gradient(-150deg,
transparent 1.5em, #58a 0);
}
.note::before {
content: '';
position: absolute;
top: 0; right: 0;
background: linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.4) 0)
100% 0 no-repeat;
width: 3em;
height: 1.73em;
}
Пока что мы всего лишь воссоздали эффект, показанный на рис, с использованием псевдоэлементов. Следующим шагом будет изменение ориентации существующего треугольника путем замены  width на  height и наоборот, чтобы он зеркально отражал срезанный угол, а не дополнял его. Затем мы повернем его на 30° ((90° – 30°) – 30°) против часовой стрелки, для того чтобы его гипотенуза была параллельна нашему срезанному углу:
.note::before {
content: '';
position: absolute;
top: 0; right: 0;
background: linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.4) 0)
100% 0 no-repeat;
width: 1.73em;
height: 3em;
transform: rotate(-30deg);
}
Как выглядит наша записка после этих изменений, вы видите на рисунке.

Мы уже почти достигли желаемого эффекта, осталось лишь сдвинуть треугольник, для того чтобы гипотенузы двух треугольников (темного и представляющего срезанный угол) совпали. Судя по тому, как обстоят дела сейчас, нам нужно сдвинуть треугольник и по горизонтали, и по вертикали, и понять, какие именно действия необходимо произвести, не так-то просто. Упростить себе задачу можно, установив для свойства  transform-origin значение  bottom right , чтобы нижний правый угол треугольника стал центром вращения и, таким образом, был зафиксирован на одном месте:
.note::before {
/* [Остальные определения стилей] */
transform: rotate(-30deg);
transform-origin: bottom right;
}
Как видно на рисунке, теперь нам осталось только сдвинуть треугольник вертикально вверх. Определить точную величину сдвига нам снова поможет геометрия. Схема на рисунке помогает увидеть, что требуемое вертикальное смещение для нашего треугольника равно  x-y=3-√3=1,267949152 что можно округлить до  1.3em :
.note::before {
/* [Остальные определения стилей] */
transform: translateY(-1.3em) rotate(-30deg);
transform-origin: bottom right;
}
Пример визуализации на рисунке подтверждает, что мы наконец добились желаемого эффекта.

Уф-ф-ф, это было нелегко! Кроме того, поскольку теперь наш треугольник генерируется с помощью псевдоэлементов, мы можем сделать его еще более реалистичным, добавив скругленные углы (настоящие) градиенты и тени  box-shadow! Финальная версия кода выглядит так:
.note {
position: relative;
background: #58a; /* Fallback */
background:
linear-gradient(-150deg,
transparent 1.5em, #58a 0);
border-radius: .5em;
}
.note::before {
content: '';
position: absolute;
top: 0; right: 0;
background: linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.2) 0, rgba(0,0,0,.4))
100% 0 no-repeat;
width: 1.73em;
height: 3em;
transform: translateY(-1.3em) rotate(-30deg);
transform-origin: bottom right;
border-bottom-left-radius: inherit;
box-shadow: -.2em .2em .3em -.1em rgba(0,0,0,.15);
}
Насладиться плодами нашего труда можно, взглянув на рисунок.


ПОПРОБУЙТЕ САМИ!

http://play.csssecrets.io/folded-corner-realistic
Эффект смотрится замечательно, но насколько он соответствует принципам DRY? Давайте подумаем, какие правки и вариации могут часто требоваться в дизайнах, использующих данных эффект:
‰ достаточно только одной правки для изменения габаритных размеров элемента и других длин (забивки и т. п.); ‰ достаточно только двух правок (одной, если не брать в расчет резервное решение) для изменения цвета фона; ‰ необходимо четыре правки и несколько нетри
виальных вычислений, чтобы изменить размер загнутого уголка; ‰ необходимо пять правок и несколько еще менее тривиальных вычислений, чтобы изменить угол, под которым загнут уголок страницы. Два последних пункта никуда не годятся. Возможно, настало время прибегнуть к помощи препроцессорной примеси:
SCSS
@mixin folded-corner($background, $size,$angle: 30deg) {
position: relative;
background: $background; /* Резервное решение */
background: linear-gradient($angle - 180deg,transparent $size, $background 0);
border-radius: .5em;
$x: $size / sin($angle);
$y: $size / cos($angle);
&::before {
content: '';
position: absolute;
top: 0; right: 0;
background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.2) 0, rgba(0,0,0,.4)) 100% 0 no-repeat;
width: $y; height: $x;
transform: translateY($y - $x)
rotate(2*$angle - 90deg);
transform-origin: bottom right;
border-bottom-left-radius: inherit;
box-shadow: -.2em .2em .3em -.1em rgba(0,0,0,.2);
}
}
/* Использовать как... */
.note {
@include folded-corner(#58a, 2em, 40deg);
}

Убедитесь, что трансформация translateY() определена перед вращением - в противном случае наш треугольник будет двигаться относительно своего угла 30°,так как каждая трансформация также преобразует всю систему координат элемента, а не только сам элемент как таковой!
ПОПРОБУЙТЕ САМИ!

http://play.csssecrets.io/folded-corner-mixin

Десерт на сегодня – видео о прикольном драндулете, которому не страшны любые преграды

Прочитано 307 раз Последнее изменение Суббота, 25 марта 2017 14:39
Другие материалы в этой категории:
Понравилась запись? Подпишитесь на обновления по почте:

TemplateMonster

Поиск по сайту

Связной трэвел

tezeks

Google+