Selective Content Loading

Share this article

One of the techniques we talk about in Jump Start Responsive Web Design is called Selective Content Loading (SCL). This technique is really useful in situations where you want to load small pieces of data into an already loaded page in a structured way. When would this be useful?

  • When you have serious bandwidth issues between your server and the end user’s device (for example, on a mobile connection that is moving on a poor network with lots of errors and having to deal with cell handoff).
  • When your pages are largely the same structurally from page to page and simply reloading the content saves many requests.
  • If you have chunked your content nicely and want to simply load in the next piece in the sequence (for example, infinite scrolling on a Twitter feed)
Some of these issues can be dealt with by good caching and using local storage and these should definitely be explored as good practices generally. However, even with smart asset caching you still require server round trips to retrieve a document, all the page HTML still has to be sent to the browser and then the browser still has to render the page. If your page has only added a couple of additional bits of data (for example, a tweet) or is only changing a small amount of content (for example, the details for a product) then SCL may be a good option for you. This doesn’t work in every circumstance and it also causes a number of possible issues with URLs, browser history and what content gets spidered on a “page” by search engines (if this important to you). Recapping our approach from Jump Start RWD, this is what we’re going to do conceptually:
  • On the first page request we’ll load up all of the page content including the site navigation, content layout, CSS and JS files as normal.
  • After the page has loaded we’ll override all of the links in our page to make them XHRs rather than a standard request for a document.
  • We’ll then process the response (the XHR response will only be the internal page content in JSON rather than the entire page) and overwrite the content that was in the page.
  • We can then use pushState() to modify our browser history (so the URL updates to something shareable and we can go backwards if needs be).
Here’s an example that should illustrate the point simply. The content has been truncated purposefully in order to keep this concise. We’re going to set up a page that can load content about books without having to reload the entire page, just the pertinent content. We’ll also use pushState() from the History API to ensure that if the user wants to share or come back to the URL they’ll be able to do so. To make things simple to express, we’re going to use jQuery for the DOM manipulation and a JavaScript templating library called Handlebars.js. If you haven’t checked out JavaScript templating options and what they can do, Handlebars is an excellent choice to get your feet wet. The core of our solution relies on the fact that URLs can respond differently depending on whether they are an XHR or a normal HTTP request. If the server gets a normal request then the view will deliver the full HTTP response (containing all the document and then the JS, CSS etc). If the server gets an XHR, it will respond with JSON which only contains data about the book requested. So, as an example, the standard HTTP response for the “Frankenstein” page looks like this:
<!DOCTYPE html>
<html>
<head>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
 
var original = null;
var backtostart = true;
 
  <script type="text/javascript">
      ($(document).ready(function() {
          var source = $("#story-template").html();
          var template = Handlebars.compile(source);
 
          var story_link_handler = (function(evt) {
              evt.preventDefault();
              $.get(this.href, function(data) {
                  $("#contentarea").html("");
                  $("#contentarea").html(template(data));
                  history.pushState({url:data.location}, data.title, data.location);
              }, "json");
          });
 
          $("ul#storylist li a").bind("click", story_link_handler);
 
          $(window).bind("popstate", function(evt) {
              if (event.state) {
                  url = event.state.url;
                  $.get(url, function(data) {
                      $("#contentarea").html("");
                      $("#contentarea").html(template(data));
                  }, "json");
               backtostart = false;
              } else {
               if (! backtostart) {
                  backtostart = true;
                      $("#contentarea").html("");
                      $("#contentarea").html(original);
               } else {
                 original = $("#contentarea").html();
                    backtostart = false;
               }
            }
          });
 
      }));
  </script>
</head>
<body>
  <ul id="storylist">
      <li><a href="mobydick">Moby Dick</a></li>
      <li><a href="gulliverstravels">Gulliver's Travels</a></li>
      <li><a href="frankenstein">Frankenstein</a></li>
  </ul>
  <div id="contentarea">
      <article id="story">
          <h1>Frankenstein</h1>
              <h2>Mary Shelley</h2>
              <p>Doctor creates artificial life</p>
          </article>
      </div>
<script type="text/javascript" src="handlebars.js"></script>
      <script id="story-template" type="text/x-handlebars-template">
      <article>
          <h1>{{title}}</h1>
          <h2>{{author}}</h2>
          <p>{{synopsis}}</p>
      </article>
      </script>
  </body>
