Table of Contents
In web design and development there are two terms you should be familiar with. First is graceful degradation. The second is progressive enhancement. These two are like yin and yang or water and fire. The cannot coexist next to each other. You can choose the first or the second one and I hope this post will help you understand why progressive enhancement is better solution and decide faster.
What is progressive enhancement
Graceful degradation is about building your website so it provides a certain level of user experience in newer browsers and than it degrade to a level where it provide users with the basic functionality. Progressive enhancement does things the other way round. When you start, you create a basic level of user experience that all browsers will support. Then, you continue by implementing more advanced functionality that will be available only to more modern browsers.
Great way to put it is to quote Christian Heilmann: “Progressive enhancement is about building robust products and being paranoid about availability. It is about asking “if” a lot. That starts even before you think about your interface.”
“Progressive enhancement is that it works very well with the “ship early, ship often” approach.”
Why to use progressive enhancement
After taking a look under the hood of progressive enhancement, let’s discuss some benefits that will make it easier for you start using it. The first one is the one often mentioned … It opens your website to users who disable JS. Another benefit is testing your website for failure by disabling JS along with using an integration tests. It also helps you prepare “fall back” when some features fail. When feature fails, there is no automatic revert to some default or original state. Progressive enhancement will help you test these cases.
Another benefit of progressive enhancement is that it works very well with the “ship early, ship often” approach. When you start with a rock-solid foundation, you are able to ship projects that work and then concentrate on adding more features and fancy stuff at a more appropriate time. These types of projects are also much easier to maintain. It enables you to concentrate on more complex interactions without worrying about the foundation.
Let’s also mention that progressive enhancement is good for your users. Following this principle you give them the security and assurance of knowing they can visit your website using any of the thousands of user-agents available to them and still interact with your content as that agent allows.
Now something for mobile users … Progressive enhancement prevents battery drain on your device. The goal is to have the same (similar) result at end no matter what technology (JS or CSS and HTML) will you use. The biggest benefit of all is that using progressive enhanced to build a website is as easy as not using it. So, prepare the “fall back” with plain HTML and style it with CSS first. Then, you are free to hide it (remove it) with JavaScript and create more dynamic and interactive feature, for example infinite scrolling instead of pagination.
“Progressive enhancement in its basic form means to start with the most basic thing and check every step on the way if we are still OK to proceed”
How to use progressive enhancement
The best way to think about progressive enhancement in web development is to think about three separate layers. The first layer contains clean and simple HTML code. There is literally nothing to break and even the first browser will render it properly (maybe not HTML5). This layer will also make it accessible for screen-readers, speech-based, very old and robotic browsers to navigate the content of your website properly. This will be the basic foundation.
The next, second, layer will contain CSS styles. At this stage you can be more creative and use newer features and fancier things. However, you should still keep in mind that some of the modules of CSS3 are not fully supported and new are coming. So, the best is to start with properties from CSS 2.1 and then continue to CSS3. This will allow visual-based browsers to render the visual representation of your website and its content.
The third and last layer is all about JavaScript. In this layer you can add any dynamic behavior and replace the “fall backs” created in previous two layers since they will still work without JavaScript. This will allow you to offer more interactive and enhanced usability of your website to the users with browsers supporting those features.
Progressive enhancement example
The easiest and most usable example of progressive enhancement in practice can be a form handling via AJAX. The form will contain two inputs – one for name (full name) and one for email address. Next, it will contain textarea for message, two radio buttons for basic robot and spam check, note about required fields and finally submit button. For typography I will go with Roboto font hosted on Google. This is basically the simplest, and kind of safe, form.
Also, don’t forget to include the action and method attributes for form element. The value of action attribute will be the path to your file with PHP that will handle the form. Value of method attribute will be “POST” – we will send data to the server, not receive (GET method). By the way, this HTML is the first layer of the progressive enhancement – the foundation.
HTML:
<form id="contact-form" action=”form.php” method=”POST”> <div class="form__details"> <input name="name" type="text" placeholder="Full Name" required> <input name="mail" type="email" placeholder="Email Address" required> </div> <div class="form__message"> <textarea name="message" id="message" cols="30" rows="4" placeholder="Your Message" required></textarea> </div> <div class="form__robot"> <input id="robot" class="robot-radio" type="radio" name="robot-radio" value="robot" checked> <label for="robot">I'm robot.</label> <input id="human" class="robot-radio" type="radio" name="robot-radio" value="human" required> <label for="human">I'm human.</label> </div> <span class="text--muted"><i class="fa fa-info-circle"></i> All fields all required.</span> <div class="form__btn"> <button class="js-form-btn btn btn--contact" type="submit" value="Submit Message" role="button">Submit Message</button> </div> </form>
You can style the form in any way you want. For this example I chose more modernist, austere and Bauhause inspired look with simple, dark grey and white color palette. The CSS styles below are written in Sass (SCSS), so don’t be surprised by some unknown functions or weird nesting. This will be the second layer of progressive enhancement.
SCSS:
.text--muted { font-family: "Roboto", arial, sans-serif; color: #666; } form { margin: auto; width: 100%; max-width: 370px; color: #333; } .form__details input, .form__message textarea, .form__robot, .btn { display: block; padding: 13px; font-family: "Roboto", arial, sans-serif; } .form__details input, .form__message textarea, .form__robot { width: 100%; border: 1px solid #ccc; } .form__details input { margin-bottom: 1em;} .form__message textarea {resize: vertical;} .form__robot {margin: 1em auto;} .form__btn {margin-top: 1em;} .btn--contact { margin: auto; font-weight: bold; text-transform: uppercase; color: #fff; background: #222; border: 0; box-shadow: 0 4px 8px #999; cursor: pointer; transition: all .25s ease-in-out; &:focus, &:hover { background: lighten(#222, 7%); box-shadow: 0 8px 8px #999; } }
The first two layers are on the scene and working so it’s time to bring some JavaScript to the game. In order to make the AJAX part easier, we will use jQuery and its ajax() method. The first step is to handle the robot check. We used checked attribute on radio for robot to prevent the form from submitting by robots. This will work great be we need to care about toggling this attribute when user will change it to human. This will be done using jQuery attr() and prop() methods and switching between true and false states.
jQuery:
$(".robot-radio").on("click", function() { $(".robot-radio").attr("checked", false).prop("checked", true); $(this).attr("checked", true).prop("checked", true); });
Next step is to handle the form submitting. We are going to watch for submit event on this form. Also, don’t forget to include parameter for function so we can prevent the default form submit. Then, the next step is to create an if statement checking the radio buttons created to stop robots from sending you nice emails. The condition will be simple, just checking for checked attribute. For true case include return false statement.
The else block will contain the parameter we used for function along with preventDefault() method to avoid sending the form. Right after this use the ajax() method. You need to setup the type that will be “POST”, url that will be PHP file, data where you will select the form and use jQuery serialize() method and, last, success callback with simple alert message to let user know that message has been sent. In the callback, you can also use reset() method to reset the form fields.
Note: You can either write the type and url manually or use attr() method and get the information from form element.
jQuery:
$(document).on("submit", "#contact-form", function(e) { if ($("#radioRobot").attr("checked")) { return false; } else { e.preventDefault(); $.ajax({ type: "POST", url: "contact.php", data: $("#contact-form").serialize(), success: function() { alert("Your message has been sent. Thank you!"); $("#contact-form")[0].reset(); } }); } });
You can see this example on codepen:
https://codepen.io/alexdevero/pen/zxgbva
or on my website.
Final words
The goal of progressive enhancement is to allow you to build projects your users can run under all conditions. We should not block or limit some users just because the technology the use. Remember, everyone deserves the access. The web is not for anyone, it’s for everyone.
What are your thoughts on progressive enhancement and graceful degradation?