Journal
I’ve started reading The Rise of the Ultra Runners, by Adharanand Finn.
Images on the Web: The Big Picture, Part 1
In modern web development there are a myriad ways to present an image on a web page and it can often feel pretty baffling. In this series I step through the options, moving from basic to flexible images; then from modern responsive images to the new CSS for fitting different sized images into a common shape. By the end I’ll arrive at a flexible, modern boilerplate for images.
Scope
This article is primarily about the HTML img
element (and related markup). I might mention CSS background images at some point, but by and large I’m focusing on images as content rather than decoration.
Similarly I probably won’t mention icons at all. I see them as a separate concern and recommend you use inline SVG rather than any image-based approach.
Terminology
Replaced element
The image element is a replaced element which means that the element is replaced by the resource (file) referenced in its src
attribute.
Aspect Ratio
You get an image’s aspect ratio by dividing its width by its height.
A 160px wide × 90px tall image can be represented as 16:9, or 1.777.
Aspect Ratio is an intrinsic characteristic of an image—i.e. it is “part of the image”—therefore outside of our control as developers. We can apply extrinsic settings which change the dimensions of the rendered image on our web page, however its aspect ratio was determined when the image was originally created and cropped.
Assumptions
CSS-wise, assume that we’ll start with nothing more complex than the following boilerplate:
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
img {
border-style: none;
display: block;
}
A basic image
Let’s start by going back to basics. I can include an image on a web page like so:
<img src="/img/250x377.jpg" alt="A Visit… by Jennifer Egan" />
Note that our markup contains no width
or height
attributes, just an alt
for accessibility. With no size-related attributes (and in the absence of any CSS acting on its width or height) the image simply displays at its intrinsic dimensions i.e. the dimensions at which the file was saved, in this case 250 × 377 pixels. The image is output as follows:

Now I know that narrow and static images like this feel pretty old-school. Since the Responsive Web Design movement we’re more accustomed to seeing full-column-width media and complex markup for intelligently selecting one file from many options.
However I still occasionally encounter use cases for displaying a relatively narrow image as-is.
Sticking with the book image example, given its aspect ratio you probably wouldn’t want it to be full-column-width on anything other than the narrowest screens simply because of how tall it could become at the expense of the reading experience. You might also be loading your images from a third party bookshop with which you have an affiliate scheme, and therefore have little control over file size and other factors influencing performance and responsive behaviour. As such you might do well to keep things simple and just load a sensibly-sized thumbnail.
See also this figure illustrating a simple database schema on the Ruby on Rails Tutorial website. On wide viewports, the author’s preference is to simply display the image at its natural, small size and centre it rather than blowing it up unnecessarily.
In summary, there remain times when you might need a narrow, fixed-size image so I want to keep that option open.
Include size attributes
When we know the dimensions of our image in advance, we can improve upon our previous markup by explicitly adding the width
and height
attributes.
<img src="/img/250x377.jpg" width="250" height="377" alt="…" />
Don’t expect fireworks; this renders the image exactly as before.

However, this addition allows the browser to reserve the appropriate space in the page for the image before it has loaded. If we don’t do this, we risk a situation where text immediately after our image renders higher up the page than it should while the image is loading, only to shift jarringly after the image loads.
We’re not overriding width or height with CSS (remember CSS rules would trump HTML attributes because attributes have no specificity) so the browser will render the image at whatever size attribute values we provide, regardless of the image’s intrinsic dimensions. As such, to avoid squashing and distortion we would ensure that our size attribute values matched the image’s real dimensions.
Flexible Images
At the dawn of the mobile web, many authors sought to handle mobile devices by creating a separate, dedicated mobile website. However this meant duplication of cost, code, content and maintenance. Responsive Web Design provided a counterpoint with a “create once, publish everywhere” philosophy which embraced the fluidity of the web and suggested we could serve desktop and mobile devices alike from a single codebase.
RWD proposed making layout and content adaptable. This included the idea of flexible images—that for any given image you need just a single, wide version plus some clever CSS to enable it to work not only on desktop but also to adapt its size for narrower contexts and still look good.
By default when a wide image is rendered within a narrower container it will overflow that container, breaking the layout. The key to avoiding this is to set a tolerance for how wide the image is permitted to go. Generally, we’ll tolerate the image being 100% as wide as its container but no wider. We can achieve this using max-width
.
<img src="/img/wide.png" alt="…" />
img {
max-width: 100%;
}
The eagle-eyed will have noticed that the above snippet once again excludes the HTML width
and height
attributes. That’s because when we began working responsively many of us stopped adding those size attributes, feeling that for flexible images the practice was redundant. The image’s dimensions were now a moving target so the space needing reserved by the browser while the image loaded was variable rather than fixed. And we were right: for a long time, browsers were not capable of reserving space for a moving target, so including the size attributes served no real purpose.
Regardless, some content management systems (most notably Wordpress) continued to output images with HTML width
and height
attributes as standard. This introduced a challenge. Without the attributes we could rely on the browser to take our simple max-width:100%
declaration and also implicitly apply height:auto
thereby always preserving the image‘s aspect ratio when scaling it down. To achieve the same goal when the HTML height
attribute is present, we needed the following revised CSS:
img {
max-width: 100%;
height: auto;
}
Here’s an example of a flexible image. It’s 2000 pixels wide, but shrinks to fit inside its narrower parent. Magic!

