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.
<h1>Reading progress bar</h1>
<p>This is a demo of a jQuery “sticky” reading progress bar which I recently developed for <a href="http://logikcull.com/white-papers/dont-get-hacked">Logikcull</a>. It hides when the viewport is too narrow, sticks to the top of the viewport on scroll, displays reading progress by section and also within each section. It can also be used for navigation.</p>
<p>The HTML for the progress bar is generated dynamically on pageload based on the elements used to define each section (in this case, H2 headers).</p>
<p>The JS could be neater, I'm sure...!</p>
<h2>Gouda</h2>
<p>Ad possit debitis sea, ea hinc discere dissentiet mel, persius posidonium sadipscing pri no. Vix fugit nusquam fierent in, cu probo congue ius. Cu regione viderer pro, quot veniam appetere et vix. Cum at nisl praesent. No nam nostro audire, no sit populo tibique, id ceteros appetere platonem pri. An graecis salutatus sed. His an dico efficiendi, novum eruditi at nec, vel ei affert mucius consequat.</p>
<p>Ex prompta constituam vis, an eos deleniti tractatos, nam alii aliquando temporibus eu. Duo ei nulla animal elaboraret. Meis adhuc id vix, ne nam nihil graecis antiopam. Vel ea eligendi perfecto repudiandae, no pri tation deterruisset. Ei unum nihil sea, tantas minimum invidunt vel an, nominavi delicata posidonium cum no. Porro adversarium cum eu, admodum lucilius nec at, eu magna definitionem has. Nam lorem movet tollit in.</p>
<p>Harum euismod assentior ei has, vidisse principes consetetur ne vel. No iriure eripuit quo, integre persequeris ex vis, ne has autem probatus. Elit copiosae efficiendi te sea, duo ad aeterno graecis, an populo assueverit sit. Vis an fabulas graecis expetenda, natum quaestio at vim. Cu sed nisl utroque vituperatoribus, ne vim stet ocurreret.</p>
<p>Nihil iracundia usu in, sit ex admodum liberavisse necessitatibus, menandri dissentiunt at his. Pri at saepe tamquam expetenda, cu eros mollis blandit eos, possit quaestio ut nec. Te expetenda evertitur vis, semper dictas eleifend cum at. Mea deserunt maiestatis percipitur ex, te sea habeo percipitur, qui ne harum tritani persequeris. Eos eu quod dolore. Ius erat illum eu, tractatos mediocrem vim ea.</p>
<h2>Brie</h2>
<p>Sea in singulis delicatissimi, alia prima ei cum. Sed in quas dissentias reprehendunt. Paulo semper corpora ne pri, vis no iriure luptatum. Alii error diceret ius te, dolorum complectitur definitionem vix ea. Fugit atqui debitis ad his. Perfecto delicata senserit id has. Tempor inimicus erroribus eam ex.</p>
<p>Pro falli eruditi sapientem ei, lucilius periculis ius ea. Eum veri meliore mentitum ex, ne erat graece per. In pro habeo simul vituperatoribus, pro minim noster utroque an. Partem delicatissimi cum et, no aeque nonumy urbanitas est. Sonet vivendum in nam. Nec porro ubique scripta in, veri saperet graecis vis cu, has cu dicat sanctus impedit. Mei in duis timeam invenire.</p>
<h2>Manchego</h2>
<p>Eos ex erant latine sanctus, at sea labore adolescens ullamcorper. Ut aeque veritus vis, no cum doming civibus adipiscing. Te mel eius quidam blandit, iudico nusquam pri ex.</p>
<p>Probo dicunt his eu, eum et eirmod labitur accommodare. Duo tempor euripidis ut, his nostrud persecuti in. Tantas oportere ullamcorper sed no, id paulo vitae voluptatibus sea. Quo te aliquid nominati signiferumque. Ad has graecis gubergren, cu iracundia voluptatibus pri.</p>
<p>Vero mediocrem salutatus ne mel. Ex prima justo volumus mei. Te sed nemore praesent interesset, eam evertitur similique comprehensam in. Ei modus minimum menandri mel, tollit perpetua eloquentiam qui ea. No modus iriure aliquip quo.</p>
<h2>Camembert</h2>
<p>Erroribus cotidieque ex quo, iisque habemus ex eos, vocent apeirian necessitatibus sit at. Sint partem invidunt te qui. His eros integre saperet at, vidit aliquip eos no. Qui ea veniam soleat periculis.</p>
<p>Has idque volutpat percipitur ea, his ne elitr sanctus detraxit. Cu eos assum dolorum recusabo, eu mei omnes suscipiantur, at eos timeam regione. Duo quas explicari cu, habemus deterruisset vix ne. An quo ferri dicam forensibus, eu populo labore corpora nec, facete commune ancillae ut pro. Nam iusto placerat te.</p>
<p>Antiopam mnesarchum temporibus cu nam, ei duo affert commune efficiendi. Usu inani efficiantur ex. Natum docendi tincidunt ex eum, qui ut diam veniam volutpat, ferri utinam munere eu vel. Ei cum liber perpetua gubergren.</p>
<h2>Edam</h2>
<p>Lorem ipsum dolor sit amet, in viderer periculis nam, delectus accusamus pro no. Sea nusquam partiendo consequat id, has tation temporibus consequuntur id. Fastidii liberavisse usu ad, prima civibus expetendis ex eum, est ex posse lucilius repudiare. Eu delenit sapientem molestiae nec, his ei cibo autem aliquando, impetus appellantur sea cu. Reque audiam ad his, case dignissim posidonium an duo, ex deleniti noluisse deterruisset usu.</p>
<p>Et impetus aliquip mel, per quod probo accumsan et. Ea solum pertinacia eloquentiam nec, et iisque sensibus scriptorem mei. Mazim laoreet repudiare ex nam, possit platonem te mei, his brute impetus adversarium ne. Usu vero autem inermis no, id wisi viris democritum vix.</p>
<p>Mandamus hendrerit scribentur eu vis, et nam aperiri volumus. Ut vix graecis legendos eleifend, ad quas mucius per. Justo nonumes offendit at mel, ut mea prompta recusabo neglegentur, at possim noluisse usu. Ad quidam aliquando vis, eam quidam ancillae pertinax eu, vis eu solum nonumy nostrud. Et cum saepe homero aeterno, graece inermis te qui, sea ut legimus urbanitas intellegat.</p>
<h2>Gorgonzola</h2>
<p>Pri antiopam volutpat te, an unum menandri quo, mei eu error comprehensam. Cu debitis scribentur sea, id errem regione percipit eos, omnium aliquando efficiendi his id. Mei et quot neglegentur, senserit indoctum his te. Commodo delectus eu usu, vel te atqui cetero nostrud. No nobis explicari cum, quo dico simul no.</p>
<p>Corpora euripidis te nam. At ius nihil indoctum sadipscing, qui at stet docendi constituto. Porro consequuntur an quo, et quodsi aliquando usu, an nec tamquam sensibus. Ea ius dictas quodsi cetero, natum praesent necessitatibus id vim, dissentiet ullamcorper ea sed. At mel menandri comprehensam, ad eos velit moderatius.</p>
<p>Prima dolorum id his, vix te volumus persecuti. Usu in solum integre, vocibus oporteat eu vix. Ei mel meis facete. Vix an copiosae electram. Te dicta laudem usu, vim mandamus referrentur ne.</p>
<p>Mel sensibus maiestatis dissentiunt te, cum cu atomorum inimicus, has indoctum mediocrem gloriatur ea. Eu modus interpretaris pro, ea duo epicuri salutatus principes. Sit cu everti bonorum torquatos. At nominati inimicus rationibus eum. No ius facer similique, ei pri alia eius vulputate. Mea ex mazim ludus scriptorem, sea lucilius constituam ei.</p>
<p>In cum munere habemus reformidans, vis iriure consequat an, vel te zril iisque. Error accusam duo ad, ei mel posse utamur omnesque. Sea tempor facilisi at, graeco conceptam eos cu. Ridens detraxit complectitur has ut, no atomorum oportere dignissim sit. Sed solum laoreet torquatos cu, per ea efficiendi comprehensam.</p>
<p>Per prompta nostrud an. Labitur iuvaret constituam nec ne, per meliore vituperata repudiandae ad. Ut per accusata oportere, cu delenit convenire contentiones eos. Ut usu elaboraret percipitur. Nam efficiendi disputando an. Eum et erat atqui omnesque, omnes appetere cu vel, et eos nusquam delicata.</p>
$background: #D6E1E5;
$subtle: #B6D1DA;
$h1: #DB5B33;
$h2: #4598B5;
$body: #6B7072;
$dark: #222;
*, *:before, *:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.clearfix:before,
.clearfix:after {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.clearfix {
*zoom: 1;
}
body {
background-color: $background;
color: $body;
font-size: 100%;
margin-bottom: 10em;
@media only screen and (min-width: 700px) { font-size: 110%; }
@media only screen and (min-width: 800px) { font-size: 120%; }
}
h1, h2, p {
padding: 0 50px;
line-height: 1.75;
@media only screen and (min-width: 800px) { padding: 0 100px; }
margin: 0 auto;
max-width: 1100px;
}
h1, h2 {
font-family: 'Open Sans';
font-weight: 300;
font-size: 250%;
line-height: 1.5;
}
h1 {
margin-top: 1.5em;
margin-bottom: 1.5em;
color: $h1;
}
h2 {
margin-top: 2em;
margin-botttom: 1em;
color: $h2;
}
p {
font-family: 'Merriweather';
font-weight: 300;
font-size: 100%;
margin-top: 2em;
margin-bottom: 2em;
}
a {
color: darken($body, 25%);
text-decoration: underline;
transition: color 100ms ease-in;
&:hover, &:focus {
color: $h1;
}
}
.progressbar {
display: none;
@media only screen and (min-width: 650px) { display: block; }
margin: 4em 0;
.shim {
display: none;
width: 100%;
}
.holder {
position: relative;
font-size: 85%;
@media only screen and (min-width: 750px) { font-size: 90%; }
@media only screen and (min-width: 900px) { font-size: 95%; }
padding: 1.8em 0 0 0;
background-color: $background;
box-shadow: 0 .5em 1.5em $background;
.bar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2px;
background-color: $subtle;
.indicator {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: $h2;
}
}
.labels {
max-width: 1280px;
margin: 0 auto;
padding: 0 2em;
text-align: center;
i {
display: block;
position: relative;
float: left;
cursor: pointer;
&::before {
position: absolute;
bottom: 0;
left: 50%;
display: block;
content: '';
width: .9em;
height: .9em;
border-radius: 50%;
border: solid 3px $subtle;
background-color: $background;
transform: translateX(-50%) translateY(50%);
transition:
border-color 100ms ease-in,
background-color 150ms ease-in;
}
&::after {
display: block;
content: attr(data-label);
position: relative;
top: 0;
padding-bottom: 1.8em;
font-family: 'Open Sans';
font-weight: 400;
color: $h2;
transition:
color 150ms ease-in,
top 100ms ease-out;
}
&:hover, &:focus {
&::before {
background-color: $subtle;
}
&::after {
top: -.2em;
}
}
&.read {
&::before {
border-color: $h2;
}
&:hover, &:focus {
&::before {
background-color: $h2;
}
}
}
&.reading {
&::after {
color: $dark;
}
&:hover, &:focus {
&::after {
top: 0;
}
}
}
}
}
}
&.fixed {
.holder {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1;
}
.shim {
display: block;
}
}
}
jQuery.extend(jQuery.easing, {
easeInOutCubic: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
}
});
$(document).ready(function(){
// set up and create progress bar in DOM
$('h2').eq(0).before('<div class="progressbar"></div>');
var container = $('.progressbar');
container.append('<div class="shim"></div>');
var shim = $('.progressbar .shim');
container.append('<div class="holder clearfix"></div>');
var holder = $('.progressbar .holder');
holder.append('<div class="bar"></div>');
var bar = $('.progressbar .bar');
bar.append('<div class="indicator"></div>');
var indicator = $('.progressbar .indicator');
holder.append('<div class="labels"></div>');
var labels = $('.progressbar .labels');
$('h2').each(function(){
var code = '<i data-label="'+$(this).text()+'"></i>';
labels.append(code);
});
var points = labels.find('i');
points.css('width', 100/$('h2').length+'%');
// match height of shim
// stop layout jumping when progress bar fixes to / unfixes
// from top of viewport
function setShimHeight(){
shim.css('height', container.height()+'px');
}
setShimHeight();
$(window).resize(function(){ setShimHeight(); });
// position indicator bar so it starts at first dot
function setIndicatorX(){
var point = points.eq(0);
var xpos = point.offset().left + (point.width() / 2);
indicator.css('left', xpos+'px');
}
setIndicatorX();
$(window).resize(function(){ setIndicatorX(); });
// fix/unfix progress bar to top of viewport
function fixPosition(){
if(container.is(':visible')) {
if(!container.hasClass('fixed')) {
if(holder.offset().top <= $(window).scrollTop()) {
container.addClass('fixed');
}
}
else {
if(shim.offset().top > $(window).scrollTop()) {
container.removeClass('fixed');
}
}
}
}
fixPosition();
$(window).scroll(function(){ fixPosition() });
$(window).resize(function(){ fixPosition(); });
// set trigger point
// i.e. how far down viewport is the "eye line"
var triggerPoint = 0;
function setTriggerPoint(){
triggerPoint = $(window).height() * .18;
}
setTriggerPoint();
$(window).resize(function(){ setTriggerPoint(); });
// update progress bar
function setPosition(){
if(container.is(':visible')) {
var section = false;
var sectionIndex = 0;
var currentPosition = $(window).scrollTop() + triggerPoint;
// dots
// if before first section
if(currentPosition < $('h2').eq(0).offset().top) {
points.removeClass('reading read');
section = -1;
}
// if after first section
else {
$('h2').each(function(){
var sectionTop = $(this).offset().top;
if(currentPosition >= sectionTop) {
points.removeClass('reading');
points.eq(sectionIndex).addClass('reading');
points.eq(sectionIndex).addClass('read');
section = sectionIndex;
}
else {
points.eq(sectionIndex).removeClass('read');
}
sectionIndex++;
});
}
// bar
var barWidth = 0;
// if before start
if(section == -1) {
var point = points.eq(0);
barWidth = point.offset().left + (point.width() / 2);
}
// if after end
else if(section >= (points.length - 1)) {
var point = points.eq((points.length - 1));
barWidth = point.offset().left + (point.width() / 2);
}
// if within document
else {
var startPoint = points.eq(section);
var startPointX = startPoint.offset().left;
var startPointWidth = startPoint.width();
var startSection = $('h2').eq(section);
var endSection = $('h2').eq(section+1);
var startSectionY = startSection.offset().top;
var endSectionY = endSection.offset().top;
var sectionLength = endSectionY - startSectionY;
var scrollY = currentPosition - startSectionY;
var sectionProgress = scrollY / sectionLength;
barWidth = startPointX + (startPointWidth / 2) + (startPointWidth * sectionProgress);
}
barWidth -= indicator.offset().left;
indicator.css('width', barWidth+'px');
}
}
setPosition();
$(window).scroll(function(){ setPosition(); });
$(window).resize(function(){ setPosition(); });
// on click, scroll to target section
points.click(function(){
var sectionIndex = points.index($(this));
var targetY = $('h2').eq(sectionIndex).offset().top - (triggerPoint * .92);
$('html, body').animate({scrollTop:targetY}, 600, 'easeInOutCubic');
});
});
Also see: Tab Triggers