Welcome to a tutorial on how to create digital signage with HTML and Javascript. Yes, anyone can make simple web pages these days. Then just access it on a smart TV, call it “digital signage”, the end. But that is not what we are making in this guide. Let us walk through something that is a little bit more robust – A progress web app (PWA) digital signage. Read on!
TABLE OF CONTENTS
JAVASCRIPT DIGITAL SIGNAGE
All right, let us now get into the digital signage example with HTML and Javascript. There are all kinds of signage from slideshows to videos to full-on POS hybrids. In this example, we will just stick with a simple slideshow.
PART 1) THE HTML
<!-- (A) SLIDES -->
<div id="slides"></div>
<!-- (B) MENU ITEMS -->
<div id="menu">
<h1>ONLY PIES</h1>
<ul>
<li>Apple Pie $1.10</li>
<li>Banana Pie $2.20</li>
<li>Cheese Pie $3.30</li>
<li>Derby Pie $4.40</li>
<li>Egg Pie $5.50</li>
<li>Fried Pie $6.60</li>
</ul>
<div>Quote "uvuvwevwevwe onyetenyevwe ugwemubwem ossas" to get 10% off!</div>
</div>
To keep things simple, this page only has a “left and right side”.
<div id="slides">
Picture slides on the left.<div id="menu">
Menu items are on the right.
PART 2) THE CSS
/* (A) WHOLE PAGE */
* {
font-family: "Brush Script MT", cursive;
box-sizing: border-box;
}
body {
display: flex;
padding: 0; margin: 0;
min-height: 100vh;
background: #2e120f;
overflow: hidden;
}
#slides { width: 60%; }
#menu { width: 40%; }
/* (B) SLIDES */
#slides { position: relative; }
#slides img {
position: absolute;
top: 0; left: 0;
display: block;
object-fit: cover;
width: 100%; height: 100%;
opacity: 0; visibility: collapse;
transition: opacity 1s;
}
#slides img.show {
opacity: 1; visibility: visible;
}
/* (C) MENU */
#menu {
padding: 20px;
color: #fff;
}
#menu ul {
padding: 0;
list-style: none;
}
#menu h1 { font-size: 36px; }
#menu ul li { font-size: 20px; }
Well, just some CSS cosmetics. Nothing “special” here.
PART 3) THE JAVASCRIPT
var sign = {
// (A) PROPERTIES
swrap : null, // slides html wrapper
now : 0, // current slide
all : 3, // total number of slides
slides : [], // html slide images
delay : 4000, // delay between each slide
// (B) INIT
init : () => {
// (B1) SLIDESHOW
sign.swrap = document.getElementById("slides");
for (let i=1; i<=sign.all; i++) {
let slide = document.createElement("img");
slide.src = `images/pie-${i}.webp`;
sign.swrap.appendChild(slide);
sign.slides.push(slide);
}
sign.slides[0].className = "show";
// (B2) ROTATE SLIDES
setInterval(() => {
sign.slides[sign.now].classList.remove("show");
sign.now++;
if (sign.now >= sign.all) { sign.now = 0; }
sign.slides[sign.now].classList.add("show");
}, sign.delay);
// (B3) IF WORKER SUPPORTED
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("4-worker.js");
}
}
};
window.onload = sign.init;
A tad bit of Javascript to rotate the slides.
- (B1) On window load,
init()
will run, create and insert<img src="images/pie-N.webp">
into<div id="slides">
. - (B2) Javascript interval timer to rotate between the slide images.
- (B3) Register a service worker if it is available. More of this in part 4 below.
PART 4) SERVICE WORKER
// (A) CREATE/INSTALL CACHE
self.addEventListener("install", evt => {
self.skipWaiting();
evt.waitUntil(
caches.open("JSSign")
.then(cache => cache.addAll([
"1-signage.html",
"2-signage.css",
"3-signage.js",
"images/pie-1.webp",
"images/pie-2.webp",
"images/pie-3.webp"
]))
.catch(err => console.error(err))
);
});
// (B) CLAIM CONTROL INSTANTLY
self.addEventListener("activate", evt => self.clients.claim());
// (C) LOAD FROM CACHE FIRST, FALLBACK TO NETWORK IF NOT FOUND
self.addEventListener("fetch", evt => evt.respondWith(
caches.match(evt.request).then(res => res || fetch(evt.request))
});
Just what does a “service worker” do? For the uninitiated, a service worker is simply a script that is “installed” to run in the background. Yes, it can even run when the user is not even on the webpage itself. For this simple worker:
- (A) A list of files and images to cache.
- (B) Create a storage cache and save all the defined files and images.
- (C) Serve files from the cache if it exists, fall back to the network if not found. That is, effectively creating an offline version of the page.
PART 5) INSTALLABLE PWA
5A) MANIFEST FILE
{
"short_name": "JS Sign",
"name": "JS Sign",
"icons": [{
"src": "images/favicon.png",
"sizes": "64x64",
"type": "image/png"
}, {
"src": "images/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}],
"start_url": "1-signage.html",
"scope": "/",
"background_color": "white",
"theme_color": "white",
"display": "fullscreen"
}
5B) HTML HEADER
<!-- MANIFEST -->
<link rel="manifest" href="manifest.json">
Finally, this manifest file should be pretty self-explanatory. It defines the name of the web app, the icons, preferred settings, etc… With that, we now have an installable PWA. Just tap on the icon to launch the page in fullscreen mode.
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
SORRY FOR THE ADS...
But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.
Buy Me A Coffee Code Boxx eBooks
EXAMPLE CODE DOWNLOAD
Click here for the source code on GitHub gist, just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
EXTRA BITS & LINKS
That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.
WHAT’S SO GREAT ABOUT PWA?
Before the trolls start to spew “so stupid”, “just copy HTML files into TV device”, or “just access a simple intranet website” – Here are a few plus points to developing a PWA.
- Easy mass deployments and updates. Don’t have to go down to each device physically, just update the server and it will automatically push.
- Offline capable, all the static files are cached in the device. It will still work if the Internet or intranet connection goes down.
- Can deploy anywhere in the world. Think about it, just access a website and hit install.
- Being a PWA opens up a world of possibilities. Maybe showing live streams, radio podcasts, flash offers, etc…
COMPATIBILITY CHECKS
- Arrow Functions – CanIUse
- Service Worker – CanIUse
- Cache Storage – CanIUse
Works on all modern “Grade A” browsers.
LINKS & REFERENCES
- Add websites and PWAs to Chrome kiosks – Google (yes, we can turn Google Chrome into a kiosk)
- Chrome Kiosk Mode On PC Android iOS Chrome OS – Code Boxx
THE END
Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!