Jank-free responsive images
There’s been a recent development wherein modern browsers can now reserve appropriate space for flexible images while they are loading (rather than only for fixed images).
This means that adding the width
and height
attributes is once again a good idea.
If you know the image’s aspect ratio in advance, you can now use any combination of width
and height
attribute values which represent that ratio, and the browser will dynamically calculate and reserve the appropriate required space in the layout while the image loads, once again avoiding those jarring layout shifts I mentioned before.
However this presents a couple of challenges.
Firstly, having the height
HTML attribute once again means that for any image we want flexibly scaled and safely constrained by CSS max-width
, we’ll also need to override that explicit height attribute value with CSS.
Secondly, having the width
attribute can be problematic when the image is one which we explicitly want to be full-container-width, such as the featured image in a blog post. The problem arises when the width
attribute value is less than the containing element’s current width. If the only CSS you have on your image is max-width:100%
then the image will adopt the value from its width
attribute and consequently be narrower than its parent, ruining the effect. One approach might be to always use a sufficiently high width
value but that feels a tad brittle; I’d rather employ a solution that is more explicit and decisive.
To solve both of the above challenges, we can apply some additional CSS.
/*
Ensure correct aspect ratio is preserved when
max-width: 100% is triggered and image
has the HTML height attribute set,
while doing no harm otherwise.
*/
img[height] {
height: auto;
}
/*
Optional class to make an image 100% container-width.
Overrides the 'width' attribute, avoiding the risk of the image
being too narrow because its width value is narrower than the container.
When using this try to ensure your image’s intrinsic width is at least as
wide as its container’s maximum width because otherwise on wide
viewports the image would stretch and the results might not be great.
*/
.u-full-parent-width {
width: 100%;
}
Pros and cons of the “one large image” approach
I’d like to quickly take stock.
Let’s say we have a source image which is 1200px wide. Let’s also say that it’s the featured image for a blog post and therefore will be placed in our main content column, and that this column is never wider than 600px.
If we make the image flexible using max-width:100%
, it’ll work on wide viewports and narrow viewports (such as a mobile phone) alike.
On the plus-side, we only need to create one image for our blog post and we’re done.
Another positive is that on devices with retina screens—capable of displaying a comparatively greater density of pixel information in the same physical space—our oversized image will appear at higher quality and look great.
On the downside, we are delivering a much larger image and therefore file size than is required for, say, a 320px wide context. This has performance implications since bigger files mean longer download times, and this is exacerbated when the device is not connected to high-speed wifi (as is often the case with a mobile phone).
Another issue which is perhaps less obvious is that your content may not be read on your website with your CSS operating on it. For example if your website has an RSS feed (like mine does) then someone may well be reading your article in another environment (such as a feed reader application or website) and who is to say how that oversized image will look there?
Dealing with these challenges using modern Responsive Images will be the subject of Part #2.
References
Front-of-the-front-end and back-of-the-front-end web development (by Brad Frost)
The Great Divide between so-called front-end developers is real! Here, Brad Frost proposes some modern role definitions.
A front-of-the-front-end developer is a web developer who specializes in writing HTML, CSS, and presentational JavaScript code.
A back-of-the-front-end developer is a web developer who specializes in writing JavaScript code necessary to make a web application function properly.
Brad also offers:
A succinct way I’ve framed the split is that a front-of-the-front-end developer determines the look and feel of a button, while a back-of-the-front-end developer determines what happens when that button is clicked.
I’m not sure I completely agree with his definitions—I see a bit more nuance in it. Then again, maybe I’m biased by my own career experience. I’m sort-of a FOTFE developer, but one who has also always done both BOTFE and “actual” back-end work (building Laravel applications, or working in Ruby on Rails etc).
I like the fact that we are having this discussion, though. The expectations on developers are too great and employers and other tech people need to realise that.
Making sense of atomic design: molecules and organisms (on Future Learn)
From 2015: Alla Kholmatova reflects on the difficulty in choosing between molecule or organism when categorising components using atomic design at FutureLearn. She also provides some handy insights into how they handled it.
When thinking about complexity of elements, it helps viewing molecules as “helpers” and organisms as “standalone” modules.
Whereas helpers can’t really exist on their own, standalone modules can.
Alla also recommends than in cases where an element doesn’t clearly fall into either group, asking the following questions may help:
- Is this more of a supporting element or a standalone one?
- Would it normally be part of something else and be reused within various components? (if so it’s probably a molecule)
- Is it a well defined and relatively independent part or section of a page? (if so it’s probably an organism)
(via @jamesmockett)
Guest mix for Multiverse Sessions, December 2020 by Tom Churchill
Kicking off with an unreleased interlude by yours truly, it covers various shades of techno and electro from artists including @tapesjamaican, @pearsonsound, @reedalerise, @datashat, @legowelt-official, @cygnus and more.
Lovely mix of mellow electro and techno vibes by my friend Tom.
Issues with Source Code Pro in Firefox appear to be fixed
Last time I tried Source Code Pro as my monospaced typeface for code examples in blog posts, it didn’t work out. When viewed in Firefox it would only render in black meaning that I couldn’t display it in white on black for blocks of code. This led to me conceding defeat and using something simpler.
It now looks like I can try Source Code Pro again because the issue has been resolved. This is great news!
So, I should grab the latest release and give it another go. Actually, for optimum subsetting and performance I reckon in this case I can just download the default files from Source Code Pro on Google Webfonts Helper and that’ll give me the lightweight woff2
file I need.
I’d also mentioned the other day that I was planning to give Source Serif another bash so if everything works out, with these two allied to my existing Source Sans Pro I could have a nice complimentary set.
Design system components, recipes, and snowflakes (on bradfrost.com)
An excellent article from Brad Frost in which he gives us some vocabulary for separating context-agnostic components intended for maximal use from specific variants and one-offs.
In light of some recent conversations at work, this was in equal measure interesting, reassuring, and thought-provoking.
On the surface, a design system and process can seem generally intuitive but in reality every couple of weeks might throw up practical dilemmas for engineers. For example:
- this new thing should be a component in programming terms but is it a Design System component?
- is everyone aware that component has a different meaning in programming terms (think WebComponent, ViewComponent, React.Component) than in design system terms? Or do we need to talk about that?
- With this difference in meaning, do we maybe need to all be more careful with that word component and perhaps define its meaning in Design Systems terms a bit better, including its boundaries?
- should we enshrine a rule that even though something might be appropriate to be built as a component in programming terms under-the-hood, if it’s not a reusable thing then it doesn’t also need to be a Design System component?
- isn’t it better for components to be really simple because the less opinionated one is, the more reusable it is, therefore the more we can build things by composition?
When I read Brad’s article last night it kind of felt like it was speaking to many of those questions directly!
Some key points he makes:
- If in doubt: everything should be a component
- The key thing is that the only ones you should designate as “Design System Components” are the ones for maximal reuse which are content and context-agnostic.
- After that you have 1) Recipes—specific variants which are composed of existing stuff for a specific purpose rather than being context-agnostic; and 2) Snowflakes (the one-offs).
Then there was this part that actually felt like it could be talking directly to my team given the work we have been doing on the technical implementation details of our Card
recently:
This structure embraces the notion of composition. In our design systems, our Card components are incredibly basic. They are basically boxes that have slots for a CardHeader, CardBody, and CardFooter.
We’ve been paring things back in exactly the same way and it was nice to get this reassurance we are on the right track.
(via @jamesmockett)
A First Look at aspect-ratio (on CSS-Tricks)
Chris Coyier takes the new CSS aspect-ratio
property for a spin and tests how it works in different scenarios.
Note that he’s applying it here to elements which do not have an intrinsic aspect-ratio. So, think a container element (div
or whatever is appropriate) rather than an img
. This is line with a Jen’s Simmons’ recent replies to me when I asked her whether or not we should apply aspect-ratio
to an img
after she announced support for aspect-ratio
in Safari Technical Preview 118.
A couple of interesting points I took from Chris’s article:
- this simple new means of declaring aspect-ratio should soon hopefully supersede all the previous DIY techniques;
- if you apply a CSS aspect-ratio to an element which has no explicit
width
set, we still get the effect because the element’sauto
(rendered) width is used, then by combining that with the CSSaspect-ratio
the browser can calculate the required height, then apply that height; - if the content would break out of the target aspect-ratio box, then the element will expand to accommodate the content (which is nice). If you ever need to override this you can by applying
min-height: 0
; - if the element has either a height or a width set, the other of the two is calculated from the aspect ratio;
- if the element has both a height and width set,
aspect-ratio
is ignored.
Regarding browser support: at the time of writing aspect-ratio
is supported in Chrome and Edge (but not IE), is coming in Firefox and Safari, but as yet there’s no word regarding mobile. So I’d want to use it as a progressive enhancement rather than for something mission critical.
Vanilla JS List
Here’s Chris Ferdinandi’s curated list of organisations which use vanilla JS to build websites and web apps.
You don’t need a heavyweight JavaScript framework, and vanilla JS does scale.
At the time of writing the list includes Marks & Spencer, Selfridges, Basecamp and GitHub.
(via @ChrisFerdinandi)
Bleep Mix #221 - Datassette (on Bleep.com)
Great DJ mix by one of my favourite electronic producers, Datassette.
This mix is all about that 160bpm+ energy that first inspired me to make music. Around 1996 — to me at least, with the advantages of teenage naîvety — it seemed like electronic music had burst into a whole new tempo range, where there were no rules and anything was possible - as long as it BELTS (which is still true). If you go beyond 200 BPM, you reach that zone where 16th notes start to dissolve into 32nds and your brain latches onto a whole new outer layer of rhythm, like a fractal or temporal shepard tone. There is still much to be discovered!
I listened to this one while walking through the Glasgow Necropolis during one of those eerily-quiet Covid-era days, and it provided a welcome shock to the system.