On Your Marks, Get Set, Wait

I’ve modified the JavaScript for this section of my site over time, but have reflected the changes in the code snippets below.

Since the last re-design of my website, I decided to make the switch to Disqus for my commenting system. This comes with a couple of disadvantages but also with a few advantages.

Disqus © 2012.

In this article I’m going to run through how I manage my comments section from a front-end development perspective, with respect to user experience, performance, and accessibility.

The Cons of Disqus

  • The greatest disadvantage of using Disqus may or may not be obvious, but it means you’re locked into using Disqus for your comments. Disqus do offer importing and exporting options, but it’s not a guarantee that whatever commenting platform you want to move from or to will make for an easy, foolproof process.
  • It also used to be the case that you needed to have an account with Disqus in order to be able to make comments, but there is now an optional setting that owners can toggle enabling guests to make comments.
  • Another issue with Disqus that isn’t terribly relevant anymore today, outside the context of a few edge case users, is that Disqus relies on JavaScript to inject your comments and commenting form onto your page—users with JavaScript turned off won’t be able to comment. I imagine there are also some aggressive ad-block browser plugins which would disallow Disqus from loading, but they’re probably also an edge case. In the case that the user doesn’t have JavaScript turned on, a message is displayed using a noscript tag.
  • It’s beyond my knowledge how caching is affected by Disqus—whether or not it is cached, or available to be cached offline—but as the movement to bring offline support to the web ramps up, this could present an issue.

The Pros of Disqus

  • Once you’ve signed up for a Disqus account, you’ll be able to comment on every site that has implemented Disqus for their commenting system and allows comments from the public.
  • Disqus has nearly all the bells and whistles you could want for making comments:
    • threaded replies; mentions; notifications
  • Robust Administration tools
  • Automatic anti-spam filters, and ones you can customise yourself, including:
    • whitelist / blacklist; restricted words
  • Option to display related articles from your own blog or from other blogs using Disqus
  • Option to add targeted ads and monetise upon clickthroughs

The Weigh In

First, let’s look at some statistics for loading Disqus comments on page load:

  • 37% of an article page’s load time comes from loading Disqus
    • This was tested on my article, Let’s Look Back, which has more (heavy) images than any of my other articles—totalling nearly 1MB of image data—meaning that the percentage of load time dedicated to Disqus could get even higher on my more minimal articles.
  • 298kB of data comes from Disqus’ three servers used to load comments, which isn’t a hell of a lot—at least, when you compare it to a decent-sized image asset.
  • 40 requests are made from Disqus in order to display the comments section.

By and large, this isn’t a massive hit. But we can almost always make things faster. I think it comes down what content is important—most people don’t comment on my articles, which begs the question: do most people care about the comments? That’s a difficult question to answer, but I think the point to drive home is that most people seem not to need the comments section—they’re here to read the articles. Maybe that will change over time, but with a mobile first approach, it’s important to consider what constraints mobile users could be under; namely, poor Internet connection speed and low processing power. The number of users browsing on mobile phones and tablets has only escalated in recent years, and we should be able to cater to their needs in ways other than just building responsively.

You shouldn’t impede your users access to your content by requiring them to download things that do not support it. Related articles, comments etc, these are secondary to the content itself, so if the user wants to see that they’ll be happy to exchange a single click over more DB queries at run time, or additional HTTP requests and JavaScript interpretation. Essentially, build it progressively enhanced.

Justin Avery of Responsive Web Design

So what can we do to reduce the page weight and load time for a majority of users? We can conditionally load comments as and when a user wants them.

At My Signal, Unleash Hell

