Website Technical Overview

I enjoy sharing my photography and automotive hobbies with friends. None of the photo sharing, blogging, or template websites gave me the control I wanted, so I set about making my own. This website is the result — it is focused on speed and accessibility. Here I will take you through the process of construction and many of the decisions along the way.

Fundamentals

A website must be hosted somewhere. With better control as the genesis for the project, it also made sense to manage the host that serves it. The site is hosted on a virtual private server running Ubuntu 14. I have installed Apache 2, PHP 5, and MySQL 5.5 as well as set up monitoring, hardened the server, and configured DNS.

The contents of each page was roughly defined in HTML5 using standard tags. I only used tags which are compatible with a vast majority of browsers. Mostly this means omitting the <main> element because it is not universally supported. Some of the HTML generation is automated using PHP and some nested block elements are needed to describe the layout I want. The required modularity and structure was written into the skeleton. With HTML5 I was happy to note that a simple page can be formed almost entirely of markup which describes the data. Very little markup needs to exist purely for formatting or DOM manipulation hooks.

Some of the PHP content was necessary for the page to work correctly. For example, the navigation section has to present the appropriate options based on the current page. In other cases dynamic generation was used as a quality of life improvement. The photo lists with captions were uploaded to a MySQL database. PHP is used to select, sort, and format the results into the page. This makes it easy to add, remove, or reorder images and captions on the pages without any coding.

Formatting

As a vehicle for sharing my work with friends and family, the visual design needs to cater to all types. To be simple enough that my grandfather can navigate on a tablet with poor eyesight. Yet also have enough detail that my enthusiast friends understand the technicalities of my work.

I set up a palette that has slightly softer contrast, stays away from pure whites or pure blacks. Most of the interface is desaturated entirely. This pulls attention towards the content which has high contrast and lots of saturation. Navigation links are imbued with a bit of saturation. Enough to draw the eye and mark them as unique. Each page link is a different and consistent color. A matching color stripe is also drawn across the top of each page just below the header which works to reinforce your location. As you scroll down to view the content, the saturated top bar is hidden and you return to the a purely desaturated view that focuses on content.

The positioning of the title, navigation, and content is designed to flow with left to right eye scan. An English language viewer should first see the header showing which site they are on, then the navigation options within the site, and finally the content of the site. Content is mostly images and a description is inlined directly below each. Links are static underlined as is standard on the web, the over state is indicated by a color highlight which matches the page color theme.

Text needed to look decent at all pixel densities and many sizes. I embedded custom fonts to get the look I liked. I am sure to use special characters where possible, such as U+0192 for the florin sign and U+2014 for em dash. The special characters I need are all encoded in the body font. This takes extra bytes but it is worthwhile.

Apache's mod_rewrite is used along with some regular expressions to alter the URL of each page. This formats the URL to be more predictable, more memorable, and clean. Of course all layout and styling was done using CSS3 in an external file.

Speed

The primary pursuit of this website is speed. This is an obsession of mine — snappy websites are much more pleasing to use. It also allows the content to be consumed on slower mobile connections and slower devices. All users appreciate a website that loads quickly.

The first order of business is to be sure that you are aggressively limiting the number of files you load. Especially files which block rendering or require a rerender. Each file load requires a round trip to server and this ends up costing far more time than the actual load does for the smaller CSS, font, and JavaScript assets. I chose to build one larger CSS file and embed the web fonts using a Base64 URI.

Next we address the files that actually do get loaded. HTML and CSS files with Data URI content are all essentially text, so they respond well to compression. I leveraged Apache's mod_deflate to transparently gzip these files when delivering them to the client. All the images are defined with placeholder sizes, they can take their time loading in place after everything else and no reflow occurs. Images are also stripped of metadata for minimum possible file size.

The browser always attempts to cache almost everything, which is to our advantage. I set mod_expires to perform proper cache control on my files and ensured that E-tags were functioning properly. The CSS with fonts should only need to load once and will not load again during the browsing session. Everything was cached correctly in my testing. My server is based in the San Francisco Bay Area which is great for me. To keep speed high for others around the world, all of my static content uses a CDN. All images and CSS should be directed your way from static.jheatherbell.com which is a CNAME alias for my CDN.

I was sure to slice the font files down to the minimal possible size. The small caps title is a custom subset which contains only twelve glyphs making it very compact. The body font is a much larger subset with extra characters such as ligatures, accented letters, and math glyphs. The bold fonts are using font-weight: bold; in CSS because it looks fine and the impact of fetching another font file was too high.

Accessibility

When I talk about accessibility I mean two things. Can be consumed on a large number of devices, and can be understood by a diverse group of people.

For devices the most critical thing is to produce a responsive design. I did not want to push users over to a mobile version or restrict their experience. This site scales dynamically from full screen on a 27" monitor down to an iPhone 4. One URL, one css file. The site is pretty simple so that's not a huge undertaking, but the effect is very much worth it. You can take this browser window and make it larger or smaller to your hearts content and it will respond correctly. The website also scales well up to 300% larger, which means if your vision isn't the best you can scale it up and still read it.

For people who are various kinds of colorblind, the site never uses only hue to differentiate the states of anything. Links are always underlined, navigation links also acquire underlines at mouse over or when active. Even if somebody completely lacked color and shade perception the website would still be fully navigable.

What about people who cannot see at all? The site is structured so that it is fully accessible to screen readers. I have tested it with the screen readers I have access to and it performs well. All of the images have alt tags which describe the image contents in detail. Using HTML5 standard tags with ARIA roles in the correct places mean screen readers should properly parse everything sanely.

Metrics

Quite a bit of effort was spent trying different configurations, measuring, and analyzing the rendering pathway. Loading two separate font files is about 5KB more space-efficient. However, the two additional server fetches consume a lot more time than loading another 5KB over an existing connection. Using embedded Base64 fonts instead sped up page loads by 100ms on your average connection, and up to 500ms on very slow connections. It also removes an entire render pass because it forces the browser to block rendering while loading the CSS file.

To finalize the DOM, CSSOM, and do a complete render on this page I need to make two server requests and load 29KB of data. The total time to render is 300-350ms depending on how long the DNS lookup takes. Further pages are 4-5KB and use the cached CSS assets. If you really crank back the network speed to 56K modem levels, final load occurs after 5 seconds.

That is very fast.