Upgrading the Simple 4x4 Grid with JavaScript

John Ex
8 min readApr 30, 2021

In a previous blog, I explained step by step how to make a 4x4 grid with HTML and CSS. At the beginning and end, I said there are better ways to do things, that are more automatic and scalable, and that is exactly what we will be doing in this blog. This is what I did to improve the 4x4 grid for a project I was working on it, so at first, we will be making the same grid, except in Javascript, and then making it better. The project that I reference is the same as the last blog, in which I explain in more detail there what it is.

Re-making the Original

One of the flaws of the last method was that it involved a lot of copy-pasting and wasn’t scalable easily. This means that if you wanted an 8x8 instead you would have to go back in and copy-paste a bunch of times again and everyone knows that if you need to copy-paste a lot, there is a way to automate it.

We can delete the previous code and start fresh with a for loop:

for (let i = 0; i < 16; i++) {}

This is just a simple loop that runs 16 times. This allows us to change the number of boxes we make by changing the number 16. To put this as simple as possible, this will run all the code inside the {} 16 times which means it will make 16 boxes out of the code that we only need to write once.

It is also a good idea to make that a variable so that it can be easily changed in your code, for example, if you wanted to have a button that changes the grid from a 4x4 to an 8x8 when clicked.

let gridSize = 16

for (let i = 0; i < gridSize; i++) {}

Now that we have that we can start filling it in. First thing is to make the actual div.

for (let i = 0; i < gridSize; i++) {

let tag = document.createElement(“div”)

}

!!! Just a note, everything from here on will be inside the loop, placed after the previous code. !!!

With this variable tag, you now have the div that we need to give attributes to. This is done with ‘.attribute = value’ which in our case we will use:

tag.id = i

To set our number id, setting it to i also makes sure it is unique and ordered.

tag.className = ‘gridbox’

This to set a class name that all boxes will have, which we used last time to style all the boxes at once.

tag.style.backgroundColor = ‘black’

This is also something you may want to add to change the color, but it can be done in CSS just like last time. It is generally encouraged to style things in a CSS stylesheet instead of inline like above, but I will explain why and how I will use inline styling for this specific situation.

And lastly, we need to insert it into the site since technically all this only exists in a variable right now. This is accomplished by writing parent.append(child)

grid.append(tag)

‘grid’ in my case refers to the parent div that I'm inserting all the boxes into.

The final product should look something like this:

for (let i = 0; i < gridSize; i++) {

let tag = document.createElement(“div”)

tag.id = i

tag.className = ‘gridbox’

tag.style.backgroundColor = ‘black’

grid.append(tag)

}

Sorry about the missing indentation, medium doesn’t have that feature for some reason.

Now you can use the same exact CSS styling sheet as we used in the last blog and it should work perfectly since the classname for all boxes are the same.

Before we move on I would like to add that the reason for doing it in this way is if you plan on changing it in the future or if there are a lot of boxes that need to be added. It is also good practice to automate things that need to be written more than once.

However, where this really shines is in the ability to add functionality very easily and can access variables, which is the whole reason for Javascript.

In my case, this grid is the main aspect of my game, it is the playing board. Because of that, it becomes very easy for me to customize and add functionality to everything. I will explain the features I added to give you an idea of how powerful this actually is.

Advanced

Inline styling

Coming back to Inline Styling, my reasoning for using it in this project is to access a variable I made:

let colorTheme = [‘black’, ‘gray’, ‘darkgray’]

This allows me to store 3 colors that I can access at any time. If I need black I can write colorTheme[0] instead.

Why?

The initial reason was so that I can use this colorTheme everywhere on the website so that I can later change the theme. Let's say instead of black and gray I wanted a blue theme

