I'm trying to build an horizontal timeline. There can be many events on any given day of a month.
So, when the events are more, the list items are unable to accommodate the available height(from: min-height
) and a vertical scroll is appearing.
If I try removing the min-height
whole content is distorted. I want the container to occupy the list with any number of items without vertical scroll.
Also, there is one more issue, when the window is small(can be seen on codepen), the horizontal scroll appears(expected and needed). But, the connector is not occupying the whole scroll width.
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.timeline__container {
background: #c0ffee;
overflow-x: auto;
display: flex;
position: relative;
}
.timeline__connector {
position: absolute;
width: 100%;
left: 0;
top: calc(50% - 4px);
height: 8px;
background: #ccc;
}
.timeline__item {
background: gold;
min-width: 85px;
min-height: 200px;
display: flex;
flex-direction: column;
justify-content: center;
}
.timeline__item:nth-child(2n) {
flex-direction: column-reverse;
}
.timeline__up {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.timeline__down {
height: 100%;
display: flex;
}
.timeline__month {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
display: inline-block;
}
.timeline__month-up {
margin-bottom: 20px;
align-self: flex-end;
}
.timeline__month-down {
align-self: flex-start;
margin-top: 20px;
}
.timeline__count {
margin: auto;
}
.timeline__count-up {
margin-bottom: 20px;
}
.timeline__count-down {
margin-top: 20px;
}
.timeline__item-event {
min-width: 180px;
}
.timeline__event__list {
height: 100%;
}
.timeline__event__list ul {
margin-left: 20px;
}
<div class="timeline__container">
<div class="timeline__connector"></div>
<div class="timeline__item">
<div class="timeline__up">
<div class="timeline__month timeline__month-down">JAN</div>
</div>
<div class="timeline__down">
<div class="timeline__count timeline__count-up">5</div>
</div>
</div>
<div class="timeline__item">
<div class="timeline__up">
<div class="timeline__month timeline__month-up">FEB</div>
</div>
<div class="timeline__down">
<div class="timeline__count timeline__count-down">15</div>
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">5th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>inventore nihil sint est.</li>
<li>Lorem ipsum dolor sit</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
<!-- <div class="timeline__count timeline__count-up">5</div> -->
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">15th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>inventore nihil sint est.</li>
<li>Lorem ipsum dolor sit</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
</div>
Codepen for the same
The reason why the height or the containers is 0 is because you are floating all the content inside them and floated elements don't expand the height (or width) of their parents.
Top header with 100% width and 50px height. Left navigation bar with 200px width and dynamic height to fill the screen. A container on the right of the nav bar and under the header with dynamic width and height to fill the screen.
I have come up with an idea to combine flex and grid to achieve what you are looking for.
There is a snipped added and I tried to keep the code as clean as possible, added comments on some of them so the code can talk for itself. Didn't change the DOM structure at all. But wait, look at this:
Also, there is one more issue, when the window is small(can be seen on codepen), the horizontal scroll appears(expected and needed). But, the connector is not occupying the whole scroll width.
To solve the above, I wrapped the .timeline__container
into a .timeline__wrapper
. removed position: relative;
from .timeline__container
.
And added position: relative;
to .timeline__wrapper
.
There are enough comments on the code, so when you go through this, you should be able to understand. You can research the grid properties used here to understand actually how this was accomplished.
Also I added a little padding on the timeline up/down classes to ignore the visual conflict with the connector (or the grey line)
Feel free to add/remove list items so that the height of the timeline items increase/decrease, and you can check if this is what was expected.
Almost forgot to mention, this works fine on safari too.
Snippet finally:
* {
/* you can ignore the pseudo elements here */
margin: 0;
padding: 0;
box-sizing: border-box;
}
.timeline__wrapper {
position: relative;
/* to fix the timeline connector */
}
.timeline__container {
background: #c0ffee;
overflow-x: auto;
/* element with an overflow can't display an absolute positioned element, that's why the wrapper up there */
display: flex;
}
.timeline__connector {
position: absolute;
width: 100%;
left: 0;
top: calc(50% - 4px);
height: 8px;
background: #ccc;
}
.timeline__item {
background: gold;
min-width: 85px;
justify-content: center;
display: grid;
grid-auto-flow: row;
grid-auto-rows: 1fr;
/* this keeps the upper and lower portion same height */
}
.timeline__item:nth-child(2n) .timeline__down {
/* these styles reverses the expected rows */
grid-row-start: 2;
grid-row-end: 1;
}
.timeline__up {
display: flex;
align-items: flex-end;
justify-content: center;
padding: 10px;
}
.timeline__item:nth-child(2n) .timeline__up {
align-items: flex-start;
}
.timeline__down {
display: flex;
align-items: flex-start;
padding: 10px;
}
.timeline__month {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
display: inline-block;
}
.timeline__month-up {
margin-bottom: 20px;
align-self: flex-end;
}
.timeline__month-down {
align-self: flex-start;
margin-top: 20px;
}
.timeline__count {
margin: auto;
}
.timeline__count-up {
margin-bottom: 20px;
}
.timeline__count-down {
margin-top: 20px;
}
.timeline__item-event {
min-width: 180px;
}
.timeline__event__list ul {
margin-left: 20px;
}
<div class="timeline__wrapper">
<div class="timeline__container">
<div class="timeline__connector"></div>
<div class="timeline__item">
<div class="timeline__up">
<div class="timeline__month timeline__month-down">JAN</div>
</div>
<div class="timeline__down">
<div class="timeline__count timeline__count-up">5</div>
</div>
</div>
<div class="timeline__item">
<div class="timeline__up">
<div class="timeline__month timeline__month-up">FEB</div>
</div>
<div class="timeline__down">
<div class="timeline__count timeline__count-down">15</div>
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">5th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>inventore nihil sint est.</li>
<li>Lorem ipsum dolor sit</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
<!-- <div class="timeline__count timeline__count-up">5</div> -->
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">15th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>inventore nihil sint est.</li>
<li>Lorem ipsum dolor sit</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
<div class="timeline__item timeline__item-event">
<div class="timeline__up">
<div class="timeline__event__list">
<div class="timeline__date">25th</div>
<ul>
<li>Lorem ipsum</li>
<li>Lorem ipsum</li>
<li>dolor sit</li>
</ul>
</div>
</div>
<div class="timeline__down">
</div>
</div>
</div>
</div>
Update: Added more items to the view according to comments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With