Kilian Valkhof

Building tools that make developers awesome.

CSS is like music to me

CSS & HTML, 2 August 2007, 3 minute read

The thing with semantic code is, once you care about it, you really care about it. It becomes something you carry with you everywhere. You wake up with it, and you go to bed with it. it’s there when you eat, when you work, when you dream. So you automatically imagine the semantic way of describing, say, a keyboard.

A keyboard?

A keyboard isn’t so hard to semantically describe. There is row of keys surrounded by a nice casing. Let’s rephrase that sentence to HTML elements: They’re an ordered list surrounded by a container. Luckily for us, the ol element is in itself a container already. This leaves us with:


 <ol class="keyboard">
  <li>c</li>
  <li>#/b</li>
  <li>d</li>
  ...add a lot of keys here...
  <li>b</li>
 </ol>

There, a nice list of keys. But: there are black keys as well. And we do need to be able to target those with CSS.


 <ol class="keyboard">
  <li>c</li>
  <li class="black">#/b</li>
  <li>d</li>
  ...add a lot of keys here...
  <li>b</li>
 </ol>

You might say that “black” is a presentational class name based on colour, and that you should call them fis or bes. But, because the black keys are widely known as “black keys”, I consider the classname to be identifying the name of the keys, not the colour. ( ;) )

All right then, now that we have the entire structure, it’s time to head to the presentational layer. Floating all the white keys, giving them a good size and a nice border, all not too complicated:


li {
  float:left;
  position:relative;
  width:20px;
  height:15px;
  padding-top:45px;
  border:1px solid #999;
  color:#000;
  background:#fff;
  text-align:center;
}

Here is where we have to destroy some of the nice and lean code. The black keys look different from the white. They’re a bit smaller, and take a part out of the surrounding white keys. To properly emulate this, we need to add an extra span. As a span is meaningless we’re still as semantic as possible, but the lean code suffers a bit. (Also, don’t forget that span‘s are inline elements, so you need to add display:block; to the CSS.)

The only way to overlap both white keys surrounding the black one is by using position:absolute;. Most of the time you have to specify two offset points (left/right and top/bottom), meaning we would have to target each key individually. But this is where the fun starts:

The trick

Some time ago I found a nice CSS trick that allowed me to make a CSS keyboard fairly easy. When you combine floats and position:absolute;, elements implicitly get a value for the left and top attributes. So you can style multiple elements to look the same, but their left-offset is dependent on their place in the source. Ideal for our keyboard!

This is how the CSS for the black keys looks like:


li.black span {
  position:absolute;
  z-index:2;
  color:#fff;
  background:#000;
  width:10px;
  height:35px;
  padding-top:5px;
  margin-left:-6px;
  border-bottom:2px solid #999;
  margin-top:-1px;
  font-style:italic;
}

We set the position to absolute, the z-index to 2 to make sure that it overlaps it’s right neighbour as well. After that we shift it half it’s width to the left using margin-left:-6px;. The rest is just for looks.

We add a little more styling, some hover and pressing (:active) effects, and we end up with this: A semantic keyboard in html and css. You can play it, too!

Polypane browser for responsive web development and design Hi, I'm Kilian. I make Polypane, the browser for responsive web development and design. If you're reading this site, that's probably interesting to you. Try it out!