A Keyboard Display using CSS Grid
Tags: css, sass, grid, html
Published: 2018-04-16 16:39:07

---
title: A Keyboard Display using CSS Grid
published: true
description: Using CSS grid to create a non-interactive on-screen keyboard.
tags: CSS, SASS, Grid, HTML
cover_image: https://thepracticaldev.s3.amazonaws.com/i/grj7003d3u75qaa3qyfa.png
---

# A Little Context

I'm certainly not an expert web developer/designer, so I get excited when I discover tools that make my life easier. At the moment, I'm excited about CSS grid. I have known about CSS grid for awhile, but I just now encountered a project that gave me a real idea as to why CSS grid is so great. I'd like to share a little bit about this experience.

I do online math curriculum development (and teach math) for a living, but I recently started doing freelance web development work (because I really enjoy learning about web dev.). I started working on a project for a client, that consists of creating web-based typing lessons. *Part of the requirement was to create a non-interactive on-screen keyboard where the keys light up on keystroke.*

This was going to be an interesting task, because the layout of keyboards is not very "rectangular," in the sense that keys are offset and some keys are wider or taller than others. Here's what I ended up with:

 ![Keyboard preview](https://thepracticaldev.s3.amazonaws.com/i/6ubmcrp40c3np2yfxzzy.png)

# Bringing in "The Grid"

I noticed that 15 "normal sized" keys fit on a single row of the keyboard, but some rows contain a mixture of "wider" keys and "normal" keys. To handle this, I ended up splitting the keyboard container (the QWERTY keyboard, left side of image above) into `15*4 + 14 = 74` tiny little columns. Each "normal" key spans 4 of these columns, each gap between keys spans 1 column, and the wider keys span a variety of columns. Each row of the keyboard spans just 1 row, whose height is 4 times as large as the width of each column. This is shown here:

![Keyboard grid](https://thepracticaldev.s3.amazonaws.com/i/grj7003d3u75qaa3qyfa.png)

To do this, I had a grid container `div#qwerty_container` to place all of the keys, and then all of the keys are direct children of this container. The CSS (I'm using SASS) for this container is as follows:

```sass
$key_size: 32px

#qwerty_container
    display: grid
    grid-template-columns: repeat(74, $key_size/4)
    grid-template-rows: repeat(5, $key_size)
    grid-column-gap: 0px
    grid-row-gap: $key_size/4
```

The `display: grid` indicates that this element has a grid layout. The `grid-template-columns` indicates the size of the columns, and I used the CSS `repeat()` function to save myself a lot of typing. Similarly, the `grid-template-rows` indicates the size of the rows.

Then, each child of this container is applied a class prefixed by `.g-` to indicate how many columns it should span. As an example, a normal key would have the class `.g-4` and this class contains the following:

```sass
.g-4
    grid-column: auto / span 4
```

That's about all it takes! The `grid-column: auto / span 4` indicates that this class shouldn't affect the starting column of the element, but the element should span 4 columns. I had my list of keys in a JS array, along with how many columns they should span, and then looped through this array and output the grid elements using Vue.JS. Pretty clean!

# Why not Flexbox?

I'm not a CSS expert, but I think this could have been done using Flexbox, because I didn't really do anything "vertical" in nature. However, the number pad on the right side (see the first image) has keys that span multiple rows. Now, this is a place for the grid to really shine! I created the number pad in essentially the same way as the QWERTY keyboard. This is what the grid looks like for the number pad:

![Number pad grid](https://thepracticaldev.s3.amazonaws.com/i/8h999sc8i013wkvfzroc.png)

However, the Plus and Enter keys both span two rows. Two handle that, I merely added an id to both of those keys and added a mere three extra lines of CSS for each of those keys. For example, say the Plus key has an id of `numpad_plus`. Then we could add the following to our SASS file:

```sass
#numpad_plus
    grid-row: auto / span 2
    height: 100%
    justify-content: center

```

In this case, the `grid-row: auto / span 2` indicates that this key should start at its "normal row," e.g. we aren't changing which row it starts at, but that the key should span 2 rows. Basically, this key should span two rows (along with the gap between the rows). The `height: 100%` and `justify-content: center` is just for the aesthetics of the keys.

# ... But is it Responsive?

The keyboard takes up a fair amount of horizontal space, so I wanted to make sure it looked good on narrower screens. CSS Grid actually made this pretty easy to implement. I picked a few breakpoints and added a media query at each. At each break point, I chose a "scale factor," such as 0.8, and essentially scaled everything relative to the grid by that scale factor - making the keyboard about 80% of its original size. Without a whole lot of extra work, I was able to nicely "shrink" the keyboard for smaller screens.

# Conclusion

This certainly isn't a comprehensive guide on CSS grid (I recommend [CSS Tricks' article](https://css-tricks.com/snippets/css/complete-guide-grid/) for that), but for me, this was an enlightening experience and opened my eyes to the beauty of the grid. I thought I'd share this experience with others. 

I'm also aware that I barely tapped into the potential of the grid - which is pretty exciting, because that means I have plenty more to learn and experience with the grid!