HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<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
/* 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();
});
Also see: Tab Triggers