Joni Korpi

Designer & developer, websites & indie games.

Joni Korpi

Hey there, I’m Joni, an independent web designer and developer based near Helsinki, Finland. I’m specialized in things like interaction design, web typography, and front-end development, with over a decade of experience in building things for the web. Right now I’m spending my time (and savings) using the web platform to make video games.

The best ways to contact me are Twitter and email: @joni­korpi, me@­joni­korpi­.com, but please note that I’m not currently looking for any new freelance work.

Kisko Labs

If you’re looking for help with design or development, you should contact Kisko Labs. I’ve worked with them since 2012, first as a full-time employee and now as a freelancer. During those years I’ve participated in over 50 projects, working on everything from digital textbook designs to complex web application user interfaces. I highly recommend their services.


Vuoro Design is my one-man company. I develop indie multiplayer games using the web platform. The first two of my games are currently under development: Valtameri is about ponderous real-time strategy and travel, while Valtakunta is about turn-based strategy on a massive scale.

I also maintain Kausi, an app somewhere between a to-do list, a calendar, and a journal.

— experimental layout systems, 2013–2015

A progress update on my work with zoomable UIs on the web

After releasing my first iteration of a zoomable UI for the web, I’ve been working on these three key issues:

  1. Making the UI less modal.
  2. Showing more of the document’s actual content before it’s zoomed in.
  3. Focusing the UI on navigating vertical documents.

Here’s a CodePen prototype of what I have right now (unlikely to work in Mobile Safari).

In the first iteration you:

  1. Looked for an interesting article or category.
  2. Clicked it to zoom in.
  3. (Clicked an article, if you only zoomed into a category.)
  4. Scrolled vertically to navigate the article.
  5. Clicked a button or hit ESC to zoom out.

In this new iteration you:

  1. Scroll horizontally through categories and center on an interesting article.
  2. Scroll vertically to zoom in and keep scrolling to navigate the article.
  3. Scroll back up (“scroll to top” shortcuts should work) to zoom out.

I find this new model much more pleasant to use. I think it’s because clicking feels like an inherently modal action, taking you out of the context you were just in. Much like walking to another room and closing the door. Clicking on something feels like a commitment. Compare it to scrolling. It’s so effortless that throwing a page up and down and catching it mid-movement actually feels fun.

Of course, there are still many issues with this new iteration.

  1. I’m relying heavily on CSS Scroll Snapping, which doesn’t even exist in Chrome yet. I “polyfilled” it with a manual snap that happens 100ms after the last scroll event fires, but it feels like crap compared to the native snapping in Safari and Firefox.

  2. Horizontal scrolling is really annoying with bad trackpads and almost all mice.

  3. I’m 3D-transforming a super-massive wrapper to move massive articles around, so performance can be poor. This would be an issue even if I moved each article individually, since performance is a core problem with ZUIs on the web. Browser engines were not designed for displaying lots of zoomed-out versions of large elements.

There are a few possible workarounds to issue #3, each with their own problems:

  • Making the elements tiny and zooming them in instead of the opposite: ruined by browser min-font-size settings.
  • Just resizing elements instead of transforming them (which I did in the first iteration): min-font-size settings again, image resizing causes lag, text reflows cause massive lag.
  • Creating thumbnails and replacing them with real content just in time: animation timing issues, thumbnail creation is a deep pit.
  • Rendering everything in WebGL: promising, but not ready for general use.
  • And so on.

If you have a really good idea how to solve this, let me know on Twitter.

P.S. For more on designing less modal UIs, check out Jef Raskin’s The Humane Interface. Wikipedia has a good summary of some of its most important lessons.

— experimental layout systems, 2013–2015

An alternative to in-site hyperlink navigation

(This post refers to a previous version of this site.)