</html>
NB you can download code used in this article in a zip file linked at the end of this article However, the equivalent JSON response for an XHR will look like this instead:
{
  "location": "/frankenstein",
  "title": "Frankenstein",
  "author": "Mary Shelley",
  "synopsis": "Mad doctor creates artificial life"
}
All the code required to make the selective loading work is requested and loaded in the first request. After that, we only get the data and then load it into the template. Let’s take a look at how the code works.
  <script id="story-template" type="text/x-handlebars-template">
      <article>
          <h1>{{title}}</h1>
          <h2>{{author}}</h2>
          <p>{{synopsis}}</p>
      </article>
  </script>
NB you can download code used in this article in a zip file linked at the end of this article Handlebars uses a script element to create a template for what an article looks like (this content won’t be rendered by the browser as it won’t take an action on its type). Variable locations are defined using {{variable}} syntax. You can do a lot more with Handlebars (conditionals, loops, block execution etc) that we aren’t using in this instance though. Note the ID for the script, we need this so we can pass it into the Handlebars template compiler. In our document ready function, we grab the HTML from the template script tag we defined above and then we compile it into a template object we can use with new data later.
  var source = $("#story-template").html();
  var template = Handlebars.compile(source);
Next, we define a function we can use for our link onclick event handler. Here we’re simply stopping the actual request to the file by preventing its default behaviour. From there we make a jQuery XHR that returns JSON to the URL that was defined in the link’s HREF
attribute.
  var story_link_handler = (function(evt) {
      evt.preventDefault();
      $.get(this.href, function(data) {
          $("#contentarea").html("");
          $("#contentarea").html(template(data));
          history.pushState({url:data.location}, data.title, data.location);
      }, "json");
  });
When the response comes back, we simply overwrite the div content area that holds all our book data.
$("#contentarea").html(template(data));
We also use pushState() to push the URL we just requested onto the browser history so we can go backwards using the back button.
history.pushState({url:data.location}, data.title, data.location);
That’s not quite the whole picture with pushState(), though, in order for it to “just work” for the user. We next create a popstate event handler on the window so that when the user hits the back button we can update the content with the appropriate data for the book. In this case we’re going and getting the data again using an XHR. With pushstate, it’s possible to store data in a state object. In our case the amount of data is small and it’s bad practice to load up the user’s browser with additional data (especially on mobile) so only do it if you can guarantee it’s a tiny amount.
  $(window).bind("popstate", function(evt) {
      if (event.state) {
          url = event.state.url;
          $.get(url, function(data) {
              $("#contentarea").html("");
              $("#contentarea").html(template(data));
          }, "json");
      }
  });
One of the things we need to consider with this technique is what happens when the browser gets back to the start of the list. That is, you’ve popped all of your XHRs off the stack and you’re back to where you started. To remedy this, we use a flag to determine if we’re back to the start or not and we save the content that was in #contentarea so we can replace it. You can use other techniques such as simply hiding the original content area or storing the original document’s JSON. We then update the popstate event to check if there’s no event.state. If so, we revert to our original form.
$(window).bind("popstate", function(evt) {
              if (event.state) {
                  url = event.state.url;
                  $.get(url, function(data) {
                      $("#contentarea").html("");
                      $("#contentarea").html(template(data));
                  }, "json");
               backtostart = false;
              } else {
               if (! backtostart) {
                  // revert the content to the original
                  backtostart = true;
                      $("#contentarea").html("");
                      $("#contentarea").html(original);
               } else {
                 // store original content to retrieve later
                 original = $("#contentarea").html();
                    backtostart = false;
               }
            }
          });
