<section id="timeline">
<div class="section-wrapper">
<div class="line">
<div data-mobiletext="Quarter 4" data-index="1" class="quarter q4 y2016 dot complete"></div>
<div data-mobiletext="2017" data-timelinelabel="Open store" data-index="2" class="year y2017 dot complete"></div>
<div data-mobiletext="Quarter 1" data-index="2" class="quarter q1 y2017 dot complete js-mobile-default"></div>
<div data-mobiletext="Quarter 2" data-index="3" class="quarter q2 y2017 dot"></div>
<div data-mobiletext="Quarter 3" data-index="4" class="quarter q3 y2017 dot"></div>
<div data-mobiletext="Quarter 4" data-index="5" class="quarter q4 y2017 dot"></div>
<div data-mobiletext="2018" data-timelinelabel="Hire first staff" data-index="6" class="year y2018 dot"></div>
<div data-mobiletext="Quarter 1" data-index="6" class="quarter q1 y2018 dot"></div>
<div data-mobiletext="Quarter 2" data-index="7" class="quarter q2 y2018 dot"></div>
<div data-mobiletext="Quarter 3" data-index="8" class="quarter q3 y2018 dot"></div>
<div data-mobiletext="Quarter 4" data-index="9" class="quarter q4 y2018 dot"></div>
<div data-mobiletext="2019" data-timelinelabel="Expand product offerings" data-index="10" class="year y2019 dot"></div>
<div data-mobiletext="Quarter 1" data-index="10" class="quarter q1 y2019 dot"></div>
<div data-mobiletext="Quarter 2" data-index="11" class="quarter q2 y2019 dot"></div>
<div data-mobiletext="Quarter 3" data-index="12" class="quarter q3 y2019 dot"></div>
<div data-mobiletext="Quarter 4" data-index="13" class="quarter q4 y2019 dot"></div>
<div data-mobiletext="2020" data-timelinelabel="Open second store" data-index="14" class="year y2020 dot"></div>
<div data-mobiletext="Quarter 1" data-index="14" class="quarter q1 y2020 dot"></div>
<div data-mobiletext="Quarter 2" data-index="15" class="quarter q2 y2020 dot"></div>
<div data-mobiletext="Quarter 3" data-index="16" class="quarter q3 y2020 dot"></div>
<div data-mobiletext="Quarter 4" data-index="17" class="quarter q4 y2020 dot"></div>
</div>
</div>
</section>
<section id="description">
<div class="section-wrapper">
<h3>GOALS AND OBJECTIVES</h3>
<div data-index="1">
<p>Year 2016, Quarter 4</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur, alias. Magni harum, earum fugit, officia eveniet minima, expedita accusantium, esse aspernatur omnis neque. Soluta, consequatur adipisci non molestiae omnis odit.</p>
</div>
<div data-index="2" class="text-default">
<p>Year 2017, Quarter 1</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae, consequuntur.</p>
</div>
<div data-index="3">
<p>Year 2017, Quarter 2</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis assumenda ipsa maiores sunt fugiat deserunt pariatur est incidunt, enim quis.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus facere necessitatibus illum debitis minus amet recusandae optio fugit tempora veritatis.</p>
</div>
<div data-index="4">
<p>Year 2017, Quarter 3</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, nihil. Ea nesciunt sed, quidem sapiente dolorem voluptatum, adipisci recusandae ducimus amet sequi atque ipsa officiis pariatur consectetur velit alias. Officiis, at illo aperiam ex accusamus, vel ab obcaecati doloribus numquam fugiat unde, error. Atque iusto nulla porro, ducimus ex vel.</p>
</div>
<div data-index="5">
<p>Year 2017, Quarter 4</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Libero laudantium repudiandae quos magni iste cum, a quisquam eligendi quasi, at animi autem necessitatibus, cumque rem optio maiores. Placeat inventore repellat voluptate reprehenderit adipisci aperiam tempore?</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio, aut illum repellat, itaque ducimus eius.</p>
</div>
<div data-index="6">
<p>Year 2018, Quarter 1</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod, vel atque molestiae dolorum soluta magni, dolores a maxime iure illo.</p>
</div>
<div data-index="7">
<p>Year 2018, Quarter 2</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dicta non quam quae consectetur laborum eveniet, similique placeat illo velit enim eligendi facilis deleniti laboriosam iure natus totam! Nostrum ipsa debitis iste eum laborum odio, aliquam dolor fuga hic unde.</p>
</div>
<div data-index="8">
<p>Year 2018, Quarter 3</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet, eveniet?</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto officia, quam iste tempore eos, vel quis nulla, aliquid pariatur deleniti libero nesciunt dicta minus reiciendis.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ex dolor, atque repellat nulla doloribus nostrum.</p>
</div>
<div data-index="9">
<p>Year 2018, Quarter 4</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates similique expedita cumque alias facilis commodi vitae recusandae, quisquam officia officiis autem distinctio quis consequuntur velit deleniti iusto illo accusantium earum, delectus blanditiis minima. Enim fugit totam, esse cumque consequatur dignissimos.</p>
</div>
<div data-index="10">
<p>Year 2019, Quarter 1</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad, laboriosam!</p>
</div>
<div data-index="11">
<p>Year 2019, Quarter 2</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sed odio iste harum quia facilis, omnis autem non, corporis ullam perspiciatis earum voluptas facere accusantium itaque asperiores, illo debitis ducimus. Facere nobis ipsam beatae voluptatum nisi possimus aliquam eum excepturi, quisquam odit, alias dolores enim, soluta nulla. Ratione quam architecto dolore.</p>
</div>
<div data-index="12">
<p>Year 2019, Quarter 3</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Est consequuntur unde laborum officiis minus, impedit voluptates. Fugiat perspiciatis nesciunt itaque!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt doloribus eaque id in cumque aliquam voluptatem, officia unde assumenda corrupti!</p>
</div>
<div data-index="13">
<p>Year 2019, Quarter 4</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae officia quas aut autem a quibusdam quam voluptas, optio iure recusandae eum, similique voluptate excepturi nobis suscipit, laboriosam laborum veniam mollitia!</p>
</div>
<div data-index="14">
<p>Year 2020, Quarter 1</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minus quod adipisci dolores, consectetur aperiam aliquam.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rerum ipsum vitae, consequuntur quidem, quasi quaerat.</p>
</div>
<div data-index="15">
<p>Year 2020, Quarter 2</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem, perferendis facilis neque vero nostrum asperiores aperiam tenetur debitis sunt labore magnam ipsum nesciunt quo inventore explicabo hic at. Sed minus optio est illum, placeat, corporis necessitatibus fuga aperiam et officia, nobis nihil quas! Quasi temporibus corrupti consectetur, id natus nobis commodi quis. Inventore voluptate porro, excepturi dicta quasi consequuntur beatae.</p>
</div>
<div data-index="16">
<p>Year 2020, Quarter 3</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci, veritatis.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis ratione consequatur fugiat vero, dolor modi qui, libero rem repellat accusantium.</p>
</div>
<div data-index="17">
<p>Year 2020, Quarter 4</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non quam aliquam aperiam consectetur sequi libero laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</div>
</div>
</section>
<div style="background-color: #FBFCFC; width: 255px; height: 40px; padding: 10px; box-sizing: border-box; position: absolute; bottom: 5px; right: 5px; font-size: 0.9em;"><a href="https://codepen.io/cjl750/pen/wdVxzV" target="_blank">Alternate version using range input</a></div>
<div style="background-color: #FBFCFC; width: 255px; height: 40px; padding: 10px; box-sizing: border-box; position: absolute; bottom: 50px; right: 5px; font-size: 0.9em;"><a href="https://codepen.io/cjl750/pen/mXbMyo" target="_blank">Version 3: greatly simplified code</a></div>
$zero: #FBFCFC
$one: #FFC107
$two: #34495E
$three: #F1C40F
$four: #C0392B
$desktop-complete: #{$four}
$mobile-complete: #{$two}
$incomplete: #{$zero}
$desktop-active: #{$two}
$mobile-active: #{$four}
=circle
background-color: $incomplete
border-radius: 50%
float: left
position: relative
left: 5.3% // (line width / # of dots)
box-sizing: border-box
html
background-color: $two
font-family: 'Raleway'
color: $zero
section
width: 100%
box-sizing: border-box
min-height: 33vh
.section-wrapper
padding: 10px
box-sizing: border-box
height: 100%
.line
width: 90%
height: 4px
background: linear-gradient(to right, $desktop-complete 13.25%, $incomplete 13.25%) // (# of dots filled * (line width / # of dots)) + ((line width / # of dots) / 2)
margin-top: 20vh
margin-left: 5% // perfect centering
&:hover
cursor: pointer
.year
+circle
// MARGINS = (((line width ÷ # of dots) ÷ 2) - (dot width ÷ 2))
// ....... = (((0.9 ÷ 17) ÷ 2) - (25 ÷ 2))
margin-right: calc(2.65% - 12.5px)
margin-left: calc(2.65% - 12.5px)
width: 25px
height: 25px
top: -10px
&::before
content: attr(data-timelinelabel)
position: absolute
top: -75px
left: -5px
width: 150px
transform: rotateZ(-45deg)
display: block
font-size: 0.8em
font-weight: bold
&::after
content: attr(data-mobiletext)
position: absolute
top: 23px
left: -15px
padding: 10px
.quarter
+circle
margin-right: calc(2.65% - 7.5px) // -7.5px since these dots are only 15px wide
margin-left: calc(2.65% - 7.5px)
width: 15px
height: 15px
top: -5px
.complete
background-color: $desktop-complete
.dot
&.active
background-color: $desktop-complete
cursor: pointer
#timeline
padding-top: 50px
padding-bottom: 50px
background-color: $three
color: $two
#description
min-height: 30vh
background-color: $two
h3
color: $desktop-complete
font-weight: 600
.section-wrapper > div
display: none
&.text-default
display: block
@media all and (max-width: 760px)
.line
.year
width: 20px
height: 20px
margin-right: calc(2.65% - 10px)
margin-left: calc(2.65% - 10px)
top: -8px
.quarter
width: 10px
height: 10px
margin-right: calc(2.65% - 5px)
margin-left: calc(2.65% - 5px)
top: -3px
@media all and (min-width: 481px)
.quarter
&.q1
display: none
.dot
&:hover
background-color: $desktop-active
cursor: pointer
@media all and (max-width: 480px)
#timeline
padding-bottom: 20px
padding-top: 0
.line
height: auto
background: transparent
margin-top: 20px
.year, .quarter
border-radius: 0
float: none
position: static
margin-right: 0
margin-left: 0
box-sizing: border-box
width: 100%
height: 42px
text-align: center
transition: background-color 500ms
&::after
content: attr(data-mobiletext)
display: block
padding-top: 12px
&.complete
background-color: $mobile-complete
color: $zero
&.active, &.complete.active
background-color: $mobile-active
color: $zero
.year
display: block
&::before
display: none
&::after
position: static
.quarter
display: none
&.y2017
display: block
View Compiled
/* JS will not correctly work when switching between desktop and mobile unless in debug mode */
$(function(){
var timeline = $('#timeline').find('.line');
var timelineDot = $(timeline).find('.dot');
var numDots = $(timeline).find('.year.dot').length * 4 + 1;
var mobileYear = $(timeline).find('.year.dot');
var mobileDefault = $(timeline).find('.dot.js-mobile-default');
$(mobileDefault).addClass('active');
// CONTENT SWITCH
$(timelineDot).each(function(){
$(this).click(function(){
var currentDesc = $('#description').find('.section-wrapper > div');
$(currentDesc).hide();
matchContent($(this)).fadeIn();
});
});
var resizeTimer;
var initialSize = $(window).width();
$(window).resize(function(){
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function(){
var delayedSize = $(window).width();
// if we resize but not enough to change layout, proceed as usual
if ((initialSize > 480 && delayedSize > 480) || (initialSize < 481 && delayedSize < 481)) {
if (initialSize > 480 && delayedSize > 480) {
desktopTimeline();
} else if (initialSize < 481 && delayedSize < 481) {
mobileTimeline();
}
}
// if we resize the page and switch between desktop and mobile layouts, reload the page
else {
location.reload();
}
initialSize = delayedSize;
}, 250);
});
// DESKTOP FUNCTIONALITY
function desktopTimeline(){
$(timelineDot).each(function(){
// highlight the appropriate portion of the line as you click the dots
var ind = Number(findIndex($(this)));
var x = round((0.9 / numDots) * ind * 100, 4);
var y = round(((0.9 / numDots) * 100 / 2), 4);
var z = x + y;
$(this).click(function(){
$(timelineDot).removeClass('active complete');
$(this).addClass('active');
$(this).prevAll('.dot').addClass('complete');
$(timeline).css({
background: 'linear-gradient(to right, ' +
'#C0392B ' + z + '%, ' +
'#FBFCFC ' + z + '%)'
});
});
});
}
// MOBILE FUNCTIONALITY
function mobileTimeline() {
$(timelineDot).click(function(){
var mobileQuarter = $(this).nextUntil('.year.dot');
if ($(this).hasClass('year')) {
$(timelineDot).not($(this)).removeClass('active complete');
$(this).addClass('complete');
$(this).next().addClass('active');
$(this).prevAll('.dot.year').addClass('complete');
$('.dot.quarter').not(mobileQuarter).slideUp(500);
$(mobileQuarter).slideDown(500);
} else if ($(this).hasClass('quarter')) {
var parentYear = $(this).prevUntil('.dot.year');
$(this).addClass('active');
$(timelineDot).not($(this)).removeClass('active');
$(mobileQuarter).add(mobileYear).removeClass('complete');
$(parentYear).add($(this)).add($(this).prevAll('.dot.year')).addClass('complete');
}
});
}
// RETRIEVE ELEMENT'S INDEX AMONG VISIBLE DOTS
function findIndex(dataInd) {
return $(dataInd).attr('data-index');
}
// FIND MATCHING CONTENT
function matchContent(matchedContent){
return $('#description').find('.section-wrapper > div[data-index="' + $(matchedContent).attr("data-index") + '"]');
}
// ROUND DECIMALS
function round(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}
$(window).resize();
});
This Pen doesn't use any external CSS resources.