“Greebling” is a term used by model makers and designers to describe non-functional surface detail: think of all the extra little panels on the Star Destroyer in the opening of Star Wars. “UI Greebling” is my term for the useless-but-great-looking interactions commonly seen on computer screens in film, particularly thrillers and action movies.

While it would be possible to create this display in with , it’s perhaps just a little easier in , so I’ve used that technology here. The demo above also uses my fullscreen YouTube background video technique discussed in a previous article. For this example, I’m providing the code and presentation of the fullscreen version of the demo on CodePen.

Markup & Styles

Most of the code is in JavaScript, but it does rely a little on some HTML for the canvas element itself:

<div class="canvascontainer">
    <canvas id="bargreeble" height="100" width="500"></canvas>

And to place the responsive canvas at the bottom of the screen and in the center, I use combined with vw and vh units:

.canvascontainer { 
    min-height: 90vh;
    display: flex;
    justify-content: center;
    align-items: flex-end;
canvas {
    width: 33vw;
    height: 10vw;

The Javascript

The script starts with two functions for getting random values: one for random boolean (true or false), the other to gain a random value between any two numbers:

function randomBool(){
    return Math.random()<.5; 
function randomVal(min,max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;

Then the canvas element, its context and dimensions are grabbed:

var barGreeble = document.getElementById("bargreeble"),
context = barGreeble.getContext("2d"),
greebleWidth = barGreeble.width,
greebleHeight = barGreeble.height,

Then a number of variables are created: numBars is the number of bars and gapWidth is the space between them. Several arrays are also created, which will contain the highest and lowest value for each bar, together with their initial value, rate of change, and initial direction (up or down). These arrays are empty at the beginning:

numBars = 18,
gapWidth = 3,
highBar = [],
lowBar = [],
initHeights = [],
rateOfChange = [],
uppyDowny = [],

The width of each bar is a function of the overall width of the canvas element, the number of bars desired, and the width between them:

barWidth = (greebleWidth - (gapWidth * numBars - 1))/numBars;

The fill of each bar is the same, so there’s no need to repeat it more than once:

context.fillStyle = "rgba(255,255,255,0.6)";

Information for the bars is entered into each of the arrays: the initial height for the first bar will be initHeights[0], for example. The rate of change for each bar is a random value of 1 or 2.

for (var j = 0; j < numBars; j++) {
   initHeights[j] = randomVal(10,barGreeble.height - 10);
   highBar[j] = randomVal(initHeights[j],barGreeble.height);
   lowBar[j] = randomVal(0,10);
   rateOfChange[j] = randomVal(1,2);
   uppyDowny[j] = randomBool();

The bars are generated with a function: first, the entire width and height of the canvas is cleared, then each bar is checked to see if it is headed up or down, and the appropriate amount added or removed from its height. If the height of the bar is greater or equal to its upper or lower limit, the bar is set to head in the opposite direction.

function randomBars() {
for (var i = 0; i < numBars; i++) {
  uppyDowny[i] == true ? initHeights[i]+= rateOfChange[i] : 
    initHeights[i]-= rateOfChange[i];
  context.fillRect(barWidth * i + gapWidth * i, initHeights[i], barWidth, 100);
  if (initHeights[i] >= highBar[i]) {
    uppyDowny[i] = false;
  if (initHeights[i] <= lowBar[i]) {
    uppyDowny[i] = true;

requestAnimationFrame is used to smooth and ease the animation; all of it is started with a call to the function:


I am coming to enjoy these quick little animations a great deal; you can expect to see more in the future, with a discussion of the code for each.

Moon animation by Robert Kooima, used under Creative Commons.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/dGagZv