Finally, we add our click event handler to all the relevant links. In our instance, we’re just using the links in the list, but in practice you could do this to a whole range of links based on class or HREF attributes.
$("ul#storylist li a").bind("click", story_link_handler);
The rest of the page is the page structure and the actual content that was requested – in this case the /frankenstein URL. As can be seen, this approach gives us a nice, responsive setup. The initial page request is a little heavier (in this case about 1Kb) but provides all of the scaffolding needed to layout the page and provide the interactions. Subsequent requests get the benefit of only having to return very small snippets of data, which are then loaded into the template. The URL is updated using pushState() which means the user can still share the URL using intents or copy and paste and that URL will work properly for whomever it is shared with. You also get the benefit that each document still exists properly – this means search engines can still correctly index your site, if that’s needed. One of the things we need to be careful of with this technique is that if we have content that exists in many different templates, the benefits from only loading the snippets of data via XHR will be destroyed by having to load all of the different content templates into the first page request and masking it from the user until it’s used. Don’t forget, all of the HTML still has to be loaded, regardless of whether it’s used or not. Where this technique works particularly well is in an “infinite scroll” scenario such as a stream of content or very long article. The content type doesn’t change almost at all (or only within a very defined way)—this technique does for “page content” as a whole what the lazy loading technique does for images within a page. If you’ve taken the time to chunk your content, this can be especially effective as it means you can avoid the user hitting “goto page 2” even though search engines will follow happily. Download code files used in this article Delve further into the world of responsive web design in Andrew’s new book with Craig Sharkie: Jump Start Responsive Web Design.

Frequently Asked Questions on Selective Content Loading

What is Selective Content Loading and how does it improve website performance?

Selective Content Loading is a technique used in web development to enhance the performance of a website. It involves loading only the necessary parts of a webpage initially and then loading the rest of the content as needed. This method reduces the initial load time of a webpage, providing a faster and smoother user experience. It’s particularly beneficial for websites with heavy content or those accessed by users with slower internet connections.

How does Selective Content Loading differ from Lazy Loading?

While both Selective Content Loading and Lazy Loading aim to improve website performance, they work in slightly different ways. Lazy Loading delays the loading of non-critical or non-visible content until it’s needed, such as images below the fold. On the other hand, Selective Content Loading involves loading only specific parts of a webpage based on certain conditions or user actions, which can include scripts, stylesheets, or other content.

How can I implement Selective Content Loading on my website?

Implementing Selective Content Loading involves identifying the critical and non-critical parts of your webpage. Critical content is loaded first, while non-critical content is loaded as needed. This can be achieved through various methods, such as using JavaScript to load content based on user actions or using CSS media queries to load content based on device characteristics.

What are the potential drawbacks of Selective Content Loading?

While Selective Content Loading can significantly improve website performance, it may also introduce complexity in website development and maintenance. It requires careful planning and testing to ensure that all content loads correctly under different conditions. Additionally, if not implemented correctly, it could potentially lead to issues with SEO as search engines may not be able to crawl and index all content.

Can Selective Content Loading affect my website’s SEO?

If implemented correctly, Selective Content Loading should not negatively impact your website’s SEO. However, it’s important to ensure that all content is accessible to search engines for crawling and indexing. This may involve using progressive enhancement techniques or providing alternative content for search engines.

Is Selective Content Loading suitable for all types of websites?

Selective Content Loading can be beneficial for many types of websites, particularly those with heavy content. However, it may not be necessary or beneficial for all websites. For simple websites with minimal content, the performance benefits may not be significant enough to justify the added complexity.

How does Selective Content Loading affect user experience?

Selective Content Loading can significantly enhance user experience by reducing webpage load times. This can lead to increased user engagement and lower bounce rates. However, it’s important to ensure that the implementation of Selective Content Loading does not disrupt the user experience in other ways, such as causing content to load unexpectedly or inconsistently.

Can Selective Content Loading be used with other performance optimization techniques?

Yes, Selective Content Loading can be used in conjunction with other performance optimization techniques, such as minification, compression, and caching. These techniques can further enhance the performance benefits of Selective Content Loading.

How can I test the effectiveness of Selective Content Loading on my website?

You can use various tools and techniques to test the effectiveness of Selective Content Loading. This can include using browser developer tools to measure webpage load times, using website speed test tools, or using A/B testing to compare the performance of different implementations.

Are there any resources or tools available to help with implementing Selective Content Loading?

There are many resources and tools available to help with implementing Selective Content Loading. This can include tutorials, guides, and libraries available online, as well as tools built into many web development frameworks and content management systems.

Andrew FisherAndrew Fisher
View Author

Andrew loves playing with technology, especially at the intersection of the web, mobile tech, ubicomp, and data. He has been creating digital solutions globally since the dawn of the Web for brands including Nintendo, peoplesound, Sony, Cotton On, the Melbourne Cup, and Optus. Andrew is the CTO for JBA, a data agency in Melbourne, Australia,

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week