Matthew James Taylor Matthew James Taylor

Web design ›

Boggle Dice Shaker (Built With Javascript)

17 Jun 2007 — Updated 6 May 2023

Boggle dice shaker

I've always loved playing Boggle but I don't own the game myself.

The only time I was ever able to play was at my friend's house. But not any more...

That's right, I have now built a Boggle dice shaker with Javascript that works in any web browser. Now all you need to play is an internet connection!

Just click the 'Shake it' button to start.


So here's how it's made:


I'm using custom HTML tags here because it just makes sense. See these articles for more details:

<boggle-tray class="shake">
    <boggle-dice id="dice0"> </boggle-dice>
    <boggle-dice id="dice1"> </boggle-dice>
    <boggle-dice id="dice2"> </boggle-dice>
    <boggle-dice id="dice3"> </boggle-dice>
    <boggle-dice id="dice4"> </boggle-dice>
    <boggle-dice id="dice5"> </boggle-dice>
    <boggle-dice id="dice6"> </boggle-dice>
    <boggle-dice id="dice7"> </boggle-dice>
    <boggle-dice id="dice8"> </boggle-dice>
    <boggle-dice id="dice9"> </boggle-dice>
    <boggle-dice id="dice10"> </boggle-dice>
    <boggle-dice id="dice11"> </boggle-dice>
    <boggle-dice id="dice12"> </boggle-dice>
    <boggle-dice id="dice13"> </boggle-dice>
    <boggle-dice id="dice14"> </boggle-dice>
    <boggle-dice id="dice15"> </boggle-dice>


Notice how nice the selectors are because I'm using custom tags!

