Home Uniquely NZ Travel Howto Pauline Small Firms Search
Mobile Friendly Responsive Web Site Design
Development Version

Overall Approach to making Our existing websites Responsive


Introduction

This page covers the continuing work to make our website into a truly Mobile Friendly Responsive Design and, in particular, to ensure it satisfies the Google Mobile-Friendly tests. Mobile devices (Phones and Tablets) have now overtaken Computers and laptops in importance for access to the internet. A 'Mobile First' technique where a design for mobile access is progressively enhanced as the accessing devices become more capable is the favoured approach for new sites. The bottom line however is that the site MUST pass the Google tools which simulate the Robots they use to evaluate whether the site is mobile friendly and responsive. The tool is at https://www.google.com/webmasters/tools/mobile-friendly and the current site fails on 3 of the 4 criteria and will move down the rankings as a result.

The main extra factors to be considered in creating a Mobile Friendly Responsive Web Site Design are:

The Viewport: Arguably the most important element in making a web site Mobile Friendly as opposed to Responsive is to make use of the Viewport information a mobile device provides. Many mobile devices have small screens but high resolutions. For example my Samsung Galaxy S3, a several year old design high end phone, has a pixel resolution of 1280 x 800 which is as high as many laptops and my A6 is 720 x 1480. The S10 has a staggering 1440 x 3040. The result is that web sites designed for laptops and desktops turn out to have un-readably small text on a mobile. Many mobile browsers try to mitigate this but usually without a lot of success. This is where the viewport comes in. If you include an extra meta tag in the header then, put simply, the browser provides dimensional information which has been adjusted to match its optimum size and scales to match. Use of the meta tag is one of the conditions to be met to pass the Google Mobile Friendly tool test.

Designing for a machine without windows: This was the first consideration we addressed. Many of our pages had pictures which opened a higher resolution version in a new 'popup' window when clicked. This does not work on most mobile operating systems and instead a new tab is opened which is much less desirable and more difficult to tidy up. Instead 'lightbox' type overlays are a much better solution and they also scale on small screens.

Designing for a touch sensitive screen: This also has several major impacts. Firstly I make considerable use of hover-over information to display further information, help and copyright notices. Secondly many of the links are close spaced and easy to touch the wrong one.

Designing for a wide variation in screen sizes and orientations. We have finally got to the Responsive Design part which I have left to last to emphasise that it only part of the story.


The approach was phased to obtain the maximum initial impact in a finite time. In our case the approaches used have to work with the minimum number of changes to existing pages as the combination of pcurtis.com and uniquelynz.com involves over 500 pages. This is the approach I actually adopted rather than the optimum one I would have adopted given 100/100 hindsight.

The final phase is to some extent an iterative process and is ongoing as both the refinement of specification of the actual existing design framework and the development and test of the tools was a progressive process. Various pages threw up extra problems and comprehensive trials of various tools and techniques on various operating systems and browsers and on a wide variety of existing pages raised a variety of issues that had to be addressed.

Diagnostic Information for Development

 

Phase 1 - Limiting the width of the pages

The first stage of modifying the web site design was to limit the maximum width of the display area. The decision was made to limit it to 960 pixels as that was half of a HD screen width of 1920. For aesthetic reasons I wanted to have a matched background outside the display area for each of the 6 areas of the site. The limiting of the width is easily carried out using a css and a few lines of code on each page. In fact the whole site can be changed with a single change in the css for the body and the code changes are only needed to display different backgrounds under the display areas and the rest of the page. The additions on the page are to add a class to the body tag and to enclose the rest of the page in a <div></div> tag with a class like this.

<body onUnload="tidy()" class="plaingreyback" >
  <div class="homelimitwidth960">
     ...html...
     ...html...
  </div>
</body>

The matching css for the 6 different areas of the web site follows:

body {
color: black;
font-family: Georgia,"Times New Roman",Times,serif;
max-width: 930px;
margin: 0 auto;
padding: 0px;
}

.plaingreyback{
background-color: #dddddd;
padding: 0px;
}

.greyback{
background: url("howto-std.jpg");
padding: 0px;
}

.homelimitwidth960{
max-width: 930px;
margin: 0 auto;
padding: 0px;
background: url("gallery/std-back.jpg");
}

.howtolimitwidth960{
max-width: 930px;
margin: 0 auto;
padding: 0px;
background: url("howto-std.jpg");
}

.pemclimitwidth960{
max-width: 930px;
margin: 0 auto;
padding: 0px;
background: url("ou-std.jpg");
}

.sflimitwidth960{
max-width: 930px;
margin: 0 auto;
padding: 0px;
background: url("gallery/marble.jpg");
}

.nzlimitwidth960{
max-width: 930px;
margin: 0 auto;
padding: 0px;
background-color: #f4fff4;
}

.srchlimitwidth960{
max-width: 930px;
margin: 0 auto;
padding: 0px;
background-color: #f0f0f0;
}

These changes have been already applied to most of the current pages on the web site and even those which have not been specifically modified have the width limited and are centred within the css for the body tag.

A number of variations can be applied within the basic concept of adding a class to the <body> tag and enclosing the whole of the remainder in a <div> tag

Phase 2 - Introducing Lightbox style Overlay Images.

The current web site makes extensive use of Popup windows to display images. The initial Howto Article on Popup Windows for Images is still one of the most popular I have written. What I set out to do was to be able to have a number of thumbnails (icons) on a page which open in a single correctly sized 'popup' Window when they were clicked and then remain in the background when one continued to browse down the page. If clicked again the window should return to the same place in the foreground or if another image is clicked it should replace the previous image and again return to the same place in the foreground. You would think this would be a common requirement and somebody would have implemented it using JavaScript. Surprisingly I could not find any proper examples of this to copy. My searches provided plenty of examples of opening Windows once for images but none which worked correctly when reusing the Window for the same or a new image and brought it back to be in view so I was forced to write my own or to be more correct a series of such popup handlers of increasing complexity as my requirements increased and other people asked me for various enhancements which were covered in Advanced JavaScript Popup Windows for Images That features more advanced techniques for Popup windows which will resize for different images, allow titles to be displayed and the background colour specified. Popup windows work very well with a reasonable size screen and an operating system/browser supporting multiple windows. On such a system it is difficult to beat and I have used it extensively on my web site where there are over 5000 images using it and it has been tested over a long period on Windows, Linux and Apple machines in many different browsers including Internet Explorer, Firefox, Opera, Chrome and Safari.

