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

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

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

Начнем со структуры 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!»