We’ve all been there — someone left a dirty coffee mug on display, turned off the light in the bathroom when we were there or forgot to replace the toilet paper roll with a fresh one when you most needed it. We are all people and office etiquette can sometimes be a bit lacking, especially when we’re in hurry or absent minded.
After being fed up with being left in the darkness for that one time too many, I’ve decided to jokingly remind people on basic office rules that should be upheld by everyone. What started as a little tongue-in-cheek joke turned into a pretty interesting side project, so I’ve decided to write this blog post and tell a little more about it.
This was not my first office project like this so I was tempted to just rehash my old idea of making climatic posters. After a bit of consideration, I’ve decided against it as I wanted to proceed with something more original. In the mean time I had a great idea for an office game based on Lifeline but with more complicated, spatial-based mechanics (I’m not writing more about it here because I still hope I’ll build it one day) that would take way too much time.
I’ve decided to mix those two and that’s how it all began. Mechanics of the game were super simple — there were 8 stickers hidden around the office, each with a QR Code, an image and a (hopefully) funny description. They looked like this:
Once you scan the QR Code you are taken to a website that adds a badge to your backpack. Once you collect all of them you get an extra final badge. Every badge has an icon, a name (not visible on stickers) and a description.
Since I’m usually a web developer, I don’t have a huge graphical talent so I had to improvise. All of the icons are based on the flat design with a shadow, something that was super popular relatively recently (not sure about now). I also very generously stolen borrowed a lot of shapes from the amazing Font Awesome 5 (buying the commercial license as early bird on Kickstarter was one of the best decisions ever!).
The Badge-Collecting App
The main focus of the badge-collecting app was performance. I wanted it to feel instantaneous with almost zero loading time, even on slow Internet connection. When I started working on the project my idea was to just host a bunch of static HTML pages but I’ve been coding in React for so long it was a chore. I’ve also tried experimenting with both preact and inferno but neither felt right and the bundle size was still not satisfactory (after all, the best code is no code at all)
In the end I went with a pretty interesting approach: on the server side I’m using React with Razzle to render the pages, then I push raw HTML to the client and apply super-minimal vanilla JS on top of it. This was the perfect mix because it allowed me to code in something I feel proficient in (and use all component-based good stuff I’ve learned to love) while at the same time what was delivered to the user did not require 100+ KB bundle that would slow everything down to a crawl.
The extra bonus of it all was that it was now impossible to search the app code for the badge URLs ;)
The other selling point of the app were animations. I put a lot of effort to make them silky smooth 60 fps. The most interesting part was animating SVG using only CSS transforms — I have created every icon in Affinity Designer, then exported to SVG and used SVGOMG to minify the file and simplify paths. I then modified all files by hand, adding HTML IDs and wrapping certain elements in groups with
<g/> tag. This allowed me to highly optimise all animations to my needs.
There were several tricks that I used to orchestrate the animation properly:
- Because the animations had to run the moment page was loaded, the delayed loading of the images ruined the composition so I have inlined all SVGs using
- When animating multiple objects I’ve learned that it is much much easier to set the entire animation length to something longer (like 10s) and then control the duration and delay using
@keyframesand percents rather than raw seconds. This made everything more predictable because it felt like moving clips on a timeline in video editor and the individual animations were never out of sync. The frustrating part was that increasing or decreasing the overall time of the animation required recalculating all
%values but if I had to maintain it longer, I’m sure I’d just fix this with custom Sass mixins.
- The trickiest part was animating the shadow on the badge. At first I thought it’ll be just a case of rotating a square and using it as a mask but it was really unpredictable and didn’t look great. In the end, I used a neat little trick with
clip-pathinstead of animating a square I’m actually animating a 5-sides polygon. Why 5 sides? Well:
- The text rendering was surprisingly difficult to control and font loading was the most unreliable part so I’ve created all texts as SVGs with fonts converted to paths. This took less space than loading an entire font, I was able to inline it and also I got predictable scaling as a bonus.
The last goal for this app was to achieve full responsiveness on all possible devices. This was done using viewport width and height units and abusing the fact both SVG and texts are fully scalable. The app works both in the portrait and the landscape mode on either mobile, desktop or tablet and everything is dynamically scaled to 100% width and height.
There is a slightly annoying bug - sorry - a “feature” on iPhone, where the 100% viewport height is actually a bit larger than viewport due to the browser UI on top which means you have to scroll a bit to see the whole picture. Fortunately it wasn’t super bad for this case but it was definitely a bit frustrating.
The Final Result
As the stickers are no longer in the office and I’ve decided to make the whole thing public, you can check out the badges yourself (apologies for SSL being broken but it seems that Heroku ACM only works for paid dynos and I’ve switched the dyno to Free already):
- Squeaky Clean
- Fear of the Dark
- Om Nom Nom
- It’s All About Paperwork
- Let’s Make It Clean
- Blah Blah Blah
- Rinse And Repeat
- and the final badge: Office Revolution!
Unfortunately I won’t be open sourcing this as I didn’t make a list of all icon inspirations and I’d rather not breach any license agreements, sorry!
The most interesting part is in CSS anyway and you can scrap that yourself as a homework (or ping me on Twitter and I’ll send you the SCSS file) ;)
Now go forth, figure out your own fun stuff and troll your coworkers. Enjoy!