Bootstrap - Как создать таймлайн (timeline)

Статья, в которой рассмотрим процесс создания адаптивного таймлайна с использованием классов сетки Bootstrap 4.
Что такое таймлайн
Таймлайн - это элемент интерфейса, предназначенный для отображения на сайте списка некоторых событий в хронологическом порядке.
Например, с его помощью на сайте можно организовать представление истории публикаций или действий пользователя (в личном кабинете).
Что же собой представляет таймлайн? Таймлайн представляет собой "линию времени", на которой посредством контрольных точек отмечаются определённые события. Каждое событие на этой линии поясняется с помощью некоторого контента.
Таймлайны бывают горизонтальные и вертикальные.
Создание вертикального таймлайна
Процесс разработки вертикального таймлайна состоит из создания структуры HTML-кода и CSS.

HTML-структура вертикального таймлайна:
<!-- HTML-разметка вертикального таймлайна -->
<section class="timeline">
...
<div class="row">
<!-- 1 элемент -->
<div class="col-12 col-sm-6 timeline-wrapper">
<div class="timeline-item">
<span class="timeline-item-section">РАЗДЕЛ</span>
<span class="timeline-item-date">07.05.2018</span>
<span class="timeline-item-header">НАЗВАНИЕ СТАТЬИ</span>
<span class="timeline-item-description">Детальное описание статьи</span>
<span class="timeline-item-link">
<a href="#">Перейти</a>
</span>
</div>
</div>
<!-- 2 элемент -->
<div class="col-12 col-sm-6 timeline-wrapper">
<div class="timeline-item">
<span class="timeline-item-section">РАЗДЕЛ</span>
<span class="timeline-item-date">25.04.2018</span>
<span class="timeline-item-header">НАЗВАНИЕ СТАТЬИ</span>
<span class="timeline-item-description">Детальное описание статьи</span>
<span class="timeline-item-link">
<a href="#">Перейти</a>
</span>
</div>
</div>
...
</div>
...
</section>
Немного о структуре HTML-кода таймлайна. Элемент с классом timeline - это контейнер. Добавление контрольных точек осуществляется посредством помещения элементов с классом timeline-wrapper в этот контейнер.
В свою очередь элемент с классом timeline-wrapper - это тоже контейнер, но уже для элементов таймлайна (timeline-item).
Элемент таймлайна (timeline-item) имеет простую структуру и состоит из 5 span элементов. Каждый из них используется элементов для разметки той или части контента контрольной точки.
Следующий шаг - это создание CSS кода для вышеприведённого HTML (действие каждого правила пояснено с помощью комментария).
/* CSS */
/* Добавление отступов к элементу с классом timeline */
.timeline {
padding-top: 1rem;
padding-bottom: 1rem;
position: relative;
}
/* Создание вертикальной линии с помощью псевдоэлеметна */
.timeline::before {
content: "";
position: absolute;
width: .125rem;
height: 100%;
background-color: #dee2e6;
left: 2rem;
top: 0;
}
/* добавление нижнего отступа и левого поля для элементов с классом timeline-wrapper */
.timeline-wrapper {
margin-bottom: 1rem;
padding-left: 4rem;
}
/* убирание у последнего элемента .timeline-wrapper нижнего отступа */
.timeline-wrapper:last-child {
margin-bottom: 0;
}
/* стили для элементов таймлайна */
.timeline-item {
position: relative;
background-color: #118c4e;
color: #fff;
padding: .825rem;
border-radius: .25rem;
}
/* добавление контрольных точек на вертикальную линию */
.timeline-item::before {
content: "";
position: absolute;
width: .75rem;
height: .75rem;
background-color: #118c4e;
border-radius: .4rem;
left: -2.3125rem;
top: 50%;
transform: translateY(-50%);
}
/* добавление стрелочек к элементам таймлайна */
.timeline-item::after {
content: "";
position: absolute;
width: 0;
height: 0;
border-top: 1rem solid transparent;
border-bottom: 1rem solid transparent;
border-right: 1rem solid #118c4e;
left: -1rem;
top: 50%;
transform: translateY(-50%);
}
/* стили для блока, в котором будет отображаться название статьи */
.timeline-item-header {
display: block;
font-weight: bold;
font-size: 1.125rem;
}
/* оформление блока, содержащего название раздела */
.timeline-item-section {
position: absolute;
top: 0;
right: 0;
background-color: rgba(255,255,255,.4);
padding: .3rem;
font-size: .875rem;
border-top-right-radius: .25rem;
}
/* оформление блока, содержащего дату */
.timeline-item-date {
display: block;
font-size: .75rem;
line-height: 2;
color: rgba(255,255,255,.8);
}
/* стили для блока, в который будет выводиться описание статьи */
.timeline-item-description {
display: block;
font-size: .875rem;
color: rgba(255,255,255,.8);
line-height: 1.7;
}
/* стили для блока, содержащего ссылку "Перейти" */
.timeline-item-link {
display: block;
font-size: .875rem;
line-height: 1.7;
text-align: right;
}
/* стили для ссылки "Перейти" */
.timeline-item-link a {
text-decoration: none;
color: rgba(255,255,255,1);
border-bottom: 1px dashed rgba(255,255,255,1);
}
/* стили для ссылки "Перейти" при поднесении к ней курсора или когда она находится в состоянии фокуса */
.timeline-item-link a:hover, .timeline-item-link a:focus {
color: rgba(255,255,255,.8);
border-bottom: 1px dashed rgba(255,255,255,.8);
}
/* для адаптивности (стили для больших экранов) */
@media (min-width: 576px) {
/* для вывода вертикальной линии по центру */
.timeline::before {
left: 50%;
}
/* стили для нечётных элементов с классом timeline-wrapper */
.timeline-wrapper:nth-child(odd) {
padding-right: 2rem;
padding-left: 15px;
}
/* стили для чётных элементов с классом timeline-wrapper */
.timeline-wrapper:nth-child(even) {
padding-left: 2rem;
margin-left: 50%;
margin-top: -2rem;
}
/* дополнительный сдвиг вверх для нечетных элементов (начиная с 3) */
.timeline-wrapper:nth-child(2n+3) {
margin-top: -2rem;
}
/* стили для псевдоэлементов ::before элементов таймлайна, расположенных в нечётных контейнерах */
.timeline-wrapper:nth-child(odd) .timeline-item::before {
right: -2.5rem;
left: unset;
}
/* стили для псевдоэлементов ::after элементов таймлайна, расположенных в нечётных контейнерах */
.timeline-wrapper:nth-child(odd) .timeline-item::after {
border-left: 1rem solid #118c4e;
border-right: none;
left: unset;
right: -1rem;
}
}
Когда ширина viewport имеет значение меньше, чем 576px, таймлайн переключается в мобильный вид. В этом режиме контент событий всегда размещается справа от линии времени.

В большинстве случаев это конечно выполняют на сервере. Получаете набор данных и через цикл формируете HTML код.
Другой случай, когда вы формируете timeline на клиенте, используя AJAX. В этом случае вы запрашиваете данные с сервера и формируете HTML код timeline с помощью JavaScript.
Для этого необходимо удалить:
— CSS код для больших экранов
— класс col-sm-6 у элементов timeline-wrapper
Пример timeline у которого все элементы располагаются справа от линии времени:
itchief.ru/examples/lab.php?topic=bootstrap&file=b4-timeline-2
При горизонтальной ориентации телефона нечетные элементы занимают всю ширину.
И если вся конструкция уже вложена в div с классом «container» необходимо всему блоку добавлять левый отступ 4rem