Варианты создания «треугольных» навигационных цепочек

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

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

Начнем со структуры HTML

<nav> выступает в качестве родительского элемента. Внутри него располагаются дочерние ссылки.

<nav class="ribbon ribbon--modifier" role="navigation" aria-label="breadcrumbs">
  <a class="ribbon__element" href="https://www.silvestar.codes/">Home</a>
  <a class="ribbon__element" href="https://www.silvestar.codes/categories/articles/">Blog</a>
  <a class="ribbon__element" href="https://www.silvestar.codes/articles/building-an-animated-sticky-header-with-custom-offset/" aria-current="page">Post</a>
</nav>

Создадим несколько базовых стилей

Сначала определим размер шрифта внешнего контейнера .ribbon. Затем зададим стили для дочерних элементов.

/* определяем размер шрифта контейнера*/ 
.ribbon {
  font-size: 15px;
}

/* Используем  em для определения размера элемента навигационной цепочки */ 
.ribbon__element {
  font-size: 1.5em;
  letter-spacing: 0.01em;
  line-height: 1.333em;
  padding: 0.667em 0.667em 0.667em 1.333em;
}

Мы используем единицы em для расчета размера треугольников. Поэтому сможем менять размер всех элементов, изменив значение font-size контейнера.

Для создания макета применим CSS Grid. Мы определим четыре столбца:

  • Три столбца для элементов цепочки;
  • Один столбец для исправления проблем с пробелами. Самая правая стрелка будет располагаться за пределами контейнера, и это может испортить исходный макет.
/* контейнер 
 * Мы используем CSS Grid.

 */
  
.ribbon {
  display: grid;
  grid-gap: 1px;
  grid-template-columns: repeat(auto-fill, 1fr) 1em; /* Автозаполнение трех элементов цепочки и одного узкого столбца, чтобы исправить проблемы с размером */
}

Grid может быть определен по-разному. Например, можно использовать свойство max-content для настройки столбцов по размеру контента. Но имейте в виду, что max-content  не очень хорошо поддерживается популярными браузерами.

/* Настраиваем изменение столбцов в соответствии с максимальным размером контента */
.ribbon--auto {
  grid-template-columns: repeat(3, max-content) 1em;
}

Если вам не нравится стиль outline, вы можете использовать другие свойства CSS, например, такие как box-shadow.

/*Используем текущий цвет ссылки, но добавляем нижнее подчеркивание при наведении курсора мыши */
.ribbon__element:hover, 
.ribbon__element:active {
  color: inherit;
  text-decoration: underline;
}

/* Очищаем стиль по умолчанию и используем тень */
.ribbon__element:focus {
  box-shadow: inset 0 -3px 0 0 #343435;
  outline: none;
}

Создание уникальной треугольной формы

Есть несколько вариантов добавления треугольников в конце каждого элемента цепочки:

  1. Сделать треугольник с границами из псевдоэлементов;
  2. Использовать задний SVG фон на псевдоэлементах;
  3. Использовать встроенные SVG изображения;
  4. Создать clip-path, используя функцию polygon().

Разберемся с каждым вариантом.

Вариант 1: использование границ

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

Далее определим верхние и нижние границы, сделав их прозрачными. Единственное, что осталось сделать – это правильно расположить элементы.

/* Левая стрелка */
.ribbon--alpha .ribbon__element:before {
  /* Устанавливаем размер содержимого на ноль */
  content: '';  
  height: 0;  
  width: 0;

  /* Используем border, чтобы псевдоэлемент соответствовал границам цепочки */
  border-bottom: 1.333em solid transparent;
  border-left: 0.667em solid #fff;
  border-top: 1.333em solid transparent;

  /* Позиционируем элемент абсолютно с левой стороны элемента ленты */
  position: absolute;
  top: 0;  
  bottom: 0;  
  left: 0;
}

/* Правая стрелка */
.ribbon--alpha .ribbon__element:after {
  /* Устанавливаем размер содержимого на ноль */
  content: '';  
  height: 0;  
  width: 0;

  /* Используем border, чтобы псевдоэлемент соответствовал границам ленты */
  border-bottom: 1.333em solid transparent;
  border-left: 0.667em solid;
  border-top: 1.333em solid transparent;

  /* Позиционируем элемент абсолютно с левой стороны цепочки и выводим за ее пределы */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  -webkit-transform: translateX(0.667em);
  transform: translateX(0.667em);
}

Цвет правого треугольника должен совпадать с цветом фона ленты. Поэтому нужно установить правильный цвет границы для каждого псевдоэлемента.

/* Правая стрелка первого элемента */
.ribbon--alpha .ribbon__element:nth-child(1):after {
  border-left-color: #11d295;
}

/* Правая стрелка второго элемента */
.ribbon--alpha .ribbon__element:nth-child(2):after {
  border-left-color: #ef3675;
}

/* Правая стрелка третьего элемента */
.ribbon--alpha .ribbon__element:nth-child(3):after {
  border-left-color: #4cd4e9;
}

И вот результат:

Вариант 2: использование фонового изображения

Треугольник также можно добавить с помощью фонового изображения. Мы будем использовать SVG.

В отличие от предыдущего варианта нам нужно сопоставить высоту нашего псевдоэлемента с высотой цепочки (или 100%). Ширина компонента должна соответствовать ширине левой границы треугольника, которая равна 0.666666em.

Затем мы используем белый треугольник в качестве фонового изображения с левой стороны. После этого применим изображения цветных треугольников с правой стороны.