colorTheme = [‘#000080’, ‘#000066’, ‘lightblue’]

These are 3 types of blue and now everything on the site will be in that color, this way I don’t need to manually change them all.

The reason its not done in CSS is that I need to be able to change this in Javascript code based on the user input. I used simple divs with onClick event listeners to allow an entire page color theme change, which of course requires a file and code of its own, but is made really easy when all of it is in a single variable. Similar to making a site Dark or Light themed, but in my case Black, Blue, or Red Themed!

Why three colors in the variable?

Simply because I need them, I need one for the outline of everything, one for the dark squares in my game, and one for the light squares.

If you are not familiar with the game I am building, It is just a 4x4 grid that has 14 light squares and randomly positioned 2 black squares that change position when clicked and add to your points. If you click the light square you lose. And that brings us to the second reason for the inline styling.

To set the two random squares to a different color and then change the clicked squares, I used the variable we made before. This is important because it will not change color when the page colors update like we mentioned before if the colors are hardcoded in, instead of using the variable as I do.

The logic used below simply checks if the current i value(aka the id of the current box being made) is inside the variable fullBoxes which is an array that gets populated with 2 random numbers at the start of each round. If true it makes the color of that box whatever color is in the first slot of our colorTheme variable, which I always make sure is the darker one. And if false it sets it to the lighter one which in my case is the third slot of our colorTheme, the light one.

if (fullBoxes.includes(i)) {

tag.style.backgroundColor = colorTheme[0]

} else {

tag.style.backgroundColor = colorTheme[2]

}

I also use the below code to set the outline color of the boxes the same time it is created, making sure it stays up to date with the page theme

tag.style.outlineColor = colorTheme[1]

Event Listeners

Another big reason to make the boxes in Javascript is to add Event Listeners.

There is a ton of stuff you can do with this and you can use any Event Listeners or functions and keyword you want and if done correctly only need to be written once, assuming it's inside the loop.

In my game, it is essential to detect when a box is clicked and then it needs to run the function I made called clicked(). There are a lot of ways to handle a situation like this so I will explain some of the methods that can be used and why I chose the one I did.

When trying to set a ‘mousedown’ event listener to all gridbox tags, it simply did not work, however, if I passed it with the id it worked but only works on that specific one. So I dropped it into the loop and made the id i

gridbox[i].addEventListener(‘mousedown’, clicked )

I used ‘mousedown’ because it feels much smoother for the game since it doesn't activate when the mouse is released, instead of when the click first happens and also making sure the click doesn’t get canceled if it is dragged.

When a box is clicked it is run through an if statement determining if it is a dark or light square to know if it should add points and reposition it or if it should end the game.

An alternative method would be to add the Event Listener into the conditional that already checks for the box color, used earlier in the same loop to set the color. The advantage of this method is that you can send it to two different functions based on what needs to happen, thus avoiding the extra conditional in the clicked function.

The reason I did NOT use this was for two reasons. First, it breaks the game because let's say the first square is a dark square and it is clicked. It will become light but the function it's attached to won't change unless we tell it to, which is a lot of extra steps since I also need to change the function attached to the new dark box. By testing for the status of the box in a function that all boxes use, it takes away a lot of reassigning that otherwise would need to be done.

And the second reason is that I want to keep my box logic in a separate file for organization purposes, which should not be overlooked because a bug WILL show up, and digging through a mess of a loop that already has a lot in it, will be a nightmare.

New Game Modes

The game is currently in a very early stage, in which only the base game is finished with a few features, however, I plan on making a lot of different game modes. Having access to variables such as gridSize will make doing that much faster and easier, and a lot less likely to break or have bugs.

I am also able to make copies and mess around with more Javascript code that opens up a whole new world of possibilities.

Conclusion

Now you know how to more efficiently make the same 4x4 grid and add A LOT of new features and other things to it. This upgrade made my project possible and a lot quicker than it would have if I didn’t take the time to make the grid more efficient. If this blog is confusing, start with the previous one that explains what it is we are making at the simplest level and then come back to this one which will make things significantly better. I also encourage you to look up and make functions and other tools that can take advantage of this method, and the power of Javascript. I do think the method of the last blog has its place, as it is easy for anyone to understand, which makes for a great learning experience, but also it doesn’t use Javascript which means someone making a site in only HTML and CSS can use that method and understand it before moving on to Javascript.

--

--