Как срезать углы на css

Как срезать углы на css

Проблема

Срезание углов — это не только быстрый способ достичь цели, но и популярный вариант стилизации как в печатном дизайне, так и в веб-дизайне. Чаще всего он подразумевает обрезание одного или нескольких уголков контейнера под углом 45°. В последнее время, в связи с тем, что скевоморфизм начал сдавать позиции плоскому дизайну, этот эффект пользуется особенной популярностью. Когда углы срезаются только с одной стороны и каждый из них занимает 50% высоты элемента, это создает фигуру в форме стрелки, что также часто используется в оформлении кнопок и элементов навигации типа «хлебные крошки».

как срезать угол на CSS

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

пример сайта со срезанными углами
Пример веб-сайта, где срезанный угол (нижний левый у полупрозрачного поля Find & Book) отлично вписывается в дизайн

 

Решение

Одно возможное решение предлагают нам всемогущие градиенты CSS. Предположим, что нам требуется только один срезанный угол, скажем, нижний правый. Трюк в том, чтобы воспользоваться способностью градиентов принимать направление угла (например,  45deg ) и позиции границ перехода цвета в абсолютных значениях, которые не меняются при изменении габаритных размеров элемента, которому принадлежит фон. Из вышесказанного следует, что нам будет достаточно одного линейного градиента.

Мы добавим прозрачную границу перехода цвета для создания срезанного угла и еще одну границу перехода цвета в той же позиции, но уже с цветом, соответствующим фону. Код CSS будет следующим (для угла размером  15px ):