I’m afraid to click things on websites. Often the result is either:

  1. A jarring full-page reload. Even though browsers try to avoid the “flash to white” effect now, an entire page’s worth of elements blinking out of existence and another bunch blinking back in is difficult to follow. It feels like teleporting from one room into another. It makes me lose my train of thought. And even though the transition isn’t actually that slow, it feels slow.
  2. An arbitrary animation. One that either brings in new content from a random direction, transforms the entire page into another, or causes an element to morph into something else. Many well designed sites found in galleries like siteInspire do these things, which even lead me into writing this dumb tweet a while ago.

I’ve been searching for ways to improve on this issue for a long while now. After making some detours with concepts like the Infinite Canvas and bi-directional scrolling, I landed on zoomable user interfaces.

Jef Raskin’s ZoomWorld, described in his book The Humane Interface, is just about the only serious ZUI design outside map browsers that I’ve stumbled into. For some reason ZUIs never really made it out of the early 2000s. Maybe it was the technical issues related to building them (I’ve certainly run into a pile of them so far), the lack of input devices designed for them, or just pure chance. Either way, I’m giving them a go!

This site is the first working zoomable UI design I’ve produced. Here’s a list of things I think are cool about it:

Navigating through posts and categories feels like I’m still in the same “system”. The site feels less like a collection of separate documents, and more like an app where each URL points to a different state of it. Traveling between states feels like a fast continuum of actions, unlike browsing separate documents. It helps me keep my train of thought.

There is no home page or navigation menu. These two elements are usually among the hardest to design, so I’m glad to be rid of them. In this design, they’re both replaced by the same thing: a zoomable view of the site’s contents. The content itself is the navigation.

Every article feels like it has a spatial location on the site. The zooming animation helps me understand where elements come from and where they’re going. I’m trying to aim for a system that makes me think “the article with yellow bars somewhere in the bottom left” instead of “the article named _Golden Grid System_”. This effect was stronger in some of my previous prototypes, which used a “dive in closer to the canvas” type of system instead of the current “bring that object closer to me”, but this one is more suited to the web’s technical constraints and seems less likely to cause issues with motion sickness.

Permalinks, browser history, animation-free browsing, and JS-free browsing are supported. The different between a zoomed-in post and a non-zoomed-in one is a couple of classes and some AJAX-loaded markup. It’s easy to render on the server-side when visiting a permalink. This also means the site is browsable with traditional full-page reloads, for people with motion sickness and for times when JS isn’t available.

You can hit ESC to zoom out. It just feels right. I’m working on doing something similar for touch screens with a pinch gesture.

You either zoom or scroll. Never both at the same time. The home view, the “map”, the “bird’s eye view” or whatever you want to call it always adjusts to the viewport’s shape and size. It never overflow-scrolls. The idea is that zooming is the way to handle its overflow. As more articles get added, they get grouped into more zoomable categories.

The fluid “covers” for each article are pure HTML/CSS. Since I’m actually resizing articles instead of using scale transforms — proved troublesome in a previous prototype, which I’ll write about in another post — I can’t show their actual textual content before they’re zoomed in. I added the “covers” to still have something recognizable there when navigating the site. I started off with bitmap images, but found that they too are a no go: too laggy to resize. Eventually I tried a pure HTML/CSS illustration for one cover, and found that they’re really cheap to resize. The constraint of illustrating with nothing but box elements turned out to be fun, and here we are.

I’m not the only one currently thinking about UIs like this. Some sites have begun using zooming as part of their designs, and there’s a lot of talk about making UIs more “spatial”: (Spatial Interfaces is required reading on the subject). I think this is a good trend.

Either way, making this site has been a blast. Let me know what you think about it on Twitter.

Before I go, I’d like to thank the following awesome people for their feedback on and help with various prototypes of this design.

P.S. The resizing technique, rem-units, and some of the history-related JS I’m using cause issues in some older browsers. I’m also a little worried about SEO and accessibility, since the nested DOM structure is weird. I’m working on it!

P.P.S. ~~The code is available on GitHub, but it’s messy.

Update: I posted a progress update on my work since this post.

— experimental layout systems, 2013–2015

Improving responsive layouts using 2D scrolling

(This post refers to a previous version of this site.)