Popups do not work so well on the modern Smart Phones and Tablets with small screens and are based round a tabbed approach rather than implementing separate windows. This makes the approach very clumsy as every popup is opened in a new tab and the reloading and automatic closing does not work. The alternative is an approach with has tended to be called Lightbox which is a JavaScript technique used to display images and other web content using modal windows where the image is overlaid over the screen with the surround dimmed out. The overlaid window can be closed by clicking outside of it or by a close button usually a standard cross-cross. Ideally the image should display full size when there is space available and shrink to fit the space available. Lightbox was originally the name of a specific JavaScript plugin, written by Lokesh Dhakar. However, common usage of the term has evolved to encompass Lightbox-style JavaScript plugins and such effects in general. The technique is now used very widely because of its simple yet elegant style and easy implementation and, most importantly it works well on small screens. The disadvantage is that it blocks use of the main window whilst a popup can just be moved aside but still be visible. I am currently using the original Lightbox but other implementations allow one to show video, web content etc in addition to just pictures and even run slide shows.

It proved very easy to install Lightbox to make my initial tests. One just needs to download a zipped file from Lokesh Dhakar's Lightbox2 Site and extract 3 folders which need to be uploaded to the root of the web site. Each html file which has pictures using Lightbox to display needs three lines added to them head section after which there is just a single ' call' required for each picture - a thumbnail and a full image are required.

A typical head section with the three lightbox links in red looks like:

<!DOCTYPE html>
<html lang="en-GB">

<head>
<meta charset="utf-8">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="js/jquery-1.11.0.min.js"></script>
<script src="js/lightbox.min.js"></script>
<link rel="stylesheet" href="css/lightbox.css">

<script src="rbox.js" ></script>
<meta name="author" content="Dr P Curtis">
<meta name="description" content="Technical Support Article covering Mobile Friendly Responsive web site design">
<meta name="keywords" content="responsive, web, design, lightbox, mobile, Mobile First, Mobile Friendly, Responsive Web Design">
<title>Responsive Web Design</title>
</head>

Note the links to my own JavaScript and CSS files follow the jQuery and Lightbox links and the order of those links is also important.

Note that the above is for HTML5 ( <!DOCTYPE html>, <html lang="en-GB"> and <meta charset="utf-8"> statements) - Lightbox works better with HTML5.

The general advice is that the <meta name="viewport" content="width=device-width, initial-scale=1">

A typical direct call looks like:

<a href="img/img_1234b.jpg" data-lightbox="attribute1" data-title="Picture copyright P Curtis 2015"><img="2015/img_1234i.jpg style="width:160px;height:120:px;float:left;" alt="Picture copyright P Curtis 2015" title="Picture copyright P Curtis 2015"></a>

One just needs to add a data-lightbox attribute to any image link to activate Lightbox. If multiple images have the same data-lightbox attribute they are displayed as a set and one can move backawards and forwards through the set and the next and previous images are preloaded. The data-title is optional and displays a caption below the image.

The majority of images on my pages are standardised in size (160 x 120 thumbnails for 400 x300 or 600 x 400 full size popup/lightbox images) and inserted by a JavaScript function which dynamically writes on-the-fly the full HTML code into the page. This is because the code is very repetitive and the only information specific to each image is the image , title and alignment (floated left or right or centered in a table cell) so a typical call would be

