Данный материал – перевод статьи https://kilianvalkhof.com/2017/design/sloped-edges-with-consistent-angle-in-css/. Мне, как начинающему forntend-разработчику, этот материал был интересен. Полагаю, эта статья будет полезна и другим начинающим или обучающимся фронтендерам.

Хедер оригинальной статьи
Хедер оригинальной статьи

Если вы посмотрите выше, то увидите, что хедер этого блога имеет наклонный край. Это одна из моих любимых особенностей нового дизайна. Техника, которую я использовал, обеспечивает постоянный угол наклона независимо от размера экрана, позволяет показывать фоновые изображения и использует только один HTML-элемент без псевдоэлементов. Вот как я это сделал.

Требования

Было несколько требований, предъявляемых к реализации:

  • Внешний вид не зависит от размера экрана.

  • Поддержка (и правильная фиксация) фоновых изображений и текста на переднем плане.

  • Работа на разных устройствах (не слишком заботясь об IE).

Если я также смогу максимально упростить HTML и CSS, то это будет бонусом, но не требованием.

Первоначальная идея

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

header {
  width:100%;
  transform:rotate(2deg);
}
Применение трансформации вращения к элементу
Применение трансформации вращения к элементу

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

header {
  width:110%;
  top:-5%;
  left:-5%;
  transform:rotate(2deg);
}
Увеличение внутреннего элемента
Увеличение внутреннего элемента

Затем добавим к странице или дополнительному элементу параметр overflow:hidden;, чтобы не возникало странных горизонтальных полос прокрутки:

body {
  overflow:hidden;
}

header {
  width:110%;
  top:-5%;
  left:-5%;
  transform:rotate(2deg);
}
Применение overflow: hidden;
Применение overflow: hidden;

Это выглядит замечательно, но что, если добавить туда текст?

Добавление текста
Добавление текста

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

body {
  overflow:hidden;
}

header {
  width:110%;
  top:-5%;
  left:-5%;
  transform:rotate(2deg);
}

header p {
  margin-left:5%;
  transform:rotate(-2deg);
}
Поворот и смещение текста
Поворот и смещение текста

До сих пор все работает нормально. Проблема начинается при переходе от фиксированной ширины к отзывчивой (responsive). Вот тот же элемент, только более широкий:

Масштабирование страницы
Масштабирование страницы

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

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

Псевдоэлемент ::after

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

  • Есть уверенность в том, что страница не будет выходить за левый или правый верхний угол.

  • Нет необходимости поворачивать содержимое в обратную сторону.

Так что давайте попробуем:

header::after {
  position:absolute;
  content: " ";
  display:block;
  left:-5%;
  bottom:-10px;
  transform:rotate(2deg);
  width:110%;
}
Добавление псевдоэлемента ::after
Добавление псевдоэлемента ::after

(полупрозрачность наложена с перекрытием, так что видно, где находятся элементы) Это работает, но нужно сместить элемент ::after так, чтобы он полностью перекрывал нижний край, и, как в примерах выше, также нужно сделать его немного шире, чтобы не было видно краев слева или справа. Я отключил overflow:hidden; и можно увидеть как располагается элемент ::after.

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

Псевдоэлемент ::after с границей

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

Использование ::after с наклонной границей
Использование ::after с наклонной границей

Выглядит хорошо, имеет гораздо лучшее сглаживание и работает, если сделать ширину тоже больше (при условии, что вы используете относительный размер для ширины границы):

Использование ::after с наклонной границей при увеличении ширины
Использование ::after с наклонной границей при увеличении ширины

Вместо границы, в другой технике, которую я видел, в качестве фонового изображения элемента ::afterиспользуется SVG с шириной и высотой в 100%, что приводит к тому же результату.

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

  • Еще один абсолютно позиционируемый элемент, который необходимо иметь в виду.

  • Трудно контролировать нужный угол и сохранять его.

  • Вы ограничены использованием сплошных фоновых цветов.

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

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

Использование Clip-Path

Если убрать трансформации и границы ::after , останется clip-path.

Clip-path не очень хорошо поддерживается, только браузеры с Webkit, Blink и Gecko поддерживают его, а для последнего необходим SVG-элемент. К счастью для меня, я могу пренебречь этим в моем личном блоге. Это Clip Path!

Добавление clip-path не представляет сложности: с помощью функции polygon можно описать трапецию следующим образом:

header {
  clip-path: polygon(
    0 0, /* left top */
    100% 0, /* right top */ 
    100% 100%, /* right bottom */
    0 90% /* left bottom */
  );
}
Использование функции polygon
Использование функции polygon

И это работает великолепно! Он работает так, как не работали методы transform и border. Можно добавить фоновое изображение, с наложением не происходит ничего курьезного, край резкий, и нужен всего один элемент <header>.

Единственная оговорка: поскольку мы описываем многоугольник относительно его элемента, то при изменении ширины элемента по отношению к его высоте меняется угол наклона. То, что на мобильном телефоне выглядит как огромный угол, на экране retina вряд ли будет выглядеть как наклон. Вот такой же clip-path на более широком элементе:

clip-path на широком элементе
clip-path на широком элементе

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

Расчеты относительно ширины

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

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

header {
  clip-path: polygon(
    0 0,
    100% 0,
    100% 100%,
    0 calc(100% - 6vw)
  );
}

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

Если нужно, чтобы наклон находился в верхней части элемента, то все будет проще: первая строка станет "6vw 0", и даже не понадобится calc().

Сейчас можно прокрутить страницу вверх до хедера (или вниз до футера) и изменить размеры браузера, чтобы увидеть эффект в действии.

Наклонные края с постоянным углом в CSS

Вот так в CSS создаются наклонные края с постоянным углом наклона, которые не нуждаются в overflow:hidden, позволяют использовать фоны и могут быть выполнены с помощью всего одного элемента.

Если у вас есть замечания или улучшения по этой технике, пожалуйста, дайте мне знать об этом в Twitter или напишите мне!

Обновление от 5 июля 2017 г: миксин Sass

Найджел О Тул (Nigel O Toole) создал Sass-миксин, позволяющий задавать угол в градусах. Посмотрите демо.

Комментарии (7)


  1. Cere8ellum
    18.10.2023 17:37

    Вот тоже когда читал начало статьи, параллельно размышлял, что проще реализовать с помощью неких автовычисляемых scss миксинов.


  1. mi_ch_ae_l
    18.10.2023 17:37

    Я в таком случае использую градиет поверх картинки

    header {
     linear-gradient(5deg, transparent calc(50% - 2px), var(--color-bg) 50%), url(./bg.jpg));
    }

    2px вычитается для сглаживания угла


  1. Metotron0
    18.10.2023 17:37

    А если сделать mask, которому указать чёрно-белый градиент с резким переходом?

    Хотя я предпочёл бы clip-path.


  1. LolaBola
    18.10.2023 17:37

    Привет из 2013, какие наклоны паря, о чем ты, это сто лет как вышло из моды


    1. a-v-gor Автор
      18.10.2023 17:37

      С такой стороны я не смотрел на этот вопрос. Меня интересовала техническая реализация. Спасибо за мысль!


    1. johnfound
      18.10.2023 17:37
      +2

      Мода всегда циклическая. Как вышло, так и опять войдет.


    1. Metotron0
      18.10.2023 17:37

      Потому что дизайнерам сказали так не делать, поскольку неудобно прилеплять png шириной в 3840 пикселей?