/* Левая стрелка */
.ribbon--beta .ribbon__element:before {
  /* Определяем размер стрелки */
  content: '';  
  height: 100%;  
  width: 0.666666em;
  
  /* Определяем фоновое изображение, которое совпадает с цветом фона */
  background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=);
  background-position: center left;
  background-repeat: no-repeat;
  background-size: 100%;
  
  /* Позиционируем элемент абсолютно с левой стороны цепочки */
  position: absolute;
  bottom: 0;
  top: 0;
  left: 0;
}

/* Правая стрелка */
.ribbon--beta .ribbon__element:after {
  /* Определяем размер стрелки */
  content: '';  
  height: 100%;
  width: 0.667em;

  /* Определяем параметры фонового изображения */
  background-position: center left;
  background-repeat: no-repeat;
  background-size: 100%;

  /* Позиционируем элемент абсолютно с правой стороны цепочки и выводим за ее пределы */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  -webkit-transform: translateX(0.667em);
  transform: translateX(0.667em);
}

/* Определяем фоновое изображение, которое совпадает с цветом фона первого элемента */
.ribbon--beta .ribbon__element:nth-child(1):after {
  background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsPSIjMTFkMjk1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=);
}

/* Определяем фоновое изображение, которое совпадает с цветом фона второго элемента */
.ribbon--beta .ribbon__element:nth-child(2):after {
  background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsPSIjZWYzNjc1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=);
}

/* Определяем фоновое изображение, которое совпадает с цветом фона третьего элемента */
.ribbon--beta .ribbon__element:nth-child(3):after {
  background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMTAgNDAiIHdpZHRoPSIxMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxNSAyMCAxMGgtNDB6IiBmaWxsPSIjNGNkNGU5IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0ibWF0cml4KDAgLTEgLTEgMCAyNSAyNSkiLz48L3N2Zz4=);
}

Смотрим на результат:

Вариант 3: встроенные SVG-изображения

Также можно использовать SVG-изображения, встроенные непосредственно в HTML.

Данный подход позволяет контролировать цвет заливки каждой стрелки с помощью CSS. Размер стрелки рассчитывается на основе размера цепочки.

/* Позиционируем элемент абсолютно и устанавливаем правильный размер */
.ribbon--gamma .ribbon__element svg {
  height: 2.667em;
  position: absolute;
  top: 0;
  width: 0.667em;
}

/* Левая стрелка */
.ribbon--gamma .ribbon__element svg:first-child {
  fill: #fff; /* Определяем фоновое изображение, которое совпадает с цветом фона */
  left: 0; 
}

/* Правая стрелка */
.ribbon--gamma .ribbon__element svg:last-child {
  left: 100%; /* Выводим правую стрелку за пределы элемента ленты */
}

/* Определяем цвет заливки, который соответствует цвету фона первого элемента*/
.ribbon--gamma .ribbon__element:nth-child(1) svg:last-child {
  fill: #11d295;
}

/* Определяем цвет заливки, который соответствует цвету фона второго элемента */
.ribbon--gamma .ribbon__element:nth-child(2) svg:last-child {
  fill: #ef3675;
}

/* Определяем цвет заливки, который соответствует цвету фона третьего элемента */
.ribbon--gamma .ribbon__element:nth-child(3) svg:last-child {
  fill: #4cd4e9;
}

Вариант 4: использование clip-path

Мы можем создать ленту треугольников с многоугольником, который маскирует фон. Потрясающим инструментом для рисования фигур прямо в браузере является Firefox’s Shape Editor.

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

.ribbon--delta .ribbon__element {
  clip-path: polygon(95% 0, 100% 50%, 95% 100%, 0% 100%, 5% 50%, 0% 0%);
}

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

/* Делаем все элементы ленты (за исключением последнего) шире */
.ribbon--delta .ribbon__element:not(:last-child) {
  width: 105%;
}

/* Делаем последний элемент ленты шире */
.ribbon--delta .ribbon__element:last-child {
  width: calc(100% + .667em);
}

Изменение реализованных вариантов

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

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

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

/* Добавляем тень под каждым элементом ленты */
.ribbon--shadow .ribbon__element {
  box-shadow: 1px 3px 3px -3px black;
}

Использование градиента для цвета

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

/* Добавляем градиент к первому элементу ленты */
.ribbon--gradient .ribbon__element:nth-child(1) {
  background-image: linear-gradient(to right, #11ced2, #11d295);
}

/* Добавляем градиент ко второму элементу ленты */
.ribbon--gradient .ribbon__element:nth-child(2) {
  background-image: linear-gradient(to right, #ef36b2, #ef3675);
}

/* Добавляем градиент для третьего элемента ленты */
.ribbon--gradient .ribbon__element:nth-child(3) {
  background-image: linear-gradient(to right, #4c9fe9, #4cd4e9);
}

Работа с размерами

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

/* Маленькие ленты */
.ribbon--small {
  font-size: 10px;
}

/* Большие ленты */
.ribbon--big {
  font-size: 20px;
}

Тут показаны ленты маленького размера:

А здесь представлены симпатичные короткие ленты:

Комбинируем  все варианты

Теперь можно скомбинировать различные эффекты вместе. Например, давайте применим градиента и тени:

На что еще обратить внимание?

Мы рассмотрели четыре различных варианта создания треугольников навигационной ленты. Вы использовали другой подход? Расскажите об этом в комментариях!

Наталья Кайдаавтор-переводчик статьи «Oh, the Many Ways to Make Triangular Breadcrumb Ribbons!»