Introduction to Progressive Enhancement

Habdul Hazeez - Jan 20 '20 - - Dev Community
_This post was originally published on October 2nd, 2019. Edited and Published to fit the theme of this series_

Most websites content are served with a combination of HTML, CSS and JavaScript. Your design and coding decision that ensure the content is presented in a usable and accessible form is one of the tenets of progressive enhancement.

It all starts by writing code that's guaranteed to run in most browsers and enhancing it with code that might not run in all browsers, and irrespective of your users browser, they will get the baseline experience and the content they came for.

We took this approach in the layout example when we talked about responsive web design. We started with a mobile viewport and then used media queries to progressively enhance the layout within different viewport.

Progressive enhancement is about changing your mindset and approach when building websites or web applications. One of the best way to understand is through practical examples.

Let's dive in.


We'll show how we can take a progressive enhancement route when building with JavaScript and CSS.

FOR JAVASCRIPT

Lets take an hypothetical situation that you have a form on your blog that allow users to submit comments to your blog post, it has form inputs for the name, email and a WYSIWYG editor which allows the user to submit code snippets.

Most WYSIWYG editor are coded in JavaScript, but what happens when your user access your website with JavaScript turned off in their browser? They will have no idea they can submit a code snippet along with their comments (unless they've visited your website before).

Save the following HTML:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Progressive Enhancement</title>
    <link rel="stylesheet" href="form.css">
</head>
<body>
    <h2 class="comment-heading">Add a Comment</h2>
    <form class="comment-form" action="" method="post" id="commentform">
        <fieldset>
        <div class="form-group">
          <label for="name" class="form__label">Name:</label>
          <input type="text" name="name" class="form__input" id="name" required>
        </div>

        <div class="form-group">
          <label for="email" class="form__label">Email:</label>
          <input type="email" name="email" class="form__input" id="email" required>
        </div>

        <div class="form-group w-100">
          <label for="comment" class="form__label">Comment:</label>
          <textarea name="comment" class="form__textarea" id="comment" </textarea>
        </div>

        <input type="submit" name="submit_comment" value="Submit Comment" class="form__button">
        </fieldset>
    </form>

<script src="tinymce/tinymce.min.js"></script>
<script>
    tinymce.init({
        selector: '#comment',
        theme: 'modern',
        height: 300,
        autoresize_bottom_margin: 20,
        autoresize_max_height: 500,
        autoresize_min_height: 325,
        plugins: [
            'advlist anchor autolink autoresize link spellchecker autosave',
            'code',
            'codesample code save'
        ]
    });
</script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Taking a closer look at the code i have referenced a script that's used for the WYSIWYG editor which is TinyMCE, download a local copy of TinyMCE to your current working directory and update the value of the src in your <script> e.g "your_current_working_directory/tinymce/tinymce.min.js".

Create a CSS file and save the following:

/**
  * CSS rules for styling the form
  */
.comment-heading {
    text-align: center;
}

.comment-form {
    margin-bottom: 1em;
    width: 100%;
}

.comment-form__noscript {
    display: block;
    margin-top: 0.8em;
}

@media screen and (min-width: 48em) {
    .comment-form {
       width: 60%;
       margin: 0 auto;
    }
}

.form__label,
.form__input,
.form__textarea {
    display: block;
    width: 100%;
    margin-bottom: 0.5em;
    padding: 0.3em;
}

.form__textarea {
    height: 13em;
}

.form-group.w-100 {
    margin-bottom: 1em;
}

.form__button {
    background-color: #1560bd;
    border: 0;
    color: #ffffff;
    font-family: "Trebuchet Ms", serif;
    margin: 0 auto;
    padding: 0.5em;
    width: 50%;
    display: block;
}

.form__button:hover {
    background-color: hsl(53.2, 4%, 41.2%);
    cursor: pointer;
    font-weight: bold;
    box-shadow:  0 2px 3px hsl(53.2, 4%, 41.2%);
}
Enter fullscreen mode Exit fullscreen mode

Load the HTML file in your browser, and if you have JavaScript enabled you should get an output similar to the image below:

A form

And if you click on the Insert tab, you will know you can submit a code snippet with your comment:

A form with insert tab clicked

But what happens when the user has JavaScript disabled? There will be no indication that code snippets can be submitted:

A form with JavaScript Disabled

With just a few lines of code, we can fix this. First there should be an information just below the textarea telling the user that they can submit code snippets with their comments.

By default this information will be hidden by JavaScript and if the user browser has JavaScript disabled they will see the information.

Copy the code below an paste just below the textarea element in the form. Then save your file.

<i class="comment-form__noscript" id="comment-form__noscript">
Javascript is disabled in your browser. To submit a code snippet
along with your comment use a <code>pre</code> tag with a class
of language-(programming-language) and wrap your snippet
with html <code>code</code>
tag. e.g<pre>&lt;pre class="language-javascript"&gt; &lt;code&gt;var i = 1;&lt;/code&gt;
&lt;/pre&gt;</pre>
Replace 'javascript' in the class name with
either html, css or php. e.g language-css,
language-html or language-php</i>
Enter fullscreen mode Exit fullscreen mode

Update the code within the <script> tag with these two lines of JavaScript which hides the information from users that have JavaScript enabled. Place the code after the TinyMCE initialization code.

  // hide the form no script information
  let comment_form_noscript = document.getElementById('comment-form__noscript');

  // hide the information
  comment_form_noscript.style.display = 'none';
Enter fullscreen mode Exit fullscreen mode

Save your HTML and CSS file. Reload in you browser, if you have JavaScript enabled you will see the form with WYSIWYG editor.

Now let's disable JavaScript.

If you are using Windows™ you can access the Developer Tools in Firefox and Chrome using Ctrl + Shift + I or the equivalent command in macOS.

Click on Console and press the F1 key on your keyboard to access the console settings, scroll down you should see 'Disable JavaScript' under Advance settings.

Developer Console in FireFox Browser

In the current FireFox browser, clicking on the Disable JavaScript checkbox will automatically reload the page and in Chrome you'll have to manually reload the pageusing the Reload button or Ctrl + R on your keyboard.

When the page reloads, you should get an output similar to the image below, with the information displayed because JavaScript is disabled. Now the user knows they can submit code snippets with their comments.

A form with information on submitting code snippets

Other cases when the user might have JavaScript disabled:

1) If they are using the Opera Mini browser, which automatically strips out all scripts to increases the page load time

2) Using a proxy server that's configured to disable scripts.

FOR CSS

We demonstrated progressive enhancement when @media rules was used to enhance the layout across different viewport in the introductory post to responsive design.

The additional information we should discuss is the use of @supports feature to check if a browser will understand a particular CSS property. The basic usage is:

@supports(display: flex) {
    /* All the code here will run in browser that supports flexbox*/
}
Enter fullscreen mode Exit fullscreen mode

And if you are using a CSS property with limited support, be sure to provide a fallback code. Can I use is a resource that will definitely come in handy.

Mind you, these are just basic examples that demonstrates progressive enhancement.

The idea is to design your website for your users and making coding and design decisions that will not affect the usability and accessibility of your site's content.

Graceful degradation is related to progressive enhancement but different — often seen as going in the opposite direction to progressive enhancement. In reality both approaches are valid and can often complement one another (source).


Our next topic is more of theory and it's about User Interface Design.

I'll see you then.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .