Pen Settings



CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

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.

+ add another resource


Babel includes JSX processing.

Add External Scripts/Pens

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.

+ add another resource


Add Packages

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.


Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.


                <h1>Reading Progress Bar CSS Only</h1>
<p class="zoom-area"><b>CSS</b> indicator to display the current reading position (how much you have "read", depending on how far you have scrolled down an article). <b>Scroll me!</b></p>
<section class="example-post">
  <div class="entry-content">
    <h2>Example Post</h2>
				<p>Lately webmaster and web designer are obsessed about <a href="">User Experience</a> and how to improve it. Tasks such as reducing the website loading time or finding <a href="">a good font combination</a> are always in the to-do list. However we are forgetting about focussing on the <strong>elements where the real contact between the user and the website happens: the forms.</strong></p>
<p>Designing pages and sections with contact forms properly is challenging because <strong>you have to guide your users through each field</strong> to get them filled correctly. Moreover, if the info added by the user doesn’t fit the field’s pattern, you should let the user know what he/she is doing wrong. And this has to be clear for all users, included non-tech visitors.</p>
<p>Fortunately, <a href="">new HTML5 specs</a> for forms have helped to improve the validation before sending the form without using server-side requirements nor JavaScript. By default inputs type like email or tel (telephone) use a pattern that checks that the info filled is correct and forms can be submitted when the user clicks on the submit bottom.</p>
<p>The key questions are: Could we improve this behaviour getting a live check? Could we also get an extra info about how to fill out a form if we get stuck? Does this help get a better UX? Yes to all, and we will do it with <a href="">CSS</a>.</p>
<h2>Knowing CSS pseudo-class and HTML elements and attributes to improve a form</h2>
<p>Let’s revise some <strong>CSS pseudo-class and HTML elements</strong> we are going to use in our demo. Some of them are very well-known but others have been added recently in the last CSS updates.</p>
<h3>input and textarea</h3>
<p><strong>The classics</strong>. They will define the fields the users are going to fill out. The typology of <code>input</code> is defined by the <code>type</code> attribute in the HTML, and this is important, as we said above, for custom HTML5 browser validation</p>
<p>This HTML attribute can be used with <code>input</code> and <code>textarea</code>. It indicates that the field should be filled out before the form is submitted. It is very useful to let user know that we need that information, for example the email or the phone number.</p>
<p>The required attribute is directly related with two pseudo-classes we can use through our CSS to know if the <code>input</code> is required or optional. They are <strong>:required</strong> y <strong>:optional</strong>, vary semantic as you can see.</p>
<p>Another HTML attribute to check the information added by users. In that case <strong>we can build our own pattern or use one of the patterns by default</strong>. It depends on the type attribute. For example, if we use the email type, it will looking for an email string (with @ in the middle and a valid domain extension such as .com, .org or whatever.) The same for tel or url. <a href="">Here</a> you have the complete list of <code>input</code> type attributes.</p>
<p>However, the power of this attribute is that we can create our own pattern, excluding numbers for instance or any character we want to avoid. The pattern attribute <a href="">requires a regular expression</a> in order to work properly.</p>
<p>The most useful attribute in this collection for UX. <strong>It helps user to understand what kind of info we are looking for</strong>. It can also display an example data that will disappear when the user starts filling out the <code>input</code> (typing a character) and not when the <code>input</code> is <code>:focus</code>.</p>
<p>Pseudo-element related with above attribute. <strong>It helps us style the placeholder</strong>, so we can change the text colour or other font properties to let users know that this is an example and not a real text.</p>
<p>Browser compatibility is good enough, however, we can add some alternative prefixed rules for each browser: <code>::placeholder</code>, <code>::-moz-placeholder</code>, <code>::-webkit-input-placeholder</code> and <code>:-ms-input-placeholder</code>.</p>
<p>A basic pseudo-class that runs when the user is focusing an <code>input</code> or <code>textarea</code>. It is necessary that the user click on it or navigate with the keyboard to considerate the <code>input</code> as focused.</p>
<p>This pseudo-selector will let us know if the string added in the <code>input</code> is correct and check with the pattern we have set. So basically we can style the <code>input</code> if the info is correct.</p>
<p>The opposite of valid. The question here is: What happens when no value is added to the <code>input</code>? Will it be <code>:valid</code> or <code>:invalid</code>? Well, the answers in that case depends on the <code>required</code> attribute. If it exists for that <code>input</code> and no value has been added, then is an <code>:invalid</code> element. Otherwise it will be <code>:valid</code>.</p>
<p>The new kid in town. It is still in the draft of CSS level 4 specification, but the compatibility with browsers <a href="">is quite reliable</a> at this moment (except on IE and Edge).</p>
<p>This is a pseudo-class that <strong>runs only when placeholder is being shown</strong>. It means that it will be enabled when the <code>input</code> is not focused and when it is focused but the user has not typed any character yet.</p>
<p>So the possibilities here are thrilled. Now, we can know if users get stuck in one of the inputs. For example, if an user has clicked on an <code>input</code> but doesn’t know what to write, we can show a notice after 5 seconds that helps the user complete it, and all of this <a href="">only with CSS</a>!</p>
<p>Another possibility: the user is filling the <code>input</code>, but 30 second has passed and the input is still invalid. Maybe the user has not understand what pattern we are looking for. Time to help with a message or something similar!</p>

</section><!-- .example-post -->
<div class="link-container">
  <a target="_blank" href="" class="more-link">Visit the original article</a>


                .example-post {
  position: relative;
  padding: 0;
  color: #7f8b90;
  border-top: 1px dotted #aaa;
  border-bottom: 1px dotted #aaa;
.example-post p {
  font-size: 18px;
  line-height: 1.5;
.example-post a {
  color: #607D8B;
.example-post:before {
    content: "";
    display: block;
  background: linear-gradient(to right top, #CDDC39 0%, #03A9F4 50%, #e6f0f5 50%);
    height: calc(100% - 100vh + 6px);
    width: 100%;
    position: absolute;
    top: 0;
    left: 0;
.example-post:after {
    content: "";
    display: block;
    background: #e6f0f5;
    height: calc(100vh - 6px);
    width: 100%;
    position: -webkit-sticky;
    position: sticky;
    bottom: 0;
    left: 0;
code {
    border: 1px solid #ccc;
    border-radius: 5px;
    padding: 3px 5px;
    font-size: 14px;
.entry-content {
    max-width: 790px;
    margin: 0 auto;  
    position: relative;
    z-index: 1;
    margin-bottom: calc(-100vh + 6px);
    padding: 0 15px;

/* demo stuff */
* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
body {
  background-color: #e6f0f5;
  padding-top: 40px;
  padding-bottom: 50px;
  margin: 0;
html, button, input, select, textarea {
    font-family: 'Nunito', sans-serif;
    color: #92a4ad;
h1 {
  text-align: center;
  margin: 30px 15px;
  font-size: 40px;
.zoom-area { 
  max-width: 650px;
  margin: 50px auto 70px;
  font-size: 24px;
  padding-left: 15px;
  padding-right: 15px;
  text-align: center;
.link-container {
  text-align: center;
a.more-link {
      font-size: 18px;
    font-weight: 700;
    background-color: transparent;
    padding: 10px 5px 0;
    border-radius: 0;
    color: #416475;
    display: inline-block;
    margin-right: 5px;
    margin-bottom: 5px;
    line-height: 1.5;
    text-decoration: none;
    margin-top: 50px;
    letter-spacing: 1px;
    border-bottom: 6px solid #92a4ad;


                // Nothing to do here