This site previously used an experimental layout that attempted to solve the following problems:

  1. Designing a responsive layout that makes use of large screens.
  2. Cutting down on the amount of time it takes to design and build a good responsive website.
  3. Making the results of a responsive design process more beautiful.

Here’s how it worked:

  • Each section on a page is stacked horizontally.
  • A section’s content flows vertically.
  • If a section’s content is taller than the viewport, the section becomes scrollable.
  • A section is never wider than the viewport.
  • A section is never wider than what is optimal for its content.

The result is a bi-directional layout. Unlike in a traditional vertical layout, you can quickly scan through each section by scrolling horizontally, and when you find an interesting one, you can drill down on it by scrolling vertically.

Also, the design of each these sections only requires 2 of the 3 states of a responsive design: just right and too small. The horizontal stacking takes care of too big. This leaves more opportunities for making interesting design decisions and cuts down on development time.

— CSS grid systems, 2010–2011

A recipe for building an infinitely adapting fixed-width grid

Frameless is the spiritual successor to Less Framework. It’s an adaptive fixed-width grid system, but it doesn’t have any predefined column configurations. The idea is to set a column and gutter size, and use as many columns as fit on the screen and you happen to need.

Although I published Frameless with a couple of templates, which are still available on GitHub, like my other grid systems, Frameless is just a set of instructions. It doesn’t contain any code that you need to use. The recipe is as follows.

1. Make a regular fixed-width grid.

Use whatever criteria it is that you usually use to create fixed-width grids: pick a column width, a gutter width etc. Don’t worry about the amount of columns just yet.

2. Make it repeat infinitely.

Give the grid and infinite number of columns, so that no matter how wide you make your screen, more and more columns come into view.

3. Center it in the viewport.

Align your grid horizontally to the middle of your screen. For a grid with an even number of columns, align the center point of your screen in the middle of the gutter between your two centermost columns. For an odd-numbered grid, align it in the middle of your centermost column.

4. That’s it, really.

Start using the grid. Whenever you need more columns and they fit on the screen, use them. But don’t try to spread your design to always fill up every column available on the screen. Adapt column by column, not pixel by pixel.


Frameless received an adequate amount of attention when published, but not as much as my previous grid systems. Most of the sites designed using it have since vanished or been redesigned.

— CSS grid systems, 2010–2011

A folding grid system for responsive design

GGS was my next step after Less Framework. Instead of a fixed-width grid, it used a fully fluid-width one, without even a maximum width. The resources it was published with are still available on GitHub.

Folding columns

The idea was to take a 18-column grid, use the outermost columns as margins, and use the remaining 16 to lay elements out. On smaller screens the 16 columns could be folded into 8, 4 and 2. This behaviour was inspired by Massimo Vignelli’s Unigrid system.

Elastic gutters

While the grid’s columns were fluid — proportional to the screen’s width — the gutters (spaces between the columns) were proportional to the font-size being used. This decision was an attempt to mitigate a big issue with fluid-width grids: no link between the proportions of the columns and the proportions of the text inside them.

Zoomable baseline grid

GGS also contained a set of typographic presets, strictly to a baseline grid. As long as all font-sizes, margins, paddings and other measurements that affected the page’s flow were set in ems and properly aligned, the page would retain a perfect vertical rhythm. The abovementioned elastic gutters were also proportional to this rhythm. Since all of these measurements were set in ems, every element on the page could be zoomed in or out to better fit inside the fluid-width columns as needed.

Golden Gridlet

Correctly setting all of these measurements is difficult, of course. I tried helping this issue by creating a little script that overlaid the Golden Grid System on the page, along with its baseline grid.


When published, GGS gained a lot of attention, as the web design community was searching ways to work with fluid-width grids, which have always been troublesome, running counter to many graphic design principles. In practise, however, GGS didn’t work very well. Using fully fluid-width columns for text is impractical. Without a maximum width of some sort, you’ll always end up with either text blocks too wide or a font-size too large.