background: #58a;
background:linear-gradient(-45deg, transparent 15px, #58a 0);

Просто, не так ли? Результат вы видите на рисунке.


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

background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0), linear-gradient(45deg, transparent 15px, #655 0);

Однако, это не работает. По умолчанию оба градиента занимают всю площадь элемента, так что они заслоняют друг друга. Мы должны уменьшить их, ограничив каждый из них половиной элемента с помощью  background-size :
background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0) right, linear-gradient(45deg, transparent 15px, #655 0) left;
background-size: 50% 100%;

Результат вы можете видеть на рисунке.

 

 

Несмотря на то что мы применили  background-size , градиенты все равно перекрывают друг друга. Причина в том, что мы забыли выключить  background-repeat,поэтому каждый из фонов повторяется дважды. Следовательно, один из фонов все так же заслоняет другой, но на этот раз за счет повторения. Новая версия кода выглядит так:
background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0) right, linear-gradient(45deg, transparent 15px, #655 0) left;
background-size: 50% 100%;
background-repeat: no-repeat;

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

 

background: #58a;
background: linear-gradient(135deg, transparent 15px, #58a 0) top left,

linear-gradient(-135deg, transparent 15px, #655 0) top right,

linear-gradient(-45deg, transparent 15px, #58a 0) bottom right,

linear-gradient(45deg, transparent 15px, #655 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;

СОВЕТ
Мы использовали разные цвета  (#58a и  #655 ) для упрощения отладки. На практике оба градиента будут одного и того же цвета.
Но проблема предыдущего кода в том, что он трудно поддается сопровождению. Он требует внести пять правок для изменения фонового цвета и четыре для изменения величины угла. Примесь, созданная с помощью препроцессора, могла бы сократить количество повторений. Вот как этот код будет выглядеть в SCSS:
SCSS
@mixin beveled-corners($bg,
$tl:0, $tr:$tl, $br:$tl, $bl:$tr) {
background: $bg;
background:
linear-gradient(135deg, transparent $tl, $bg 0)
top left,
linear-gradient(225deg, transparent $tr, $bg 0)
top right,
linear-gradient(-45deg, transparent $br, $bg 0)
bottom right,
linear-gradient(45deg, transparent $bl, $bg 0)
bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
}


Затем, когда необходимо, его можно будет вызывать, как показано далее, с 2–5 аргументами:
SCSS
@include beveled-corners(#58a, 15px, 5px);
В этом примере мы получим элемент, у которого верхний левый и нижний правый углы срезаны на  15px , а верхний правый и нижний левый — на  5px , аналогично тому, как работает  border-radius , когда мы указываем меньше четырех значений. Это возможно благодаря тому, что мы в нашей примеси SCSS также позаботились о значениях по умолчанию для аргументов, — и да, эти значения по умолчанию могут ссылаться и на другие аргументы тоже.
ПОПРОБУЙТЕ САМИ!
http://play.csssecrets.io/bevel-corners-gradients

Читайте также  Как сделать гибкие эллипсы

Искривленные срезанные углы

искривленные срезанные углы пример дизайна
Превосходный пример использования искривленных срезанных углов на веб-сайте http://g2geogeske.com; дизайнер сделал их центральным элементом оформления: они присутствуют в навигации, в содержимом и даже в нижнем колонтитуле.
Вариация метода с градиентами позволяет создавать искривленные срезанные углы — эффект, который многие называют «внутренним радиусом рамки», так как он выглядит словно инвертированная версия скругленных углов. Единственное отличие заключается в использовании радиальных градиентов вместо линейных:
background: #58a;
background: radial-gradient(circle at top left, transparent 15px, #58a 0) top left,

radial-gradient(circle at top right, transparent 15px, #58a 0) top right,

radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right,

radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;

 

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

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

Решение со строковым SVG и border-image

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

Аналогично, для изменения фонового цвета также необходимы четыре правки, а если учитывать резервное решение, то все пять; анимировать изменение величины срезанного угла невероятно сложно, а в некоторых браузерах вообще невозможно. К счастью, в зависимости от желаемого результата мы можем воспользоваться еще парой методов. Один из них подразумевает объединение  border-image со строковым SVG-кодом, в котором и генерируются углы.

Зная, как работает border-image (если вам необходимо освежить эти знания в памяти, подсказку вы найдете здесь), можете ли вы уже представить, как должен выглядеть требуемый SVG-код?

Так как габаритные размеры для нас неважны ( border-image позаботится о масштабировании, а SVG-рисунки идеально масштабируются вне зависимости от габаритов — будь благословенна векторная графика!), все размеры можно приравнять к единице, для того чтобы оперировать более удобными и короткими значениями. Величина срезанного угла будет равна единице, и прямые стороны также будут равны единице. Результат (увеличенный для удобства восприятия). Код, необходимый для этого, показан далее:
border: 15px solid transparent;
border-image: 1 url(‘data:image/svg+xml,\
<svg xmlns=»http://www.w3.org/2000/svg»
width=»3″ height=»3″ fill=»%2358a»>\
<polygon points=»0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2″/>\
</svg>’);


Обратите внимание, что размер шага нарезки равен  1 . Это не означает 1 пиксел; фактический размер определяется системой координат SVG-файла (потому-то у нас и отсутствуют единицы измерения). Если бы мы использовали проценты, то нам пришлось бы аппроксимировать 1/3 изображения дробным значением, вроде  33.34% . Прибегать к приблизительным значениям всегда рискованно, так как в разных браузерах значения могут округляться с разной степенью точности. А придерживаясь единиц изменения системы координат SVG-файла, мы избавляем себя от головной боли, сопутствующей всем этим округлениям.

Читайте также  Как сделать ромб на css

 

Как вы видите, срезанные углы присутствуют, но фона нет. Эту проблему можно решить двумя способами: либо определить фон, либо добавить ключевое слово  fill к объявлению  border-image , чтобы центральный элемент нарезки не отбрасывался. В нашем примере мы лучше определим отдельный фон, так как это определение будет также служить обходным путем для браузеров, не поддерживающих данное решение.

Помимо этого, вы, вероятно, заметили, что теперь срезанные углы меньше, чем при использовании предыдущей техники, и это может поставить в тупик. Мы ведь задали ширину рамки, равную  15px! Причина в том, что в решении с градиентом эти 15 пикселов отсчитывались вдоль градиентной линии, которая перпендикулярна направлению градиента. Однако ширина рамки измеряется не по диагонали, а по горизонтали/вертикали.

Чувствуете, к чему я веду? Да-да, снова вездесущая теорема Пифагора, которую мы активно использовали здесь. Схема на рисунке должна прояснить ситуацию.

 

Короче говоря, для того, чтобы достичь того же визуального результата, нам необходима ширина рамки, в 2 раз превышающая размер, который мы бы использовали в методе с градиентом. В данном случае это будет пиксела, что разумнее всего аппроксимировать до  20px , если только перед нами не стоит задача как можно точнее приблизить размер диагонали к заветным  15px :
border: 20px solid transparent;
border-image: 1 url(‘data:image/svg+xml,\
<svg xmlns=»http://www.w3.org/2000/svg»
width=»3″ height=»3″ fill=»%2358a»>\
<polygon points=»0,1 1,0 2,0 3,1 3,2 2,3 1,3
0,2″/>\
</svg>’);
background: #58a;
Однако, как можно видеть, результат не совсем тот, которого мы ожидали.

 

Куда делись наши кропотливо срезанные углы? Не бойся, юный падаван, углы все так же на месте. Вы сразу же поймете, что произошло, если установите другой фоновый цвет, например  #655.
Как демонстрирует рисунок ниже, причина, почему наши углы исчезли, кроется в фоне: тот фон, который мы выше определили, попросту заслоняет их. Все, что нам нужно сделать для устранения этого неудобства, — с помощью  background-clip запретить фону подлезать под область рамки:
border: 20px solid transparent;
border-image: 1 url(‘data:image/svg+xml,\
<svg xmlns=»http://www.w3.org/2000/svg»\
width=»3″ height=»3″ fill=»%2358a»>\
<polygon points=»0,1 1,0 2,0 3,1 3,2 2,3 1,3
0,2″/>\
</svg>’);
background: #58a;
background-clip: padding-box;


Теперь проблема решена, и наше поле выглядит точно так же, как раньше. К тому же на этот раз мы можем с легкостью изменить размер углов, внеся всего лишь одну правку: просто скорректируем ширину рамки. Мы можем даже анимировать этот эффект, потому что  border-width поддерживает анимацию!

А для смены фона требуется теперь две правки вместо пяти. Кроме того, так как наш фон не зависит от эффекта, накладываемого на углы, мы можем определить для него градиент или любой другой узор, при условии, что по краям цвет все так же будет равен  #58a .

Например,  мы используем радиальный градиент от цвета  hsla(0,0%,100%,.2) до  transparent. Осталось решить лишь одну небольшую проблему. Если  border-image не поддерживается, то резервное решение не ограничится отсутствием срезанных углов. Из-за того что фон обрезан, пространство между краем поля и его содержимым уменьшится. Для того чтобы исправить это, необходимо для рамки определить тот же цвет, который мы используем для фона:
border: 20px solid #58a;
border-image: 1 url(‘data:image/svg+xml,\
<svg xmlns=»http://www.w3.org/2000/svg»\
width=»3″ height=»3″ fill=»%2358a»>\
<polygon points=»0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2″/>\
</svg>’);
background: #58a;
background-clip: padding-box;

В браузерах, где наше определение  border-image поддерживается, этот цвет будет проигнорирован, но там, где  border-image не работает, дополнительный цвет рамки обеспечит более изящное резервное решение. Единственный его недостаток — увеличение количества правок, необходимых для изменения фонового цвета, до трех.
ПОПРОБУЙТЕ САМИ!
http://play.csssecrets.io/bevel-corners

Читайте также  Как создать параллелограмм на CSS

Решение с обтравочным контуром

Хотя решение с  border-image очень компактное и хорошо соответствует принципам DRY, оно накладывает определенные ограничения. Например, наш фон все так же должен быть либо целиком, либо хотя бы вдоль кромок заполнен сплошным цветом.

А что, если мы хотим использовать другой тип фона, например текстуру, узор или линейный градиент? Существует другой способ, не имеющий подобных ограничений, хотя, конечно, определенные ограничения его применения есть.

Помните свойство  clip-path из секрета «Как сделать ромб»? Обтравочные контуры CSS обладают поразительным свойством: они позволяют смешивать процентные значения (с помощью которых мы указываем габаритные размеры элемента) с абсолютными, обеспечивая невероятную гибкость. Например, код обтравочного контура, обрезающего элемент до формы прямоугольника со скошенными углами размером  20px (если измерять по горизонтали), выглядит так:
background: #58a;
clip-path: polygon(
20px 0, calc(100% — 20px) 0, 100% 20px,
100% calc(100% — 20px), calc(100% — 20px) 100%,
20px 100%, 0 calc(100% — 20px), 0 20px);
Несмотря на краткость, в этом фрагменте кода принципы DRY не соблюдены, и это становится одной из самых больших проблем, если вы не используете препроцессор. В действительности этот код — лучшая иллюстрация принципа WET из всех решений на чистом CSS, представленных в этой книге, ведь для изменения размера угла здесь требуется внести целых восемь (!) правок.

С другой стороны, фон можно поменять с помощью только одной правки, так что у нас есть хотя бы это. Одно из преимуществ данного подхода — то, что мы можем использовать абсолютно любой фон или даже обрезать подменные элементы, такие как изображения. На рисунке показано изображение, стилизованное с использованием срезанных углов. Ни один из предыдущих методов не позволяет добиться такого эффекта. Помимо этого, свойство  clip-path поддерживает анимацию, и мы можем анимировать не только изменение размера угла, но и переходымежду разными фигурами.

 

Все, что для этого нужно, — использовать другой обтравочный контур. Помимо многословности и ограниченной поддержки браузерами, недостатком этого решения является то, что, если мы не позаботимся о достаточно широкой забивке, текст также будет обрезан, так как при обрезке элемента его составляющие никак не учитываются. В противоположность этому метод с градиентом позволяет тексту просто выходить за границы обрезанных углов (ведь они всего лишь часть фона), а метод с  border-image работает так же, как обычные рамки, — переносит текст на новую строку.

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

БУДУЩЕЕ СРЕЗАННЫЕ УГЛЫ
В будущем, для того чтобы воплотить эффект срезанных углов, нам не придется прибегать к помощи градиентов CSS, обрезки или SVG. Новое свойство corner-shape, входящее в состав CSS Backgrounds & Borders Level 4 , спасет нас от этой головной боли.Оно будет использоваться для создания эффекта срезанных по разной форме углов в сочетании со свойством border-radius, которое необходимо для определения величины обрезки. Например, для описания срезанных углов размером 15px по всем сторонам изображения достаточно такого простого кода:border-radius: 15px;
corner-shape: bevel;

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Поделиться
(Visited 12 547 times, 1 visits today)

Об авторе

admin administrator

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: