Posts about CSS

Give footnotes a spec

I use footnotes on this blog, but have often found them annoying to implement, write, and deal with, so I found Jake Archibald’s post on footnotes an interesting take on the matter:

If reproduced as-is, footnotes on the web are even worse than their printed counterparts. In print, the footnotes are usually at the bottom of the current page, so they’re a quick glance away, and you can use a finger to mark your place in the main text while you’re off on your side-quest. Whereas on this beautiful pageless web of ours, you have to scroll all the way down to the end of the article. You can try flinging right to the bottom of the document, but if there’s a sizeable footer or comments section, you’ll overshoot the footnotes. And of course, after all of this, you have to scroll back to where you were, which is easier said than done.

Jake suggests myriad ways to deal with this problem, most of which I’d already implemented, but none of them solve the root problems:

  1. Footnotes are less accessible, because they’re often set smaller than body text. 
  2. On the printed page, footnotes can exist in the footer of any page. This makes them unobtrusive to read, since the size of a page is restricted by the physical limitations of books. Your eyes don’t have to travel far. On the web, no such luck: a webpage can be a mile long, so placing footers at the end of the document can turn footnotes into a very un-fun game. 

The bigger problem in my mind is #2, and I’ve been contemplating solutions to this for some time. 

On the web, I’ve often thought the best solution is using something similar to <aside> or <section role="notes"> in the way Jake describes. Ideally, each footnote” would directly follow the paragraph it pertains to. 

On desktop, these footnotes could be displayed in the margins of the page. (It’s called marginalia for a reason.) The smaller type can stay, mostly as a way to semantically highlight the insignificance of the footnote itself, which almost certainly exists for the author’s sake and not the reader’s. This works really well in Klim Type Co’s essays and case studies. (Unfortunately, Klim’s solution doesn’t scale down to mobile.)

I dislike the popup solution, which presents the user which a choice and annoys me personally as a reader. Popups are also annoying to build. 

The problem with using <aside> or <section role=“notes”> is that these solutions are not part of any agreed-upon footnote spec. It’s scope creep if you’re building in most CMSs today, including (and probably especially) WordPress. They also don’t render as footnotes in RSS feeds, so your content will be presented differently there than it would be on a website. (One could replace marginalia with normal footnotes for RSS feeds, but again, scope creep.)

For now, one way around it is to use JavaScript to fetch the footnotes and display them inline as marginalia beside the text. I’ve never built this out, but I can imagine a few potential accessibility problems (in addition to the accessibility issues already present for footnotes).

The best solution, outside of abandoning footnotes altogether, is an HTML spec for footnotes that removes the need for each developer to suggest their own implementation. Whatever the spec is, it could incorporate a best-practices approach that allows for CSS styling to transform footnotes into marginalia, something similar to an <aside>, or even a popup. It would also, theoretically, solve accessibility problems that developers create with their own implementations. 

For now, a better approach is probably to replace each footnote with a <section role=“note”>, which is an idea I hadn’t considered, but quite like. Thanks Jake!

The slow removal of SCSS from my projects

After reading through Chris Krycho’s extremely cool and clever CSS mixin for light and dark variables, I was particularly struck by his conclusion:

The last couple bits I need to knock down to not need SCSS at all are:

  • The equivalent of the nice @use directive. I think I might actually be able to use Lightning CSS directly along with its interpretation of native @import for bundling and minification.
  • Applying the same approach to the syntax highlighting theme shown above for the syntax highlighting theme, for which I also currently use a @mixin the same way.

This got me thinking about what I use SCSS for these days. SCSS has been a constant part of my toolchain for twelve or thirteen years now; I feel like it’s been a part of my workflow forever. But it frustrates far more than it delights today, at least for me. The announcement of CSS Nesting in December gives me hope that a major reason to use SCSS is becoming part of the standard spec in the future.

Beyond that, here are the last couple things I need to not need SCSS anymore:

  1. Like Chris, I need a good @use or @import directive. Today, this is SCSS’s best feature. I hadn’t heard of Lightning CSS before, but now I am going to check it out (although I am wary of replacing a well-known tool with a less well-known tool).
  2. I think browser targets are helpful as a compilation feature, and I am unsure of a way to make that part of the default CSS spec.
  3. I love using SCSS variables for media queries. @media (min-width:$bp-m) is far easier to use, in my experience, than @media (min-width:700px) or @media (min-width:45em). I understand why we can’t use environment variables, but it really is a shame I just can’t write @media (min-width:var(--bp-m)) and call it a day. I don’t know if I’ll ever get this as part of CSS spec. I’m also aware that best practice is probably to abandon variables in media queries and rely on something more conventional, but old habits…

I think the @use directive is the most important for my needs, and at a certain point, I’d be happy to give up futzing with the developer toolchain around SCSS compilation. Nothing has thrilled me more over my career than watching CSS improve and gain features over the past fifteen years. We’ve gone from floats to grids to crazy math formulas inside variables, and as a result, our layouts have been more less rigid and far easier to work with.

It’s still a great time to be a web designer.

Scaling SVGs without scaling their strokes

A forewarning: Unfortunately, I am going to share a roadblock I ran into, rather than a solution. I am sorry if this post is a bit of a downer.

Recently, I was working on a website for a client that included vector images of maps. The maps look something like this. These are vector maps in a line art style, where the maps appear hand drawn.

Here’s an example design with the map, so you can see what I’m working with:

An screenshot of a website mockup. The website mockup has map outlines on both the left and right side, with text in the centre. The text says: "We're on a mission to share Jesus with every home. We provide strategies and easy-to-use resources in printed and digital formats that Christians can use to present a gospel message to others, where they live and where they go. Learn how we do it."

What I wanted to do was place an inline SVG on the page, then scale its size along with the page itself. So I wrote code like this:

svg.map {
	display:block;
	margin:0;
	width:100%;
	height:auto;
}

You know, your bog-standard CSS.

This works as expected: the SVG scales along with the width of the page, and the aspect ratio of the SVG never changes. (The aspect ratio in this example is not a known quantity, and the client could change this map at any time to a different location.)

Here’s the problem: as the SVG scales, the strokes in the SVG scale as well. On a phone, the map looks correct: 1px strokes surrounding each country. On a desktop, it looks ridiculous: the strokes are 20px wide. It’s as if somebody drew the map with a highlighter.

To fix this, I turned to vector-effect — in particular, non-scaling-stroke. As always, the MDN Web Docs page is very helpful.

Here’s the problem with non-scaling-stroke: It only seems to work if you scale the SVG with transform="scale(X,Y)". It has no effect if you are merely resizing the SVG with CSS.

So this code does not work:

<style>
svg.map {
	display:block;
	margin:0;
	width:100%;
	height:auto;
}
</style>

<svg viewBox="0 0 500 240">
  <path
    vector-effect="non-scaling-stroke"
    d="M10,20 L40,100 L39,200 z"
    stroke="black"
    stroke-width="2px"
    fill="none"></path>
</svg>

Instead, the path must look like the following:

<path
	vector-effect="non-scaling-stroke"
  transform="translate(300, 0) scale(4, 1)"
  d="M10,20 L40,100 L39,200 z"
  stroke="black"
  stroke-width="2px"
  fill="none">
</path>

This was a huge disappointment for me, and for a few peers I ran this problem by. We all expected my solution to work because nowhere in the documentation does it say that scale is required.

Either the documentation needs to get updated, or vector-effects intended use needs to become more robust.

Preventing typographic widows with CSS

Richard Rutter shared an idea for limiting typographic widows with CSS. I love the simplicity of his proposal and would be thrilled if something like this were implemented as part of the core spec.