<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();
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js