Many people trying to use GGS were also confused by the lack of predefined code for working with the grid. Like in Less Framework, I tried to advocate forgoing predefined layout code and only offered measurements and visual templates for using the grid system. That wasn’t enough. The result was an avalanche of requests for tutorials on Twitter and various web development forums, which I failed to address while trying to focus on finishing my degree.

Later on I developed Frameless, the last entry in my early CSS grid system saga.

Oh well! This project certainly taught me to spend more resources on communicating my ideas, even after they’re published and done.

— CSS grid systems, 2010–2011

An early adaptive CSS grid system

I called Less Framework “a CSS grid system for designing adaptive websites”. It was basically a fixed-width grid that adapted to a couple of then popular screen widths by shedding some of its columns. It also had matching typographic presets to go with it, built with a modular scale based on the golden ratio. The resources it was originally published with are still available on GitHub.

Guidelines over code

Contrary to how most CSS frameworks work, Less Framework simply provided a set of code comments and visual templates, instead of having predefined classes to control the layout with. This is how I still work today and definitely a method I advocate. Predefined layout code makes too many assumptions, getting in the way whenever I try to do anything different.

/*    Default Layout: 992px.
      Gutters: 24px.
      Outer margins: 48px.
      Leftover space for scrollbars @1024px: 32px.
cols    1     2      3      4      5      6      7      8      9      10
px      68    160    252    344    436    528    620    712    804    896    */


Less Framework was popular in the early days of responsive design. (It actually launched around the same time as LESS. That was quite a naming conflict.) With articles written on sites like Mashable and Sitepoint. It ended up helping design various sites and even being used as part of other frameworks, like 320 and Up.

Eventually, I moved on from fixed-width grid systems and worked on a fully fluid-width one, in the form of Golden Grid System. Later, I revisited the fixed-width grid concept in the form of Frameless.

Less Framework’s popularity was helped by the following contributions and the lovely people behind them (dead links crossed off):

— old writing, 2010–2012

An unexpected opportunity to control how the page loads, using Typekit

(This post refers to a previous version of this site.)

I finally have a blog. For the longest time I haven’t been able to let out the endless rambles about all the little design detail and theories bouncing around in my head. Now I can, and will.

I’m going to start by going over a little trick I discovered when designing this site. When you opened this page, you may noticed that it took a moment longer to load than usual, and that it didn’t just blink into existence, but faded in.

The culprit behind the extra loading time is the asynchronous Typekit snippet, which loads the web fonts used on this site. Unlike the regular Typekit snippet, the asynchronous one doesn’t automatically protect you against the Flash of Unstyled Content that can happen if the fonts don’t load quickly enough, so I had to take care of that manually.

I had to make sure no text elements on the page would show until the fonts have finished loading. To accomplish this, I simply set the opacity of all text on the page to zero using the .wf-loading class provided by the Typekit snippet. I also added a fallback for versions of IE that don’t support opacity.