boggle-tray {
    border:.2em solid #f96800;
    box-shadow:-5px 5px 5px rgb(0 0 0 / 20%);
boggle-tray.shake {
boggle-dice {
    border-top:1px solid #fff;
    border-right:1px solid #fff;
    border-left: 1px solid #cbc2aa;
    border-bottom: 1px solid #cbc2aa;
    box-shadow:-5px 5px 5px rgb(0 0 0 / 20%);

@keyframes shake {
    0% {transform: translate(1px, 1px) rotate(0deg)}
    10% {transform: translate(-1px, -2px) rotate(-1deg)}
    20% {transform: translate(-3px, 0px) rotate(1deg)}
    30% {transform: translate(3px, 2px) rotate(0deg)}
    40% {transform: translate(1px, -1px) rotate(1deg)}
    50% {transform: translate(-1px, 2px) rotate(-1deg)}
    60% {transform: translate(-3px, 1px) rotate(0deg)}
    70% {transform: translate(3px, 1px) rotate(-1deg)}
    80% {transform: translate(-1px, -1px) rotate(1deg)}
    90% {transform: translate(1px, 2px) rotate(0deg)}
    100% {transform: translate(1px, -2px) rotate(-1deg)}

The Javascript

This is where all the magic happens:

// Create dice face arrays
aDice0 = new Array("T", "O", "E", "S", "S", "I");
aDice1 = new Array("A", "S", "P", "F", "F", "K");
aDice2 = new Array("N", "U", "I", "H", "M", "Qu");
aDice3 = new Array("O", "B", "J", "O", "A", "B");
aDice4 = new Array("L", "N", "H", "N", "R", "Z");
aDice5 = new Array("A", "H", "S", "P", "C", "O");
aDice6 = new Array("R", "Y", "V", "D", "E", "L");
aDice7 = new Array("I", "O", "T", "M", "U", "C");
aDice8 = new Array("L", "R", "E", "I", "X", "D");
aDice9 = new Array("T", "E", "R", "W", "H", "V");
aDice10 = new Array("T", "S", "T", "I", "Y", "D");
aDice11 = new Array("W", "N", "G", "E", "E", "H");
aDice12 = new Array("E", "R", "T", "T", "Y", "L");
aDice13 = new Array("O", "W", "T", "O", "A", "T");
aDice14 = new Array("A", "E", "A", "N", "E", "G");
aDice15 = new Array("E", "I", "U", "N", "E", "S");

// Create tray face array
aFace = new Array(15);

function shakeit() {
    // Select random face for each dice
    aFace[0] = aDice0[RandNo(6)];
    aFace[1] = aDice1[RandNo(6)];
    aFace[2] = aDice2[RandNo(6)];
    aFace[3] = aDice3[RandNo(6)];
    aFace[4] = aDice4[RandNo(6)];
    aFace[5] = aDice5[RandNo(6)];
    aFace[6] = aDice6[RandNo(6)];
    aFace[7] = aDice7[RandNo(6)];
    aFace[8] = aDice8[RandNo(6)];
    aFace[9] = aDice9[RandNo(6)];
    aFace[10] = aDice10[RandNo(6)];
    aFace[11] = aDice11[RandNo(6)];
    aFace[12] = aDice12[RandNo(6)];
    aFace[13] = aDice13[RandNo(6)];
    aFace[14] = aDice14[RandNo(6)];
    aFace[15] = aDice15[RandNo(6)];
    // Jumble the dice
    for (d = 0; d < 16; d++) {
        // Get a random number between 0 and 15
        newnumber = (Math.random() * 16);
        newnumber = parseInt(newnumber, 10);
        temp = aFace[d];
        aFace[d] = aFace[newnumber];
        aFace[newnumber] = temp;

    var tray = document.getElementsByTagName("boggle-tray")[0];
    void tray.offsetWidth; // trigger a DOM reflow to reset
    // Update the tray
    for(t = 0; t < 16; t++) {
        if (document.getElementById('dice'+t)) {
            document.getElementById('dice'+t).innerHTML = '<strong>'+ aFace[t] +'</strong>';

function resetShake(tray) {"shake 0.5s";

// Generate random integer between 0 and limit
function RandNo(iLimit) {
    var ranNum= Math.floor(Math.random() * iLimit);
    return ranNum;

function addshakecontrol() {
    var shakebutton = document.getElementById('shakebutton');
    if (shakebutton) {
        addEvent(shakebutton, "click", shakeit);

function addEvent(obj, evType, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evType, fn, false);
        return true;
    } else if (obj.attachEvent) {
        var r = obj.attachEvent("on"+evType, fn);
        return r;
    } else {
        return false;

window.onload = function() {

Title image by Rich Brooks.

Matthew James Taylor

“I've been developing websites professionally for over two decades and running this site since 1997! During this time I've found many amazing tools and services that I cannot live without.”
— Matthew James Taylor

I highly Recommend:


Canva — Best Graphic Design Software

Create professional graphics and social media imagery with an intuitive online interface.

Learn more


Ezoic — Best ad network for publishers

Earn more than double the revenue of Google Adsense. It's easy to set up and there's no minimum traffic requirements.

Learn more


SiteGround — Best Website Hosting

Professional Wordpress hosting with 24/7 customer support that is the best in the industry, hands down!

Learn more


Brevo (Formerly Sendinblue) — Best Digital Marketing Platform

Manage your email list, promote your services, and send international SMS messages to your customers.

Learn more

See more of my recommended dev tools.

Columns all the same height

Equal-Height Columns (CSS Grid, Flexbox, Floated Containers, & Table Methods)

Direct-to-Brain Augmented Reality (DBAR) with Neuralink & AI

Direct-to-Brain Augmented Reality (With Neuralink & AI)

Footer at the bottom of the page diagram

Bottom Footer (CSS Grid, Flexbox, & Absolute Position Methods)

Ogga surfing

Ogga the Cane Toad (About the Comic Strip & Characters)

Graeme Frontbum

Graeme Frontbum (About the Comic Strip & Characters)

An example of a printed MacBook Air

Printable MacBook Air! (4 Easy Steps)

Sepia ink life drawing

Ink Life Drawing (6 Experiments with Nibs & Brushes)

A nice sharp pencil

The Art of Sharpening Pencils (Styles & Techniques)

How to add CSS to HTML

How to add CSS to HTML (With Link, Embed, Import, and Inline styles)

Flowers growing in a tiny house window flowerbox

12 Small House Benefits: Why Building Tiny Makes Sense!

Small house blueprint

13 Small House Design Principles (The Illustrated Guide)

Responsive house plan

Responsive House Plan (Web Design Meets Architecture!)

Lyndal the flower girl

Art by Matthew James Taylor (Paintings, Drawings & Digital Art)

Web design Web design Architecture Architecture Life drawing Life drawing Art gallery Art gallery Synesthesia Synesthesia Comics Comics

About Contact Privacy

© 1994 — 2024 Matthew James Taylor