<script>hpop('2015/img_1234.jpg','Picture copyright P Curtis 2015,'left')</script>

It initially looked as if the 'script calls' I use for my popups could remain the same and only the JavaScript function would need to be changed. This would mean the the changes on most of my pages would be small and most could be made by a couple of 'find and replace' edits. This seemed to work until I tested the shrinking to fit small windows as would be used on a mobile device an I found that feature seemed to required HTML 5 to work. I changed the Doctype so the page was set to use HTML 5 and everything seemed to be work in the usual browsers but when I came to validate the page the differences between HTML5 and HTML 4.01 Transient became more obvious. My fairly simple test page generated 57 HTML errors, and that did not include the dynamically written text for the popup calls which the validator did not see!

I decided to continue with carrying out the changes to the pages with scripted calls to images which involved adding three lines and changing the two links to use a different Javascript and css file in the <head> section and progressively change to HTML5 to realise their full potential on mobiles . The new functions are all very comprehensively covered in the latest article in the series Using Lightbox to Display Web Images and I am writing a page covering The Conversion to HTML5 so no more will be said here.

 

Phase 3 - Developing a fully Mobile Friendly and Responsive Design

1. Specifying the Current Structure and Framework of the Web Site and Development Decisions

Firstly we have to take into account that it is an existing web site and we do not want to go completely back to scratch. This means that the principle of designing Mobile-First is more difficult but we can modify use the basic philosophy to do a mobile design then work back to the existing design. The main principles are to do with navigation and display of images so lets try to specify the techniques used site wide. What follows is not static - it has been progressively developed over a period of months and may still be enhanced or have, hopefully minor, changes in direction.

The current framework has:

It is clear that some of the techniques do not exist on mobiles or machines with a small and/or touch sensitive screen. The obvious restrictions are:

Decisions resulting from mobile operating systems and touch sensitive screens:

Other Decisions

Breakpoints

There will need to be a number of 'breakpoints' where the layout changes but the number should be minimised. The main width breakpoints are determined by:

Although not optimum the same breakpoint in width will be used for:

The end result is that there only need to be two breakpoints which cause a potential reload:

2. Development of the JavaScript based Responsive Code and Utilities

In our case the solution for has to work with the minimum number of changes to existing pages as the combination of pcurtis.com and uniquelynz.com involves over 500 pages and 5000 images. The current pages use scripts which write html to the document 0n-the-fly, in particular this is used in the popup/lightbox pictures. This is an approach which is going out of favour but saves a lot of extra html code and gives considerable flexibility. Most of the pictures are now in 'blocks' using tables which are up to 4 wide.

Although it was not clear during the development it is now apparent that the new JavaScript code and much of the old breaks down into distinct groups:

In documenting this section it has revealed several inconsistencies which others should avoid. Some I have changed but some I will probably have to live with or carry out some very serious global search and replaces. Do not make the same mistakes!

Having broken them up in this way the following sections will cover the actual code.

JavaScript tests and derived variables.

 

// Detect mobile operating systems . Credit to http://www.abeautifulsite.net/detecting-mobile-devices-with-javascript

var is_mobile = {
  Android: function() {
    return navigator.userAgent.match(/Android/i);
  },
  BlackBerry: function() {
    return navigator.userAgent.match(/BlackBerry|BB10/i);
  },
  iOS: function() {
    return navigator.userAgent.match(/iPhone|iPad|iPod/i);
  },
  Opera: function() {
    return navigator.userAgent.match(/Opera Mini/i);
  },
  Windows: function() {
    return navigator.userAgent.match(/IEMobile/i);
  },
  any: function() {
    return (is_mobile.Android() || is_mobile.BlackBerry() || is_mobile.iOS() || is_mobile.Opera() || is_mobile.Windows());
  }
};

function isMobile() {
 return (is_mobile.any())
}


function isComputer(){
return (!isMobile() && screen.width > 720 && screen.height > 720 )
}
function isNetbook(){
 return (!isMobile() && screen.width > 720 && screen.height > 600 && screen.height < 719 )
}

function isFirefox() {
  return navigator.userAgent.match(/Firefox/i);
}
function isApple() {
  return navigator.userAgent.match(/WebKit/i);
}
function isIE9() {
  return navigator.userAgent.match(/MSIE 9.0/i);
}
function isOpera() {
return navigator.userAgent.match(/Opera/i);
}

var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1; // historic and believed only used in fudge in popup5()
function isChrome() {
  return is_chrome ;
}

// Find screenWidth taking viewport implementations in consideration

var screenWidth = screen.width
var inWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; // Browser Independent
if (inWidth > 280 && inWidth < screen.width) { screenWidth = inWidth } // Otherwise Viewports may nor give corrected innerWidth

I have found conflicting views on the support of viewport in browsers and window.innerWidth and window.innerHeight seem to be best and most consistently supported by browsers. I am not sure that the expression is actually better but it is in my test suites.

Responsive Changes to Tables

Some of the most important layout on the site is done by use of tables including navigation bars and blocks of pictures. The initial approach was to make additions to the tables of pictures so extra row breaks can be added to reduce the width to 3 or 2 columns. This is done adaptively writing the extra 'row code' (</tr><tr>). I found this had a advantageous side effect that larger blocks can be used which can respond to the width so instead of say using successive blocks of say 4 wide and three wide pictures a single block of 7 can be used which breaks according to the width. The popup/lightbox image code and the table format is written when the page is first loaded or reloaded. A manual reload can be quite fast as almost everything should be held in cache and only a re-render should need to take place.

It was realised at an early stage that it would be possible to automatically call a reload if the aspect ratio of a mobile device changes from Landscape to Portrait or even if a significant change in width is detected. Reloads are already used for the changes from popup to lightbox picture displays. This approach is covered below. The adaptive change using additional writing to the document allows also the top menu to change from 6 wide to 3 x 2.

// Functions that define the various breakpoints used primarily for tables. Values are allocated in these functions.

function isTwoCols () {
 var sw = screen.width
  if(window.innerWidth) {
    if (window.innerWidth < screen.width) { sw = window.innerWidth }
  }
  return ( sw < 550 )
}

function isThreeCols() {
  var sw = screen.width
  if(window.innerWidth) {
    if (window.innerWidth < screen.width) { sw = window.innerWidth }
  }
  return ( (sw > 549 && sw < 719 ) )
}

function isFourCols() {
  var sw = screen.width
  if(window.innerWidth) {
    if (window.innerWidth < screen.width) { sw = window.innerWidth }
  }
  return (sw > 718 )


function scnWidth() {
var sw = screen.width
if(window.innerWidth) {
if (window.innerWidth < screen.width) { sw = window.innerWidth }
}
return ( sw )
}


// This code is used to define the number of columns in picture tables


function reponsivePictureblockSplit(pbIndex){
  if (isTwoCols() && (pbIndex % 2 == 0 ) ) {
     document.write('\<\/tr\>\<tr\>');
  } else if (isThreeCols() && (pbIndex % 3 == 0 ) ) {
     document.write('\<\/tr\>\<tr\>');
  } else if (isFourCols() && (pbIndex % 4 == 0 ) ) {
     document.write('\<\/tr\>\<tr\>');
  }
}

function ReponsiveNavBarSplit(){
  if (!isFourCols() ) {
    document.write('\<\/tr\>\<tr\>');
  }
}

In documenting the above it became clear that the functions ought to use the value screenWidth which should be browser independent and work with IE8 and earlier.

The following is an example of the html for a block of 7 pictures using the above javascript functions

<table class="pictureblock">
  <tr>
    <td class="pictureblock"> <script>hpop('nz08/img_2806','Fokker Triplane', 'gallery1' )</script></td>
    <td class="pictureblock"> <script>hpop('nz08/img_2804','Replica Pfalz DIII', 'gallery1' )</script></td>
  <script>reponsivePictureblockSplit(2)</script>
    <td class="pictureblock"> <script>hpop('nz08/img_2803','Nieuport II', 'gallery1' )</script></td>
  <script>reponsivePictureblockSplit(3)</script>
    <td class="pictureblock"> <script>hpop('nz08/img_2837','Two Fokker triplanes on the attack', 'gallery1' )</script></td>
  <script>reponsivePictureblockSplit(4)</script>
    <td class="pictureblock"> <script>hpop('nz08/img_2686','Sopwoth Camel on landing', 'gallery2' )</script></td>
  <script>reponsivePictureblockSplit(5)</script>
    <td class="pictureblock"> <script>hpop('nz08/img_2858','Nieuport II coming in to land ', 'gallery2' )</script></td>
  <script>reponsivePictureblockSplit(6)</script>
    <td class="pictureblock"> <script>hpop('nz08/img_2861','Four of the five Harvards', 'gallery2' )</script></td>
  </tr>
</table>

The pages still need hand crafting but the changes are mostly a series of repetative pastes and an edit of the index parameter in reponsivePictureblockSplit(4).

The following shows how the navigation menu to changes from 6 wide to 3 x 2 using the above javascript function.

<table style="width:100%;">
  <tr >
    <td class="homebar" > <a class="homebar" href="homepage.htm">Home</a> </td>
    <td class="pemcbar" > <a class="pemcbar" href="pemc.htm">Pauline</a> </td>
    <td class="howtobar" > <a class="howtobar" href="howto.htm" >Howto&nbsp;Articles</a> </td>
  <script>ReponsiveNavBarSplit()</script>
    <td class="unzbar" > <a class="unzbar" href="nzguide.htm">Uniquely&nbsp;NZ</a> </td>
    <td class="sfbar" > <a class="sfbar" href="enterprise.htm">Small&nbsp;Firms</a> </td>
    <td class="srchbar" > <a class="srchbar" href="site-search.htm">Search</a> </td>
  </tr>
</table>

The dynamic (on-the-fly) [re]writing of table is perhaps the most technique developed to make my pages responsive but does require the page to be reloaded to display major changes.

Responding Automatically to Orientation and Window Size Changes

This is the key to the rewriting the page on-the-fly to respond to changes. The technique of dynamic creation of tables is very powerful but we need a mechanism to detect and respond to changes in window or Viewport changes in size or orientation and reload the page when required. It is possible to set up an event handler to reload the page but this has to be used sparsely to avoid the time involved. There are several events which seem appropriate namely resize and orientationchange but the implementation seems to vary between browsers. orientationchange is obviously only appropriate to mobile browsers.

What I have found so far is:

So I initially made a handler for resize events which checked for the size of change to avoid multiple calls for reloads. Initially this just looked for changes of greater than a set number of pixels but I then realised that one should check for changes which result in the need for a change of the number of columns displayed in adaptive tables.

I was forced to abandoned the use of location.reload(false) which forces use of cache but found window.location.href = window.location.href does force a reload in Firefox.

Latter tests show that window.location.href = window.location.href fails if there is an anchor (#anchor) defined in Firefox and the latest code uses a test for Firefox which uses location.href=location.pathname this still seems to use cache but leaves one at the top of the page after the reload. I have found no way round this for Firefox but other browsers can use the alternative approach of history.go(0) which preserves anchors and ones possition on the page.

Later testing showed Apple browsers (Safari etc) however seem to work best with location.reload(false) to preserve ones location on the page.

The final mechanism to decide if a reload is required looks for changes in size which cross a 'column boundary' and thereby minimises the number of calls. It is also possible add timers to reduce any possibility of jitter further but it has proved unnecessary.

It has unfortunately proved necessary to make the responsiveReload() function browser dependent.

window.addEventListener("orientationchange", responsiveReload);
window.addEventListener("resize", responsiveReload);

var twoCols = isTwoCols();
var threeCols = isThreeCols();
var fourCols = isFourCols();

function responsiveReload() {
 // Check for a change in the columns required before a reload
  if( twoCols == !isTwoCols() || threeCols == !isThreeCols() || fourCols == !isFourCols() ) {
    twoCols = isTwoCols();
    threeCols = isThreeCols();
    fourCols = isFourCols();
    if( isFirefox() ) {
      location.href=location.pathname
      return true;
    } else if (isApple()){
      location.reload(false) // setTimeout(location.reload(false), 1000);
      return true;
    } else {
      history.go(0)
    }
  }
}

The code for the detection of various browsers has been covered earlier.

The above has not proved sufficient and the extra code is currently being written up in Diary part 31

Switching, Hiding and Showing Blocks of text and pictures

This is the other major techniques used on my pages for responsive design. Its use includes changing the footers for Mobile versus Computer and for changing the size of Maps and Images.

/*
Function to allow one to switch between two two blocks for Responsive design.
if rlogic is true display the block within a tag with id of showId
otherwise display the block within a tag with id of hideId
this function MUST FOLLOW the two tag enclosed blocks
*/

function ResponsiveShowHide(rlogic,showId,hideId){
  var expand1=document.getElementById(showId);
  if(!expand1)return true;
  if (rlogic) {
     expand1.style.display="block"
  } else {
     expand1.style.display="none"
  }

  var expand2=document.getElementById(hideId);
  if(!expand2)return true;
  if (rlogic) {
    expand2.style.display="none"
  } else {
    expand2.style.display="block"
  }
return true;
}

Further Examples of use of ResponsiveShowHide() - Image Maps and Screenshots

Image maps can not be scaled so there has to be a choice based on their size as to whether just an image is displayed which scales or the full map which is a fixed size based on the image size. A good criteria is probably to use a break-test of two column to change from a full display of the picture map to a simple image with scaling allowed. In practice this should enable image maps on most mobiles in landscape view. This is a perfect example of the use of ResponsiveShowHide().

I looked at various options for screen dumps including changing to a scalable width with potential jitter or use a scaled down icon (160px) and lightbox overlay (without using a script). In the end I decided that making sure that the pages should work just as before on a laptop or desktop should take priority. In any case the screen dumps are from desktop or laptop and those who need them will be using such a machine when they need them. I therefore ended up with a similar solution to that developed for image maps using ResponsiveShowHide(). Depending on the image size I choose to use display either

The breakpoint is chosen using the nearest 'column' breakpoint or if too big using screenWidth directly. An example (which also shows the original image code commented out) and making use of my ResponsiveShowHide function is:

<!-- <p class="center"><img src="gallery/opencpn_options.jpg" style="width:600px;height:621px;padding-top:15px;" alt="screenshot" title="screenshot"></p> -->

<p id="fix8" class="center"><img src="gallery/opencpn_options.jpg" style="width:600px;height:621px;padding-top:15px;" alt="screenshot" title="screenshot"></p>
<p id="shrink8" class="center"><img src="gallery/opencpn_options.jpg" style="max-width:98%; height:auto;padding-top:15px;padding-left:5px;" alt="screenshot" title="screenshot"></p>
<script>ResponsiveShowHide(isFourCols(), "fix8", "shrink8")</script>

Changes to the popup/lightbox scripts.

These are the scripts which dynamically write the popup and lightbox code on the page and are covered in depth in the Using Lightbox to Display Web Images and associated pages. They have been tidied up and the padding adjusted to save width and the changes fed back into the Using Lightbox to Display Web Images page.

The only addition is a mechanism to get down to 320 wide screens with two column blocks of pictures. This is done by reducing the size of the icons from 160 x 120 to 120 x 90 pixels just for horizontal icons and screens under 356 wide and reducing the padding to a minimum. vbox() is by definition narrower and does not need modification. The code for the hbox() script (which dynamically writes the complex calls for lightbox pictures) is now:

function hbox(image, title, alignment) {
   cssalign = "width: 160px; height:120px; display: block;margin-left:auto;margin-right:auto;padding-left:6px;padding-right:6px;padding-top:10px;padding-bottom:10px;"
   if (screenWidth < 358 ) { cssalign = "width:120px;height:90px;display:block;margin-left:auto;margin-right:auto;padding-left:1px;padding-right:1px;padding-top:10px;padding-bottom:10px;" };
   if(alignment == "left"){ cssalign = "width:160px;height:120px; float:left;padding-left:0px;padding-right:6px;padding-top:10px;padding-bottom:10px;" ; alignment="center"};
   if(alignment == "right") { cssalign = "width:160px;height:120px; float:right;padding-left:6px;padding-right:0px;padding-top:10px;padding-bottom:10px;" ; alignment="center"}
   if((alignment !== "center" && alignment.substring(0, 7) !== "gallery") || getCookie('broadband') == "false" ){alignment = image.substring(image.lastIndexOf('/')+1) };
   title = title + " (" + image.substring(image.lastIndexOf('/')+1) + ")";
   document.write('<a href=\"' + image + 'b.jpg\" data-lightbox=\"' + alignment + '\" data-title=\"' + title +'\"><IMG src= \"' +image + 'i.jpg\" alt=\"' + title + '\" title=\"' + title + '\" style=\" ' + cssalign + ' \" \/></a>')
}

The only change in the hpop script is to force use of hbox for everything other than computers and netbooks.

3. Developing a 'push-up' Settings and Navigation Menu for the Footer

The is the last area where we need to look at as part of our our Responsive Design. Currently the footer is where the settings for display of images are changed. Again a lot of options were tried out but the best seemed to be to switch between the existing footer on wide displays with a navigation bar and two settings 'links' to a compact display without settings or navigation bar and instead have a popup menu with combined navigation and settings. This did not require any extra JavaScript - only some more CSS. It looks quite complex as the settings part is written on the fly and changes in response to screen width and whether it is a computer or netbook.

The following shows the important section where the menu is created and switched and toggled on and off by an onClick on the menu image. It does not include the code to add the settings 'links' as they have a confusing number of options!.

<div class="menu" style="float:right;padding-right:10px;">
   <ul id="footerMenu" style="display:none;">
      <li class="homebar" ><a class="homebar" href="homepage.htm">Home</a></li>
      <li class="pemcbar"><a class="pemcbar" href="pemc.htm">Pauline</a></li>
      <li class="howtobar"><a class="howtobar" href="howto.htm" >Howto&nbsp;Articles</a></li>
      <li class="unzbar"> <a class="unzbar" href="nzguide.htm">Uniquely&nbsp;NZ</a></li>
      <li class="sfbar"><a class="sfbar" href="enterprise.htm">Small&nbsp;Firms</a> </li>
      <li class="srchbar"> <a class="srchbar" href="site-search.htm">Search</a></li>
  </ul>

  <a href="javascript:void(0)" onClick="ExpandToggle('footerMenu')"><img src="gallery/hamburger.jpg" alt="Navigation Menu and Settings " title="Navigation Menu and Settings" style="height:32px;width:32px;float:right;"></a>
 /div>

The important part is however done in the additions to the Cascading Style Sheet. This loosely based on ideas I initially found at http://www.inspirationalpixels.com/tutorials/creating-a-responsive-menu-with-html-css-jquery simplified and modified for my purposes and with the use of jQuery removed. The only obscure bit is the creation of the little arrow and there is some extra explanation at https://css-tricks.com/snippets/css/css-triangle/ . :after is a pseudo element and needs the content:"" to make it display. The positioning of the menu and triangle is all absolute and is set up for an icon size of 32 x 32 pixels and would need adjustment for a different size in the various bottom and right values.


.menu {
   position:relative;
   display:inline-block;
}
.menu ul {
   width:250px;
   position:absolute;
   bottom:42px;
   right:0px;
   padding:3px 5px;
   border-radius:8px;
   background:#a0a0a0;
}
.menu li {
   margin:2px 0px 2px 0px;
   float:none;
   display:block;
}
.menu a {
   display:block;
}
.menu ul:after {
width:0px;
height:0px;
position:absolute;
bottom:-10px;
right:16px;
content:"";
border-left:10px solid transparent;
border-right:10px solid transparent;
border-top:10px solid #a0a0a0;
}

The code above, which is currently in use, raises and lowers the menu only when the icon or the links within the menu are clicked. Many menus are also cleared by clicking anywhere outside the menu or after a set time. I have developed code to do both which is in the Further Development section below and they are both in use on this page but not the rest of the site. The javaScript is currently local but will only add about 20 lines to responsive.js and have a low impact on the site speed.

The Big Question: What should one do - the existing method works fine but will some users expect the menu to be hidden automatically? The existing method is best for very small screens, in particular in landscape view, where the screen will need to be 'scrolled' to get to all the menu with the risk of accidental clicks. My current feeling is to leave as it is or possibly add a timeout as a fall back but the code is available for others if they feel differently.

4. Changes to the Cascading Style Sheets to make the site more mobile friendly.

The majority of the remaining changes are in the Cascading Style Sheet. The sizes of the header text has been changed and likewise the styles for the Navigation Bar to make them higher and easier for touch sensitive mobile use. These automatically get applied to all pages. The padding on paragraphs, headers etc makes the layout look better with the and reduced width body by providing a small margin either side. It could be made adaptive to avoid wasting space on very small screens. I have included the classes for centering below. Others will need to adapt these to their own layouts. Note that almost all the sizes are specified in em so they are relative to the size of the base font rather than absolute. Pixels, em and % are handled well and consistently by most browsers one will meet, other dimensions are less consistently handled.

body {
color: black;
font-family: Georgia,"Times New Roman",Times,serif;
max-width: 930px;
margin: 0 auto;
padding: 0px;
}
p {
color: black;
padding-left: 6px;
padding-right: 5px;
}
h1 {
font-size: 1.8em;
font-weight: bold;
padding-left: 6px;
padding-right: 5px;
}
h2 {
font-size: 1.6em;
font-weight: bold;
padding-left: 6px;
padding-right: 5px
}
h3 {
font-size: 1.37em;
font-weight: bold;
padding-left: 6px;
padding-right: 5px
}
h4 {
font-size: 1.19em;
font-weight: bold;
padding-left: 6px;
padding-right: 5px
}
h5 {
font-size: 1.1em;
font-weight: bold;
padding-left: 6px;
padding-right: 5px
}
a:link {
color: #0000ff;
}
a:visited, a:active {
color: #0080ff;
}
a:hover {
color: #cc0000;
text-decoration: none;
}
ul, ol {
padding-top: 0px;
padding-bottom: 0em;
padding-left:1.5em;
padding-right:0px;
margin: 0px;
}
img {
border: 0px solid black;
}
table, td, tr {
border: 0px solid black;
}
h1.center, h2.center, h3.center, h4.center, h5.center, p.center, div.center {
text-align: center;
}
table.center {
margin-left: auto;
margin-right: auto;
}

Lists

We have now covered most of the changes to make the pages responsive. There are however some more changes which will make them display better on a small screen. Firstly the indentation on lists needs to be reduced, particularly for those which are deeply indented and secondly the spacing needs to be increased if they are used as a menu or index with links to increase the spacing for touch screens. These changes were originally tested by defining some new classes in the CSS for the various list types I use and by padding the list items. The list padding needs to only be applied when required, namely when there is a link but the reduction in indentation has been made global.


ul, ol {
   padding-top: 0px;
   padding-bottom: 0em;
   padding-left:1.2em;
   padding-right:0px;
   margin: 0px;
}

li.index {
padding-top:.25em;
padding-bottom: 0em;
padding-left:0em;
padding-right:0em;
margin: 0px;
}

Navigation Bars

The same requirement to increase the spacing between links applies to Navigation Bars but here the solution is even simpler and just involves increasing the line spacing. The bar is also centered at the same time.

p.navigationbar {
   text-align:center;
   line-height:1.6;
}

Minimum Width for Picture Block data cells

Whilst testing the changes with borders turned on I realised that the appearance of the picture block would be improved if I added a minimum width (min-width) to class td.pictureblock for data cells - it makes the table layout more even with a mix of landscape and portrait pictures as the screen size reduces. This has to be 157 not 160 to cover the case of 320 wide screens where I shrink the image size but is still much better than 120. The whole of the relevant css for pictureblocks is now:

table, td, tr {
  border: 0px solid black;
}
  table.pictureblock {
  width: 90%;
  border-collapse: collapse;
  margin-left: auto;
  margin-right: auto;
  background-color: white;
}
td.pictureblock {
  text-align: center;
  padding:0px;
  min-width:157px;
}

Checklist of Changes always needed on each page

This assumes that the pages have already been changed to HTML5 and that the changes to limit the width to 960 have already been made!

  1. Add <meta name="viewport" content="width=device-width, initial-scale=1"> in head above JavaScript includes.
  2. Change from ebox.js to rbox.js
  3. Change from general.css to responsive.css
  4. Add the three links for lightbox if pictures are used on the page.
  5. Replace Navigation Bar(s).
  6. Add new class to any Navigation Links at top and bottom of page (if used).
  7. Change all Picture Blocks to new format with ResponsivePictureblockSplit(index) Scripts.
  8. Hand craft any image maps and other images such as screen grabs.
  9. Copy/Paste a complete new 'footer' to the page from a matching page (Home, Pauline, Howto Articles, Uniquely NZ, Small Firms or Search) which has been modified. This will differ depending whether settings are required because the page has pictures.

It is often quickest to replace the whole head and copy the keyword, description and title meta statements from the old head along with any page specific styles.

Browser Dependencies

Where possible I have used the lowest level of Javascript and CSS possible and only functions which are Browser Independent however there are some areas where that is impossible. Even so I have had to use a few fudges and workarounds which are browser dependent. These are mostly in the area of popups and gaining or maintaining focus (Opera and Chrome) . The other area is in detecting changes in the page size and reloading the page as part of the responsive design (Firefox and Safari) . Earlier versions of Internet Explorer also pose particular problems.

Specifics may follow

Further Development

Removal of use of <script> element within tables

It has come to my attention that the strict definition of HTML[4] does not allow a <script> element within a <tr> element However the HTML5 recommendation does seem to allow the <script> element under certain circumstances, ie if it is used as a script-supporting element - see http://www.w3.org/TR/html/tabular-data.html#the-tr-element. I do not get any validation errors with the HTML5 validator provided by W3C however tidy5 gives a warning. It is possible that my mechanisms which add an extra </tr><tr> using a <script> element could fail if browsers or the validator become more strict in the future so I have been looking at alternatives/enhancements.

Navigation Bar changes

The split of the navigation bar can easily changed to use responsiveShowHide() although the code is longer. This is in use on this development page

<div id="showNav6x1" >
 <table style="width:100%;">
  <tr>
   <td class="homebar" > <a class="homebar" href="homepage.htm">Home</a> </td>
   <td class="pemcbar" > <a class="pemcbar" href="pemc.htm">Pauline</a> </td>
   <td class="howtobar" > <a class="howtobar" href="howto.htm" >Howto&nbsp;Articles</a> </td>
   <td class="unzbar" > <a class="unzbar" href="nzguide.htm">Uniquely&nbsp;NZ</a> </td>
   <td class="sfbar" > <a class="sfbar" href="enterprise.htm">Small&nbsp;Firms</a> </td>
   <td class="srchbar" > <a class="srchbar" href="site-search.htm">Search</a> </td>
  </tr>
 </table>
</div>
<div id="showNav3x2">
 <table style="width:100%;">
  <tr>
   <td class="homebar" > <a class="homebar" href="homepage.htm">Home</a> </td>
   <td class="pemcbar" > <a class="pemcbar" href="pemc.htm">Pauline</a> </td>
   <td class="howtobar" > <a class="howtobar" href="howto.htm" >Howto&nbsp;Articles</a> </td>
  </tr><tr>
   <td class="unzbar" > <a class="unzbar" href="nzguide.htm">Uniquely&nbsp;NZ</a> </td>
   <td class="sfbar" > <a class="sfbar" href="enterprise.htm">Small&nbsp;Firms</a> </td>
   <td class="srchbar" > <a class="srchbar" href="site-search.htm">Search</a> </td>
  </tr>
 </table>
</div>
<script> ResponsiveShowHide( (isFourCols() ),"showNav6x1","showNav3x2")</script>

Picture Block changes

The picture blocks seemed more of a problem initially until I realised the solution was to write the whole table as a series of scripts. I have therefore created a number of scripts which write HTML tags and the whole is then enclosed in a <script></script> tag. This then follows the existing layout of a table and my picture blocks so it is easily understandable but is actually much more compact.

<script>
  tableCpictureblock();tr();
  tdCpictureblock();hpop('nz08/img_2806', 'Fokker Triplane', 'gallery1' );tdE();
  tdCpictureblock();hpop('nz08/img_2804', 'Replica Pfalz DIII', 'gallery1' );tdE();
    reponsivePictureblockSplit(2);
  tdCpictureblock();hpop('nz08/img_2803', 'Nieuport II', 'gallery1' );tdE();
  trE();tableE()
</script>

The matching javascript in rbox.js will be:

<script>
function td(){
  document.write('\<td style=\"padding:0px;\"\>');
}
function tdCpictureblock(){
  document.write('\<td class=\"pictureblock\"\>');
}
function tdE(){
  document.write('\<\/td\>');
}
function tr(){
  document.write('\<tr\>');
}
function trE(){
  document.write('\<\/tr\>');
}
function tableCpictureblock(){
  document.write('\<table class=\"pictureblock\"\>');
}
function tableE(){
  document.write('\<\/table\>');
}
</script>

As you can see I have initially chosen function names which reflect the HTML tags and associated classes. I have chosen the convention of ending a closing tag function with E and used a C when there is a class in use in an opening tag.

NOTE: The changes in the JavaScript include file rbox.js have been made and uploaded but the changes in the html have not yet been implemented on any other pages on my site but are being held in reserve for future problems.

Changes to footer to reduce rewriting on the fly

The next version of the footer makes more use of ResponsiveShowHide() instead of JavaScript writing on-the-fly of the text for changing between Popups and Lightbox and changing Bandwidth. This seems to reduce 'glitches' in the display as well as being a tidiercookie_banner way to do it. It is currently being tested on this page.

The code above, which is currently in use, raises and lowers the menu only when the icon or the links within the menu are clicked. Many menus are also cleared by clicking anywhere outside the menu or after a set time.

Hiding Heading and/or Footer Menu when one clicks anywhere else.

outside By first attempt to set up clearing down the menu when any where else was clicked was by adding an onClick event to the <body> element. This failed as any clicks on the menu icon were also clicks on the body and led to a race condition with generally the menu being hidden as fast as it was displayed!

I tried various ideas with timers to get round the problem but they were ugly and my favourite solution is to use the click on the menu icon to set a flag and an event handler for the document to pick that up for action. I had no race condition but I added a slight delay to the event handler as belt and braces. This seemed to work very well although it means one is always adding a specific event handler through my javaScript include file regardless of whether it is needed. I therefore added code to check if the id of the menu is present before adding the handler. The following has the three existing functions to expand or hide blocks at the top for completeness and the new additions follow:

// Existing functions to display or hide blocks

function ExpandOn(topicID){
  var expand=document.getElementById(topicID);
  if(!expand)return false;
  if(expand.style.display=="none"){
    expand.style.display="block"
  }
  return true;
}
function ExpandOff(topicID){
  var expand=document.getElementById(topicID);
  if(!expand)return false;
  if(expand.style.display=="block"){
    expand.style.display="none"
  }
  return true;
}
function ExpandToggle(topicID){
  var expand=document.getElementById(topicID);
  if(!expand)return false;
  if(expand.style.display=="none"){
    expand.style.display="block"
  } else {
    expand.style.display="none"
  }
  return true;
}

// New additions with both header and footer menu handling

window.onload=function() {
  if (document.getElementById('showFooterMenu') || document.getElementById('showHeaderMenu' )) {
    document.onclick = docClick
  }
}
var display_footer_menu="false";
var display_header_menu="false";
var kill_header_timeout;
var kill_footer_timeout;
function docClick() {
  setTimeout(function(){
    if (display_header_menu=="true") { ExpandToggle('showHeaderMenu');
    } else { ExpandOff('showHeadMenu');}
    if (display_footer_menu=="true") { ExpandToggle('showFooterMenu');
    } else { ExpandOff('showFooterMenu');}
    display_header_menu="false";
    display_footer_menu="false";
  }, 5);
}
function setDisplayFooterMenu() {
  display_footer_menu='true';
  clearTimeout(kill_footer_timeout);
  kill_footer_timeout = setTimeout(function(){
    if (display_footer_menu=="true") { ExpandToggle('showFooterMenu'); display_footer_menu="false";
    } else { ExpandOff('showFooterMenu'); }
  }, 20000);
}
function setDisplayHeaderMenu() {
  display_header_menu='true';
  clearTimeout(kill_header_timeout);
  kill_header_timeout = setTimeout(function(){
    if (display_header_menu=="true") { ExpandToggle('showHeaderMenu'); display_header_menu="false";
    } else { ExpandOff('showHeaderMenu'); }
  }, 20000);
}

Hiding Menu after a set time

I saw no reason why I should not add a 'timer' to setDisplayFooterMenu() which also calls docClick() (or a dedicated function) to hide the menu after a set time as well. It also needs to have a clearTimout to avoid unintended removals if the menu is re-enabled. The modified code to include a 20 second timeout is below.

var timeoutID

function setDisplayFooterMenu() {
  display_footer_menu='true';
  clearTimeout(timeoutID);
  timeoutID = setTimeout(function(){
    if (display_footer_menu=="true") { ExpandToggle('showFooterMenu');
      display_footer_menu="false";
    } else { ExpandOff('showFooterMenu'); }
  }, 20000);
}

The Big Question: What should one do - the existing method works fine but will some users expect the menu to be hidden automatically? The existing method is best for very small screens, in particular in landscape view, where the screen will need to be 'scrolled' to get to all the menu with the risk of accidental clicks. My current feeling is to leave as it is or possibly add a timeout as a fall back but I had to prove it could be done! This page currently implements both.

I looked at several ways of adding a banner to the top of the page to satisfy EU cookie warning legislation. This is not strictly a part of the Responsive part of the site update and may be moved to a new page in the future

In brief ....

You must tell people if you set cookies, and clearly explain what the cookies do and why. You must also get the user’s consent. Consent can be implied, but must be knowingly given.

There is an exception for cookies that are essential to provide an online service at someone’s request (eg to remember what’s in their online basket, or to ensure security in online banking).

The same rules also apply if you use any other type of technology to store or gain access to information on someone’s device.

To be valid, consent must be freely given, specific and informed. It must involve some form of positive action – for example, ticking a box or clicking a link – and the person must fully understand that they are giving you consent. You cannot show consent if you only provide information about cookies as part of a privacy policy that is hard to find, difficult to understand, or rarely read.

Consent does not necessarily have to be explicit ‘opt-in’ consent. Implied consent can also be valid. If you are relying on implied consent, you need to be confident that your users fully understand that their actions will result in cookies being set. However, in some circumstances (for example, collecting sensitive personal data such as health details) it is likely that explicit opt-in consent is more appropriate.

As long as you do this the first time you set cookies, you do not have to repeat it every time the same person visits your website.

Information summarised from the ICO advice on Cookies and similar technologies

This should ideally use a method which works from within the Javascript file already linked from every page. One way is a conditional javascript write in the included javascript file. This was my initially favoured solution and it worked well on a simple test page but I could see additional complexity in a responsive environment. The second way is based on an idea I found at https://www.creare.co.uk and that creates a <div> element containing the banner and' injects' it into the page after it has loaded. This is actually very simple to do and it is possible to place the banner at the top or bottom quite easily and there is more explanation at https://www.creare.co.uk/js-eu-cookie-law-banner. I brought the concept into my trial page as a drop in replacement for the writing on the fly function which made use of my existing cookie routines. I also kept the way of removing the banner - my earlier alternative was a simple rewrite of the page using a location.reload(false) as I do elsewhere.

// extra code added to existing function
window.onload=function() {
  if (document.getElementById('showFooterMenu') || document.getElementById('showHeaderMenu' )) {
    document.onclick = docClick
  }
  if (getCookie('cookies_accepted') == "false" || getCookie('cookies_accepted') == "undefined") { 
    createBanner();
  }

}

// The method of adding an extra <div> element is based on an idea at https://www.creare.co.uk/js-eu-cookie-law-banner

function createBanner(){
  var bodytag = document.getElementsByTagName('body')[0];
  var div = document.createElement('div');
  var bannerCode = '<img title="Close Banner" onclick="removeBanner()"   src="gallery/close_banner.png" style="height:20px;width:20px;float:right;padding:6px;"><p style="padding:10px 10px;">';
  if ( !navigator.cookieEnabled ) { // Warn if Cookies disables
    bannerCode += '<b>Warning:</b> Cookies have been disabled in your browser settings so advanced functions will not work and preferences will not display correctly <br> ';
  } else {
    bannerCode += 'This website uses cookies and by '
    bannerCode += '<a href="javascript:void(0);" onclick="doAccept()" class="homebar" title="Agree to use of Cookies">Agreeing</a>'
    bannerCode += ', or continuing, you signify acceptance.&nbsp;&nbsp; <a href="cookies.htm" class="homebar" title="Privacy &amp; Cookies Policy">More&nbsp;Details</a>'
  }
  if ( isIE9orless() ) { // Additional warning if old browser
    bannerCode += '<br><b>Warning:</b> You are running an early version (' + msieversion + ') of Internet Explorer so some advanced web site functions have been disabled.'
  };
  bannerCode += '</p>';
  div.setAttribute('id','cookie_banner');
  div.setAttribute('style','background:yellow;border-radius:7px;'); // Better to use #cookie_banner {background:yellow;border-radius:7px;} in style sheet
  div.innerHTML = bannerCode;
// bodytag.appendChild(div); // Alternative - adds Banner before </body> tag
  bodytag.insertBefore(div,bodytag.firstChild); // Alternative - adds Banner after <body> tag
  setCookie('cookies_accepted',"true",cookie_time,"/"); //Remove commenting to have default of banner only appearing once.
}

function removeBanner(){
  var element = document.getElementById('cookie_banner');
  element.parentNode.removeChild(element);
}

function doAccept() {
  setCookie('cookies_accepted',"true",cookie_time,"/");
  removeBanner();
}

function doNotAccept() {
  setCookie('cookies_accepted',"false",cookie_time,"/");
}

Additions of Warnings to Banner

The above code includes additions or changes to the banner if:

  1. If cookies are disabled use alternative message ( if ( !navigator.cookieEnabled ) {.... )
  2. If one is using an old version of Internet Explorer using following test function

var msieversion = 0;
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){
  msieversion = Number(RegExp.$1) }

function isIE9orless() {
  return ( msieversion != 0 && msieversion < 10 );
}

Further thoughts:

Change bannerCode to bannerHTML to make clearer that is the variable where the HTML code which is in the <div> is built up.

Change the test and flag for isIEorless() to be more general and cover other legacy or problem browsers where popups do not work well.

Making embedded Videos Responsive - youtube and it's Friends

Videos have a reputation of being difficult to add to responsive pages. I have however found a reasonably simple way to make the size respond to different sizes of screen. This is done by wrapping the code which embeds the video in a way that it shrinks with the page simply by by using css. The ideas came from https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php and http://stackoverflow.com/questions/15844500/shrink-a-youtube-video-to-responsive-width but I have extended it to also include centring the video and adding a small margin. This technique should work with most modern browsers.

The following is added to the end of the script .css file (responsive.css)

.videoWrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.videoWrapper iframe {
position: absolute;
top: 5%;
left: 5%;
width: 90%;
height: 90%;
}

The 25 pixels is for the 'candy' on the player (controls) and the margins centre the player in the responsive 'box'

And the video code is wrapped like this:

<div class="videoWrapper">
   <iframe width="832" height="468" src="https://www.youtube.com/embed/nVwqw8CWfaE?rel=0" frameborder="0" allowfullscreen></iframe>
</div>

Note the <iframe .... > is all one line obtained from the youtube site. I have however modified the width and height to match my 930 pixel html body width when using a 5% margin either side.

This technique could be combined with a Switch (hide/display) between a fixed width and a responsive width as is done with most other maps and large images and to offer a smaller and lower data rate video to mobile devices.

Tools and Tips for Testing

Using Chromium/Chrome locally for test (Fix cookies problem)

My normal way of testing is to use a local copy of the site. This does not work with Chromium/Chrome as it does not respect local cookies. This is a security issue and there is no way of changing the behaviour in Settings. You can however start Chromium with the flag from the command line or my modifying the .desktop file.

chromium-browser --enable-file-cookies

Installing LiveReload

LiveReload monitors for changes in a folder and automatically reloads the browser if any change is detected. Also, when you change a CSS file or image, the browser is updated instantly without even reloading the page.

Installing LiveReload is a simple process in Linux. To install LiveReload one must first install rubygems, then guard and finally guard-livereload:

sudo apt-get install ruby-dev
sudo gem install rdoc -V
sudo gem install guard -V
sudo gem install guard-livereload -V

Then create a new file named .Guardfile in your home directory. Put the following in the file and save it.

# https://github.com/guard/guard-livereload
guard :livereload do
watch(%r{.+.(css|js|htm|html)$})
end

This will watch the directories (that we're working on) for the changes in css, js, htm and html files inside them (or in their subdirectories).

Next install a LiveReload extension for your web-browser. It is this extension that refreshes the page after receiving command from guard-livereload app. Extensions are available for Chrome, Firefox and Safari.

Once you have it installed on your browser, bring up your terminal and browse to the directory where your web files (html, htm, css, js) are located. Then type guard and press enter. You can watch the operation in the terminal

Open up the HTML file on your browser, and press on the LiveReload button (which is located in the main toolbar in Chrome and Safari & in the add-on toolbar in Firefox). The LiveReload button should now be active (red).

Leave the terminal running and make changes to your site and when you save the file, the changes will be reflected immediately on the browser and you can see a record in the terminal. When you have finished type exit

pcurtis@defiant:~$ cd "/media/DATA/My Web Site" && guard
05:18:59 - INFO - LiveReload is waiting for a browser to connect.
05:19:04 - INFO - Browser connected.
05:19:07 - INFO - Guard is now watching at '/media/DATA/My Web Site'
05:19:21 - INFO - Reloading browser: lightbox.htm
05:19:31 - INFO - Reloading browser: lightbox.htm
05:20:00 - INFO - Reloading browser: lightbox.htm
[1] guard(main)> exit

08:50:52 - INFO - Bye bye...

I run with an editor and a browser in half width windows beside each other and use Ctrl S frequently to save and view the changes

Installing HTML Tidy (tidy-html5)

I use tidy to check the html - the original tidy did not handle html5 so Tidy-html5 was developed, abandoned forked and now exists again at https://github.com/htacg/tidy-html5

There are binaries at http://binaries.html-tidy.org/.

I currently have HTML Tidy version 5.2 and 5.4 is now available for Linux as a .deb

Note that you may have to inhibit updates to the version in the repository which is the old tidy not the HTML5 version. Tidy is used by nixnote which may have be removed and reinstalled after the new html5 version is in place.

Now installed as tidy not tidy5 or tidy-html5 so example of use on this file is:

$ cd "/media/DATA/My Web Site" && tidy -e responsive.htm
Info: Document content looks like HTML5
No warnings or errors were found.

About HTML Tidy: https://github.com/htacg/tidy-html5
Bug reports and comments: https://github.com/htacg/tidy-html5/issues
Or send questions and comments to: https://lists.w3.org/Archives/Public/public-htacg/
Latest HTML specification: http://dev.w3.org/html5/spec-author-view/
Validate your HTML documents: http://validator.w3.org/nu/
Lobby your company to join the W3C: http://www.w3.org/Consortium
:/media/DATA/My Web Site$

Link to W3C HTML5 Validator Copyright © Peter & Pauline Curtis
Fonts revised: 28th April, 2021