Let's create an accessible tic-tac-toe game.

Let's create an accessible tic-tac-toe game.

Savvas Stephanides's photo
Savvas Stephanides
·Nov 23, 2021·

6 min read

Featured on Hashnode

Table of contents

  • 1. What we're making
  • 2. The basic game code
  • ♿ Accessibility enhancement 1: Contrast
  • ♿ Accessibility enhancement 2: Keyboard accessibility
  • ♿ Accessibility enhancement 3: Screen reader support
  • Conclusion

We all love a game of tic-tac-toe. It’s simple, it’s fun and a good pastime for all ages. It’s also great as a project to practice learning a new programming language or tool. This tutorial will do exactly that, but with a twist you haven’t seen before. We are going to create a tic-tac-toe game in Javascript, and learn about accessibility along the way by making our game accessible to everyone.

We'll start by making the code for the basic game, but you can skip to the accessibility enhancements if you want to skip the first part.

1. What we're making

In this tutorial, we are creating a typical tic-tac-toe game. In case you need a refresher on how it works:

This game is played by 2 people on a 3 by 3 grid. One player is assigned “X” and the other “O”. Each player takes turns adding their flag to the grid. Whoever completes a line horizontally, vertically or diagonally wins the game.

We are going to code this logic in Javascript, and create the interface in HTML and CSS

We are then going to make the game accessible. This means:

  1. Every element will have sufficient contrast
  2. The game can be played fully with a keyboard
  3. The game should be screen reader accessible

Here's a working demo of how the final game will work.

Let’s begin by coding the logic in Javascript.

2. The basic game code

For the whole initial game code before the accessibility enhancements, see the Github repo .

Game logic (Javascript)

We start building our game with the game logic, built with Javascript. How you implement this is up to you, as this isn't the important thing here, but the general rules are:

  • The game is played by 2 players, each using a flag: The "X" and the "O"
  • Each player takes turns adding a flag to a 3 by 3 grid
  • Once a line, either horizontal, vertical, or diagonal, is complete, the game is over.

For my own implementation, I have created a Game function and stored in a file called Game.js. See here for the full code for the function.

This function can be used to create a new Game object like so:

var game = new Game()

To play the next round, we use playNextRound() function:

game.playNextRound({horizontal: "left", vertical: "top"})

And to check if the game has ended, we use the gameHasEnded() function:


Other variables include:

  • game.board to get the current state of the board as an array
  • game.flagTurn to get which flag is playing next, "X" or "O"

The UI

Now that we have the logic down, let's create our HTML code to utilise this logic, plus some Javascript to render the game board at gameplay.

The UI is controlled by the GameView function in GameView.js. See full code here.

And finally the HTML is used for whatever is displayed at the user. Full code here.

This is how the initial tic-tac-toe game would look and work (GIF):

GIF demonstration of how the basic tic-tac-toe game looks like

Full code for the initial game

Now let's make it accessible!

♿ Accessibility enhancement 1: Contrast

One of the first considerations when making an accessible application is contrast. By that we mean two things:

  1. The contrast between a piece of text and its background
  2. The contrast between two graphical elements.

For our game, I have chosen two main colours: a light grey and a dark purple. They seem to work well as background colour, tile colours and the colours of the “X” and “O” flags within the tiles.

For the game I have used a shade of purple (#512D6D) with a shade of light grey (#EEEEEE) for good contrast.

Now that we've taken care of contrast, let's move on to another major accessibility topic and how we can improve our game.

♿ Accessibility enhancement 2: Keyboard accessibility

If you noticed in the code, the tiles in our HTML are all basically <div>s. This is great for our tic-tac-toe game but it poses a major accessibility problem: <div>s aren’t “focusable”. That means you can’t access them when you’re pressing Tab on your keyboard. How can we fix this?

One way is to include buttons within the tiles that are only visible when they gain focus with the Tab key in our keyboard.

And when you click the buttons, a flag (X or O) would be added.

We need to make sure our buttons are clearly labelled, such as "Add X flag to top right" so that screen reader users know exactly where the focus is on the board.

Here's the update to the GameView.js file which adds the buttons to the board.

Full code with keyboard accessibility added

Speaking of screen readers...

♿ Accessibility enhancement 3: Screen reader support

As mentioned in the previous section, in order for the buttons to have good screen reader support they must be descriptive of what they do. Which is why button labels are like "Add X flag to bottom left" or "Add O flag to the top right".

But that's not all. Since tic-tac-toe is an interactive game, it doesn't require page refreshing for every click. This makes it difficult for screen reader users to know what's going on in the page. This is where "announcers" need to be introduced.

Announcers, or live regions , are parts of a page where the screen reader announces the content of, whenever that region changes.

To create a live region, we need to assign a role="region" attribute to a <div> tag, as well as an aria-live attribute:

<div id="announcer" role="region" aria-live="assertive"></div>

The aria-live attribute can be either polite or assertive:

  • polite means that the screen reader only announces the change if the user is idle
  • assertive means that the screen reader stops whatever is announcing to announce the change to the user. For our game, we will choose the assertive option.

We can also include a Javascript function in the GameView which updates the region:

function announce(announcement){
    let announcer = document.querySelector("#announcer")
    announcer.innerHTML = announcement

One of the uses for a live region, is to announce the positions of X and O flags on the board at the press of a button.

Suppose we are in the middle of the game and the user wants to know what is where on the board.

At the press of a button called "Announce board", the screen reader will announce:

X flag on top left, center center, center right. O flag on top center, center left, bottom center. No flag on top right, bottom left, bottom right.

Video demo

Complete code with screen reader support


In this tutorial we took one of the most popular games, and one of the most popular choices for apps to develop for programming practice, and took it a step further. We made it accessible, which means that everyone, regardless of ability can play. By adding good contrast to our game, we have ensured that players with color vision deficiency ("colour-blindness") can clearly separate between the game elements. It also helps everyone avoid eye strain. By making our game fully accessible with a keyboard, we ensure that people with certain motor disabilities can play our game. It also helps everyone navigate our game more easily, using a keyboard. Finally, we made our game screen reader accessible, which means players who are blind or have low visibility can hear the current game status and can play just like everyone else. Tic-tac-toe is a fun game and everyone, no matter how they are able to experience the web, deserves to play it.

Have you made your own version of an accessible tic-tac-toe game? What difficulties did you have to face?

Did you find this article valuable?

Support Savvas Stephanides by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
Share this