Let’s decide what the conditions are for loading the comments:

  1. The user has finished reading the article, gets to the bottom of the page, and wants to read the comments
  2. The user navigates to the page from a link that directs them to the comments (with #comments appended to the URL)
  3. The user clicks a link to the comments section from within the article itself (also by #comments being appended to the URL)

Let’s dive into some code. Here’s how I was loading Disqus non-conditionally:

(function(d) {
    var typekitTimeout = 5000;
    if( window.sessionStorage ) {
        if( sessionStorage.getItem('useTypekit') === 'false' ) {
            typekitTimeout = 0;
        }
    }
    var config = {
        kitId: 'bbn1puz',
        scriptTimeout: typekitTimeout
    },
    h = d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+"wf-inactive";if(window.sessionStorage){sessionStorage.setItem("useTypekit","false")}},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+="wf-loading";tk.src='//use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
})(document);

I didn’t want to reinvent the wheel, so I followed in the footsteps of others who have done the same thing. First I wanted to create an action for the user to perform if they reached the bottom of an article and want to dip into the comments, and did so with a button.

<button class="button--show-comments" id="js-show-comments" role="button" aria-pressed="false" disabled>
    <svg class="icon  icon--feather"><use xlink:href="#svg--feather" /></svg>
    <span class="disqus-comment-count" data-disqus-url="http://foo.bar">Leave a Comment</span>
</button>

And let’s create some associated JavaScript to create and hook onto our button and perform two actions: remove the button and load Disqus.

var commentsButton  = document.querySelector('#js-show-comments');

commentsButton.disabled = false;

commentsButton.addEventListener('click', function() {
    showComments();
});

function showComments() {
    commentsButton.parentNode.removeChild(commentsButton);
    commentsButton.removeEventListener('click', function(){});

    (function() {
        var dsq = document.createElement('script');
            dsq.type = 'text/javascript';
            dsq.async = true;
            dsq.src = '//' + disqusShortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
}

What we’re doing here is:

  1. Assigning our button to a variable
  2. Adding an click event listener to our button (which fortunately also works via keyboard commands)
  3. When the button is clicked, remove the button and load in our comments

Everything’s looking sweet so far, so let’s tackle the 2nd and 3rd conditions from above: watching for a hash change in the URL (pointing to #comment) or catching it when the page is loaded.

var commentsHash = ['#comment', '#disqus_thread'];

window.addEventListener('load', function() {
    updateFromHash();
});

window.addEventListener('hashchange', function() {
    updateFromHash();
});

function updateFromHash() {
    commentsHash.forEach( function(hash) {
        if( window.location.hash.indexOf(hash) !== -1 ) {
            showComments();
        }
    });
}

What we’re doing here is:

  1. Assign our hash value to a variable (because why not?)
  2. If the URL already contains our desired hash on page load, run the showComments() command
  3. If the hash changes in the URL after the page has loaded, and it matches our desired value, run the showComments() command

If you remember, the showComments() function removes the button we created before—we want to do the same thing if #comment is in the URL and we’re loading Disqus, as we don’t want or need users to be able to load comments twice; in fact, that would be completely the opposite of what we’re trying to achieve here!


Almost there! Let’s create a failsafe—if our button no longer exists when the showComments() function is run, that means we’ve already loaded the comments, so we shouldn’t do it again.

function showComments() {
    if( commentsButton !== null ) {
        commentsButton.parentNode.removeChild(commentsButton);
        commentsButton.removeEventListening('click', function(){});

        (function() {
            var dsq = document.createElement('script');
                dsq.type = 'text/javascript';
                dsq.async = true;
                dsq.src = '//' + disqusShortname + '.disqus.com/embed.js';
            (document.getElementsByTagName('head')[0] || document.  getElementsByTagName('body')[0]).appendChild(dsq);
        })();
    }
}

The Whole Nine Yards

Here’s the entire snippet of code for my comments section:

<button class="button--show-comments" id="js-show-comments" role="button" aria-pressed="false" disabled>
    <svg class="icon  icon--feather"><use xlink:href="#svg--feather" /></svg>
    <span class="disqus-comment-count" data-disqus-url="http://foo.bar">Leave a Comment</span>
</button>
<section id="comments" class="clear  comments">
    <div id="disqus_thread"></div>
    <noscript>Please enable JavaScript to view comments.</noscript>
</section>
var disqusShortname = 'chrisburnell';

We’ve met all the conditions we set when we embarked upon this task:

  1. Create a button to load the comments
  2. Load the comments if the page was navigated to with the #comment hash
  3. Load the comments if the user clicks an anchor to jump to #comment section

As we saw in the statistics of Disqus’ impact, these aren’t massive savings, but they’ll certainly help out some of my users whom I know are browsing on slow connections and slow mobile phones.


We still have a small thorn when it comes to users without JavaScript enabled. Of course, the noscript tag will display a message, Please enable JavaScript to view comments, but there’s no way for those users to view the comments. On the other hand, Disqus have discussion pages for each of your articles, but the URL isn’t predictable enough to print this URL with my CMS (Jekyll) dynamically; furthermore, these pages don’t work without JavaScript enabled anyway.

A List Apart has a pretty nice solution to this in the same vein as Disqus, but it works without JavaScript enabled, for example: this comments page. Maybe if Disqus was able to give a similar URL back in the case where JavaScript is disabled, but as it’s an external service, this doesn’t seem possible without JavaScript. https://disqus.com/comments/?url=https://chrisburnell.com/article/a-slice-of-heaven is a possible solution to a minor problem—let’s hope Disqus implements something like this soon.


Big thanks to Ben Walters, a JavaScript wizard and close friend of mine, for helping me achieve this solution.

Let me know, as always, down below (treat that link as a proof of concept) if you have any suggestions for improvements to my code or other ideas on the matter. ’Til next time!

🗓 published on
🗓 updated on
📚 reading length ~1750 words
🏷 tagged under
🔗 shorturl repc.co/a4YF1


Flyknife Comics Square Illusion