Making o(m)g:image, Part II: As Little JS As Possible
This is part two of my series of posts describing how I made my quiz game o(m)g:image.
- Project Announcement
- Pt. I: Design Iterations
- Pt. II: As Little JS As Possible
One of my goals when making this project was to use as little JavaScript as possible.
In retrospect, I have to admit that was a pretty ambitious goal. Not because it was hard from a technical point of view, but because it was hard from the point of view of human nature.
Allow me to explain.
I write a lot of JS for my day job. And I write a lot of JS for other small projects (not necessarily websites, but scripting data, tools, etc.) And when you have the great and might hammer of JS, every solution looks like a nail.
So it required a lot of self-discipline to avoid mindlessly falling into the practice of throwing JS at every problem I wanted to solve.
For example, I couldâve made this whole site as a âsingle page react appâ. But Iâve done that on prior personal projects and now I donât want to ever touch any of those projects (I also hope I wonât have to). I mean, weâre talking projects with React before its major version jump, like React 0.14.x with webpack/babel/etc. (Oh young Jim, you didnât understand as well back then.) But Iâm a little smarter now, so my goal on this project was: as little JS as possible.
But JavaScript is like a smartphone: as much as you donât want to use it, you canât help yourself. Again, it required a constant, mindful willingness to keep stepping back and asking myself, âCan I do this without JavaScript â if possible?â
In the end, I like where I landed. Every âquestionâ is an HTML page. Every âanswerâ is an HTML page. Even the ânavigationâ where you can see how all the questions, is an HTML page.
For example, at one point I wanted to have some navigation on each page. My first thought was something interactive on the page, like a widget that says âQuestion 4 of 12â, you click on it, then it expands and shows you all the questions on the quiz, including which ones youâve answered and whether you got them right or wrong.
How do you do that without using JavaScript?
At first I thought, âUse a <details>
element, it wonât require JavaScript!â But as I thought through the ramifications, I wasnât in love with the solution.
The more I thought about it, the more I wanted to reach for JavaScript: a fancy slide out drawer, a slick popup menu, an in-place expand. So! Many! Options!
But I wanted to avoid JS as much as possible â âonly for whatâs absolutely criticalâ I told myself. Could I show/hide navigation with only HTML?
What I landed on was navigation as an HTML page. Every page has a little piece of information that tells you what question youâre looking at, e.g. âQuestion 1 of 12â.
If you click on it, rather than expanding the navigation inline, or popping out a drawer with the navigation, or doing something else that requires JavaScript to reveal the information, it simply takes you to a new HTML page with the information. (The browserâs back button serves as the equivalent of a âclose drawerâ or âcollapse thisâ JavaScript solution.)
The only enhancement to the game that actually uses JS is the part that keeps track of which questions have been answered and whether the answer was correct or not. If you have JavaScript enabled, you will see this information additionally layered onto this navigational pageâs UI.
With this approach, Iâm truly using JavaScript for what JavaScript alone can do which is keep track of client state (you might argue I could have a server with a session here, but another constraint of the project was no server, so yeah).
This HTML-first approach really drove the design of the site. I had to ensure that navigational elements always stayed at the top of the page in consistent places across pages to ensure the UI didnât jump as you navigated around (from the top of the page). My goal was to make the site so lean and so fast, that multi-page navigations felt as close as possible to in-place, on-page interactions.
Iâm pretty happy with where the project ended up technically. I think it holds a great tension of low-cost maintenance for me over time, but still a great, solid experience for end users across a wide variety of devices â and, hopefully, across a long period of time.
The whole exercised really impressed on me once again that sometimes we just need to build simpler UIs. If your frontend is hard to build, itâs probably hard to use. If you make it easier and simpler to use, itâll likely be easier and simpler to build and maintain.
That said, the irony here is that itâs actually quite hard to build something like this because you have to make ruthless choices about cutting things that arenât absolutely necessary.
In other words, building websites backed by MBs of JavaScript is hard. You know whatâs even harder? Questioning whether you actually need to build what youâre building, and cutting it down to the essentials. (HTML is really good at essentials.)
It reminds me of that old saying about how shorter writing requires more time, except for websites, i.e. âMy website is lots of JavaScript. If Iâd had more time, I wouldâve made it lots of HTML.â