.wf-loading h1, .wf-loading h2, .wf-loading h3,
.wf-loading p, .wf-loading li {
  opacity: 0;
} h1, h2, h3, p, li {
  visibility: hidden; /* Old IE */

While playing around with this, I realised I could also control how the text eventually appears after the fonts have finished loading. By adding a very short CSS transition, I could make it fade in.

This should work in most modern desktop and mobile browsers, including IE9. The fade-in might feel a bit laggy on underpowered computers and mobile devices that don’t use GPU rendering, but that’s okay, since it’ll feel more or less just like a regular blinking-into-existence page load.

h1, h2, h3, p, li {
  opacity: 1;
  visibility: visible; /* Old IE */
  -webkit-transition: opacity 0.24s ease-in-out;
  -moz-transition: opacity 0.24s ease-in-out;
  transition: opacity 0.24s ease-in-out;

There was one downside though: hiding the content made the initial load seem slower. Even though the site is progressively rendering into existence in the background, we can’t see it, which makes the load time feel longer.

To alleviate this effect, I added a little loading spinner as a GIF image. Since the spinner needed to appear immediately, I embedded it into my stylesheet using a data URI. I used Opinionated Geek’s Base 64 encoder to encode image and embedded it as follows:

.wf-loading #content header {
  background: url(data:image/gif;base64,lots-of-base64…) center center no-repeat;

This should work just fine in all modern browsers, including IE8–9. IE6–7 will simply ignore it, which is fine by me. This is just a minor detail after all.

Loading spinner vs. no loading spinner
Before and after. The spinner makes it clear something is happening.

The resulting effect is pretty interesting, isn’t it? It doesn’t feel like a regular HTML page load, but not exactly like an AJAX load either.

This technique could also be applied to images or even the entire page. Theoretically you could even create all sorts of Powerpoint-esque transitions using CSS transforms. It’s good to practice restraint though, as these effects can be quite performance-intensive. Also, the simpler and faster the transition is, the less likely it is to annoy anyone — good transitions are felt, not noticed. Personally, I think this one turned out pretty good, but I’d love to hear your opinions about it on Twitter.

Update on 23 Jul 2011: The IE fallback was causing the fade-in to feel jerky in Safari, so I split it off into a separate declaration using an IE conditional class. It will probably not work in IE6, but will in IE7–8.

Update on 2 Aug 2011: The fade-in on this site is currently disabled while I’m investigating whether it has something to do with the mysterious plummeting of this site’s Google ranking.

Update on 10 Aug 2011: The fade-in is back in action. It doesn’t seem to have caused my ranking problems.

— old writing, 2010–2012

Using media queries to make a clean break from legacy browsers

(This post refers to a previous version of this site.)

This site was designed Mobile First. The styles that make up the mobile version of its layout, which I’ll call the Narrow Layout from now on, are not inside a media query, while the styles that make up the wider versions are. As a result, browsers with no support for media queries will only see the Narrow Layout. This is a good thing.

Instead of enabling media queries in the browsers that don’t support them, like Internet Explorer 6–8, I chose to simply serve them the Narrow Layout, slightly enhanced with Paul Irish’s IE conditional classes.

For example, I gave the layout a static width to make sure the content never stretches uncomfortably wide, and made sure images always display at full size, since I had halved their maximum sizes in the Narrow Layout.

As a result, old mobile browsers will see a fluid single-column layout, and IE6–8 will see a similar static-width layout, perfectly comfortable for reading even on larger screens.

This site in IE7
This is roughly what this site looks like in IE7.

body {
  width: auto;
.ie body {
  width: 540px;

#content figure {
  width: 240px;
  max-width: 100%;
.ie #content figure {
  width: 480px;

So that’s old IE and old mobile browsers taken care of. Now comes the fun part. Since I can be sure that legacy browsers won’t be seeing any of the wider versions of my layout, I’m free to design them with the assumption that they’ll be viewed in a browser that supports such luxuries as…

  • 2D transforms
  • CSS2.1 selectors: + > [attr]
  • most CSS3 selectors
  • :before and :after
  • opacity, box-shadow, and text-shadow
  • min/max-width and min/max-height
  • box-sizing and inline-block
  • rgba() and hsla()
  • and even root-ems!

Suddenly all the shackles imposed by old IE are gone. I can even use margins on floated elements. I’ll just let that sink in for a moment.

I think I’ll be using this technique to deal with legacy browsers from now on. It requires no Javascript, no hacks, no separate stylesheets, and barely any effort, since single-column layouts rarely require the kind of advanced positioning that IE6 will have problems with. In this site’s case, I had to write less than a dozen lines of CSS to make the Narrow Layout comfortable to view in old IE. Simple, effortless, and oh so liberating.

— old writing, 2010–2012

Adaptive Web Design: as applied to the design process of a web application

The full thesis is available as a PDF, but you can read the abstract below.


This thesis explored the usage of adaptive web design techniques in the design process of a reservation and inventory management web application, New Reserve. It attempted to uncover issues a designer is likely to face when moving from a traditional web design process to an adaptive one.

Most issues uncovered were related to keeping visual design appealing and attempting to support multiple input methods, such as touch screens and mice, at the same time.

Using a fluid grid for visual design was found to be difficult, as they caused problems when elements start stretching beyond their optimal maximum dimensions, and when element dimensions are determined in a mix of percentage units and absolute units. Intentionally leaving empty space in wide designs and using the alternative “border-box” model were found to alleviate these problems.

Using the “Mobile First” approach for design was found to be recommended, as the amount of mobile internet users is set to overtake desktop internet users very soon. The approach also helps in keeping designs cruft-free. Making images adapt to mobile sizes and bandwidth restrictions was found to be difficult, but there is hope for a standards-based technique to deal with this in the near future.

Using progressive enhancement was found to be the key in developing a web application with features accessible by a wide array of devices. Forcefully adding support for features using polyfills was found to require caution, as a single polyfill may not be suitable for all input methods.

— old writing, 2010–2012

A magazine article on using fixed-width layouts with responsive design

This is an article I wrote for .net Magazine #211. I’m rehosting it here, since they’ve since made their old issues inaccessible on the web.

(You can also view this article as the original print PDF.)

Responsive web design, a method coined by Ethan Marcotte, has been getting lots of attention lately. In its simplest form, it uses a flexible grid to create a fluid layout, and media queries to spot-fix any problems that crop up when the structure gets too wide or narrow. It’s great, and is really paving the way for more adaptive websites.

But responsive design is all about fluid layouts. I still prefer set widths.

That’s fine, but we static designers haven’t quite updated our tactics to deal with the myriad screen sizes in use today: 960px isn’t good enough any more.

Media queries are the key elements of adaptive websites. We could simply use them to create an optimised layout for all the most common screen sizes in use today, each with their own pixel-based grid. The result would likely be a set of layouts that would look good by themselves but that would be out of keeping with one another.

For example, say we made layouts for 320px, 768px, 1,024px and 1,280px. The optimal grids for each of these would require different column widths, which would mean slight changes to the dimensions of elements, creating the feeling that each design is slightly different from the other. This kind of deviation is bad.

Also, who really wants to construct four grids for a single website? Instead, why not create a system that makes it efficient to form multiple layouts and keeps them as consistent as possible.

Now imagine that we’re designing a grid for a brand. It would have to retain its proportions despite the size of the media it’s projected on: business cards, stationery, billboards and so forth. It would most likely be scaled up and down to fit, and the content inside it would simply change size with it as required.

In website layouts, however, we can’t just scale whatever’s in our grids whenever the screen size alters. Generally, we want all the text and element measurements to remain the same, ensuring a feeling of familiarity across each design.

Composing the grid system

We’ve established that column widths must remain the same across each layout. So must the gaps between columns, since they would change the dimensions of elements that span multiple columns. We’re left with two things to fiddle around with: the margins around the grid and the number of columns.

I’m going to use Less Framework – a CSS blueprint I’ve built – as an example. In it, I use a column width of 60px, and 24px gaps between columns. I’ve found these dimensions to be remarkably flexible. With them, I can create layouts with three columns and 46px margins (320px), five columns and 42px margins (480px), eight columns and 60px margins (768px) and 13 columns with 72px margins. There’ll still be space left over for browser chrome (1,212px), and it’s easy to add an 11-column option with 42px margins (984px) if it’s needed.

In a system like this, elements created for one layout are often reusable in others. For example, a block of text three columns wide will fit into any of the layouts as it is, and an image six columns wide can be scaled down to 50 per cent to slot into the three-column layout, taking advantage of the iPhone 4’s double resolution.

Implementation is simple. First, pick a default layout. This will be served to all browsers that are incompatible with media queries. I use the 768px one, but 984px is a safe bet. Write the CSS for this layout normally, with no media queries applied. Then write the other layouts inside an inline media query. They’ll be used by all modern desktop and mobile browsers and inherit styles from the default layout, so you won’t have to write too much extra CSS; you’ll just be overwriting as necessary.

Browsers that are incompatible with media queries – most notably Internet Explorers 6-8 – will ignore every style declaration inside an inline media query, using the default layout. However, you can use JavaScript to add support here. At the time of writing, css3-mediaqueries.js seems best.