A Keyboard Display using CSS Grid
Grant Sander

Grant Sander @gksander

About: Software engineer focused on using JavaScript/TypeScript to build full-stack web and mobile apps.

Location:
Valparaiso, Indiana
Joined:
Mar 23, 2018

A Keyboard Display using CSS Grid

Publish Date: Apr 16 '18
42 6

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

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

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:

$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
Enter fullscreen mode Exit fullscreen mode

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:

.g-4
    grid-column: auto / span 4
Enter fullscreen mode Exit fullscreen mode

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

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:

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

Enter fullscreen mode Exit fullscreen mode

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 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!

Comments 6 total

  • Thomas Rigby
    Thomas RigbyApr 17, 2018

    Good work, Grant! Do you have a link to this project online to see it in action? :)

    • Grant Sander
      Grant SanderApr 17, 2018

      Thanks, Thomas! You can check out a sample of it at (sorry, link died) (there's still some work to do for the project, but this is more or less the foundation of it). This is a "right hand, middle row" exercise.

  • Massimo Artizzu
    Massimo ArtizzuApr 17, 2018

    Too bad grid doesn't support non-rectangular areas 😝
    You could've made a classic L-shaped enter key.

    Anyway, that keyboard layout can be done in flex, but you have to create vertically oriented sub-containers, making everything a little complicated. Grid is so nice!

    • Grant Sander
      Grant SanderApr 17, 2018

      I thought about hacking together an L-shaped enter key by essentially combining a horizontal key and a vertical key, but I figured it'd look sketchy and the borders wouldn't look like they should.

      Interesting - that's good to know! I originally did the QWERTY in flex, but figured doing the number pad in flex would be way more work. So I ended up doing both in grid.

      I really like how these kinds of layouts can be done with so little markup. All of the elements are direct children of the container, so the HTML side of things just looks/feels way cleaner.

  • Vinicius Cavalcante Donato
    Vinicius Cavalcante DonatoApr 17, 2018

    nice post! Grid is amazing

Add comment