Boggle Dice Shaker (Built With Javascript)
3 Nov 2025
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:
The HTML
I'm using custom HTML tags here because it just makes sense. See these articles for more details:
- Replace Divs With Custom Elements For Superior Markup
- Custom HTML Tags (18 Things To Know Before Using Them)
<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>
</boggle-tray>
The CSS
Notice how nice the selectors are because I'm using custom tags!
boggle-tray {
display:block;
width:10em;
height:10em;
display:flex;
flex-wrap:wrap;
background:#911e03;
border:.2em solid #f96800;
font-size:1.6em;
border-radius:.7em;
box-shadow:-5px 5px 5px rgb(0 0 0 / 20%);
}
boggle-tray.shake {
animation-duration:.3s;
animation-name:shake;
}
boggle-dice {
display:block;
width:2em;
height:2em;
margin:.2em;
line-height:2em;
text-align:center;
background:#f1e9d3;
border-top:1px solid #fff;
border-right:1px solid #fff;
border-left: 1px solid #cbc2aa;
border-bottom: 1px solid #cbc2aa;
color:#000;
border-radius:.3em;
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];
tray.classList.remove("shake");
void tray.offsetWidth; // trigger a DOM reflow to reset
tray.classList.add("shake");
// 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) {
tray.style.animation="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() {
shakeit();
addshakecontrol();
}
Title image by Rich Brooks.
![]()
Follow me on @mattjamestaylor
Web design
Architecture
Life drawing
Art gallery
Synesthesia
Comics