Rearranging DOM to optimize page load speeds

Posted by admin at April 6, 2017

Balancing optimum UI/UX design that meets requirements with minimal page load speeds is always a major point of consideration for the front-end designer.

On one end, the designer tries to achieve the exact specifications of the web application being developed (e.g. where to place a button or a menu, how many menu items to load once) and on the other end, the pages should be designed to be responsive and also have minimal load times (here we are faced with the questions: whether to use asynchronous calls or not, whether to hide contents with show/hide toggle links). And loading pages in slow internet connections amplifies the need to strike this delicate balance.

One of the ways of I try to achieve this balance, involves toying around with the DOM elements and throwing in some JavaScript magic to ensure that the most-wanted or most-used features are loaded first, are completely responsive to user input.

ILLUSTRATION:

As an example, here is a code segment from a project I was working on (an online library of sorts)


<div id="left_panel">
    <!-- panel that contains the table of contents (sluggish) -->
    <?php for ($i=0; $i<count($res); $i++) { ?>
        <a href="javascript:;" onclick="load_values_into_right_panel(<?php echo $i; ?>);">
            <?php echo $res['article_title']; ?>
        </a>
    <?php } ?>
</div>
<div id="right_panel">
    <!-- panel that contains the body of the article and hence loads very fast -->
</div>

The Design: The basic design of the webpage is made up of two panels: the table of contents on the left and the body of the selected article on the right. A user clicks on an article title in the table of contents in the left panel and JS loads up the value in the right panel.

The Problem: The table of contents had to load a very large of items. For a library with thousands of articles or sections of articles, the page would be loading for a long time. Also, I noticed that the user would be more interested in the Article Body section and the since the this section is on the right (HTML pages are loaded top to bottom, left to right), the page is blank for a number of agonising seconds.

Techniques:

  1. Paginating the number of articles in the table of contents
  2. Showing only the parent sections or chapters of articles instead of the actual article titles to decrease the number of items loaded. However, this technique would loose its effect if the total numner of chapters runs into the hundreds. The page would be loading the table of contents panel for while.
  3. Rearranging the DOM in such a way that the article body (on the right) is loaded first, while the left side gradually loads.

Lets Code:

Below is how the code segments looked:


<div id="left_panel">
    <!-- panel that contains the table of contents (sluggish) -->
    <?php for ($i=0; $i<count($res); $i++) { ?>
        <a href="javascript:;" onclick="load_values_into_right_panel(<?php echo $i; ?>);">
            <?php echo $res['article_title']; ?>
        </a>
    <?php } ?>
</div>
<div id="right_panel">
    <!-- panel that contains the body of the article and hence loads very fast -->
</div>

Solution: Using the third technique, we want contents of the “left-panel” to be loaded AFTER the “right_panel”. So what we can do is to create a new div container after the right_panel div, move the div contents of the left_panel in it and then replace the contents of the left_panel with a loading icon.


<div id="left_panel">
    <!-- loading icon -->
    <img src="path/loading.gif" /> loading please wait...
</div>
<div id="right_panel">
    <!-- panel that contains the body of the article and hence loads very fast -->
</div>
<!-- create a new div container after the right_panel div -->
<div id="left_panel_hd" hidden>
<!-- moved from the left_panel div -->
    <?php for ($i=0; $i<count($res); $i++) { ?>
        <a href="javascript:;" onclick="load_values_into_right_panel(<?php echo $i; ?>);">
            <?php echo $res['article_title']; ?>
        </a>
    <?php } ?>
</div>

Now we call on javascript to move the contents of the new container “left_panel_hd” back to the old container “right_panel”, after it has been fully loaded. The code segment below does the trick:


<script>
function reloc_toc()
{
    // move the contents from the placeholder to the left_panel
    left_panel.innerHTML = left_panel_hd.innerHTML;
    
    // clear the contents of the placeholder container
    left_panel_hd.innerHTML = '';
}
</script>

Next we call this function after the placeholder is loaded.


<div id="left_panel">
    <!-- loading icon -->
    <img src="path/loading.gif" /> loading please wait...
</div>
<div id="right_panel">
    <!-- panel that contains the body of the article and hence loads very fast -->
</div>
<!-- create a new div container after the right_panel div -->
<div id="left_panel_hd" hidden>
<!-- move the div contents of the left_panel in it -->
    <?php for ($i=0; $i<count($res); $i++) { ?>
        <a href="javascript:;" onclick="load_values_into_right_panel(<?php echo $i; ?>);">
            <?php echo $res['article_title']; ?>
        </a>
    <?php } ?>
</div>
<script>reloc_toc();</script>

What the code modifications we have made does is to first load light DOM elements

  • the left panel with only a loading gif in it (left_panel)
  • and the right panel containing the body of the article (right_panel)

This is shown on the page while the heavier elements are loading in the hidden placeholder container left_panel_hd. When this placeholder container is completely loaded the Javascript function reloc_toc(); then populates the left_panel with the contents of the placeholder container.

Gradual Pagination:

For some conditions, the placeholder container itself might also take a longer time to load, leaving the left panel in loading gif limbo forever. To solve this, we can combine a form of gradual pagination, where reloc_toc() function transfers content from the placeholder to the left panel, either one by one or in smaller batches.


<div id="left_panel">
    <!-- loading icon -->
    <img src="path/loading.gif" /> loading please wait...
</div>

<div id="right_panel">
    <!-- panel that contains the body of the article and hence loads very fast -->
</div>

<!-- create a new div container after the right_panel div -->
<div id="left_panel_hd" hidden>
<!-- move the contents of this div to the left_panel -->
    <?php for ($i=0; $i<count($res); $i++) { ?>
        <a href="javascript:;" onclick="load_values_into_right_panel(<?php echo $i; ?>);">
            <?php echo $res['article_title']; ?>
        </a>
        <!-- for each loop, load the new result into the visible div ONE BY ONE-->
        <script>reloc_toc();</script>
    <?php } ?>
    <script>
         // remove the hidden div or clean it up left_panel_hd
         left_panel_hd.innerHTML = '';
    </script>
</div>

Now, I know a few lines of code in AngularJS can solve this effectively. This tutorial is just a plain JavaScript translation of how I understand the problem and also provides a better understanding of how the front-end (JS) and the back-end (PHP) components, fit into the solution.

   0 likes

Suggested Read