Pen Settings



CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource


Babel is required to process package imports. If you need a different preprocessor remove all packages first.

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


Save Automatically?

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.


<p>The form below demoes a pattern where each question has its own <strong>live region</strong>, which errors are inserted into.</p>
<p>Its <code>validate()</code> is set up to always return false. This is on purpose and just for the demo.</p>
<p>Some notes/tips:</p>
  <li>Make sure your error area is associated with your input (by putting it inside the label or by associating it with <code>aria-labelledby</code>)</li>
  <li>Best keep your labels short.</li>
  <li>You can also group your errors in one live region instead of having errors with each field.</li>
  <li>You can also group your errors at the top of the page, not use a live region and give the error area focus when someone tries to submit a form that has errors according to your script.</li>
<form action="">
  <div class="question">
    <label for="question-1" id="label-1">What is your name? <em>Note, when you leave the field an error will appear in an explicit live region (assertive)</em></label>
    <input type="text" id="question-1" data-error="That's not a name" aria-labelledby="label-1 error-area-1" />
    <div aria-live="assertive" aria-relevant="additions removals" class="error-area" id="error-area-1">
    <!-- insert error messages here -->
  <div class="question">
    <label for="question-2" id="label-2">Where do you live? <em>Note, when you leave the field, an error will appear in a role=alert, which should behave like a live region</em></label>
    <input type="text" id="question-2" data-error="That's not a city" aria-labelledby="label-2 error-area-2" />
    <div role="alert" class="error-area" id="error-area-2">
    <!-- insert error messages here -->
  <div class="question">
    <label for="question-3" id="label-3">How old are you? <em>Note, when you leave the field, an error message should appear in a live region (polite)</em></label>
    <input type="text" id="question-3" data-error="That's no a number" aria-labelledby="label-3 error-area-3" />
    <div aria-live="polite" class="error-area" id="error-area-3">
    <!-- insert error messages here -->
  <button type="button" id="button">Send in</button>



                body { font-family: sans-serif; } 
form { background: papayawhip; padding: 1em; }
label { display: block; margin: 1.5em 0 .5em; }
input, button { font-size: 100%; border: 1px solid darkgrey; padding: .5em; }
button { background-color: black; color: white; border: 0; margin: 1em 0; }
.error-area { color: darkred; font-style: italic; }



                // hugely simplified, this just inserts an error 
// any time you leave any field

var fields = document.querySelectorAll( 'input' );

[] fields, function( field ) {
  field.addEventListener( 'blur', function( event ) {
      handleError( );   


function validate( field ) {

  // your validation magic may be more complex 
  return false;


function handleError( field ) {

  if ( field.getAttribute( 'data-has-error' ) !== 'true' ) {

    var error = getErrorMessage( field );
    var question = field.closest( 'div' );
    var errorArea = question.querySelector( '.error-area' );

    if ( validate( field ) === false ) {

      errorArea.appendChild( error );
      field.setAttribute( 'data-has-error', 'true' );


function getErrorMessage( field ) {
  var message = document.createElement( 'p' );
  var messageContent = field.getAttribute( 'data-error' );
  message.textContent = 'Error: ' + messageContent; 
  return message;