Posts in the Design Category

Better Image Optimization by Restricting the Color Index

Published 7 months, 1 week past

Let’s talk about image optimization.  There are a few images used in meyerweb’s new design, and while I wanted them to be pleasing to the eye, I also wanted them to be lightweight.  My rough goal was to not have the design elements (images plus CSS) be more than half the total page weight for a typical blog post, not counting any post-specific images like photos or diagrams.  Thus, if a typical blog post’s page weight was 500KB, I didn’t want the images and CSS to add up to more than 250KB or so.

Spoiler: I achieved my goal, but at the same time fell short.  What I had overlooked was custom fonts, which I’ll get to in a later post.

I found out that how you optimize images matters a whole lot.  Let’s consider one example: the spiral-like image (which, yes, is a quiet callback to past work) at the center of the previous-next links at the bottom of blog posts and archive pages.  After I extracted a full-resolution copy of that particular sketch from pages 13-14 of Hamonshū, Vol. 1 and did a little cleanup with filters and so on, it became a 1.4MB Acorn file.

The full-size image in Acorn.

(Side note: Acorn’s “Transparentomatic” filter was an enormous time-saver on this project—it made dropping out the page texture a breeze, and easily adjustable, without forcing me to create and retouch mask layers and whatnot.  Thanks, Flying Meat!)

With the image ready to be tested in-browser, I would use Acorn’s Web Export dialog to save it as a PNG.  The nice thing about this dialog is its built-in Resize feature, which let me keep the Acorn file at its native size (almost a thousand pixels on each side) and export it to the size I wanted—in this case, 200 pixels across.  I did this sort of thing a lot, because I tested a variety of images for every design element.

Once I settled on the image I wanted, I’d drop it on ImageOptim to optimize it.  This usually slammed all eight cores in my aged laptop’s CPU for a good few seconds, and resulted in up to 5% size savings.

That last paragraph probably looks like an indictment of ImageOptim, but wait!  It’s fully redeemed by the end of the post, by which time I will have indicted myself instead.

At this point, my spiral image had gone from a 1.4MB Acorn file to a 30KB PNG.  That’s pretty good, even if 30KB feels a tad bulky for a 200×200 image.  I just assumed, what with all the transparency and shades of color and all that, it wasn’t too far out of line.  But as the whole design started to come together, I discovered that when you added up all the illustration images on, say, the home page, I’d let image bloat sneak up on me in the worst way.  They were totalling close to a megabyte, and they’d all been through ImageOptim already.

I went back to Acorn to see if I could squeeze any more out of the file size, maybe convert some of the images to JPGs if they didn’t need the transparency.  As I flipped between file formats in the Web Export dialog, I noticed something I’d previously overlooked in the PNG export options: a bit depth slider.  I’d been saving the PNGs with no bit depth restrictions, meaning the color table was holding space for 224 colors.  That’s… a lot of colors, roughly 224 of which I wasn’t actually using.

When I clicked the “Index PNG Colors” checkbox and changed the slider until I started getting dithers or obvious color loss, then brought it up a notch or two, the difference was astounding.  Instead of a 30KB file, I got a 4.4 KB file.  Instead of saving at 75% the original size, it was now 11%.

Wait a second… how long has THAT been there?

So I went back through the directory with all my design elements and repeated the process.  I do have batch image processing software installed, but I elected to do this manually so I could pick the best color depth for each file by eye.  It could be that some would be okay at 4 colors instead of 8; others might need 16 or 32 to retain visual fidelity.  Fortunately for me, I only had a couple dozen images to go through, but it would have been worth it even at 10 times that many.

Once I’d gone through all the images and saved them with restricted color depth, my theme’s image directory was down to 242KB total.  The biggest of them, the separator wave illustrations, had gone from being ~150KB each to ~25KB each—all five of them together now totalled less than just one of them had before I did the color indexing.

The directory, well and fully smooshed.

At this point, I thought, “All right, let’s see what ImageOptim does with these.”  It squeezed them down even further, taking my total from 242KB to 222KB, a nine percent reduction.  Which is to say, the percentage savings I got on these already-small files was larger than I’d been getting on the much bigger files—plus, ImageOptim processed them quickly and with a minimum of CPU slamming.  Which is honestly pretty great, given the age of my laptop (about seven years).

So: did I meet my performance goal?  As I said at the outset, yes, but also no.  For a single blog post with around 10KB of text content and no embedded media, the page weight is around 460KB, with the size varying a bit depending on how much markup is needed for the 10KB of text.  (Here’s one recent example with some content variety.)  Of that, the CSS, split across two files, totals 35.2KB.  The images add up to 102.9KB.  Add them together, and you get just a hair over 138KB, or right around 30%.  Huge success!

Except I hadn’t factored in custom fonts, which all by themselves currently total 203.6KB (44% total page weight), mostly due to the three faces of IM Fell I’m using.  That’s right: The fonts weigh more than the CSS and images put together.  Once they’re added in with the CSS and images, the design elements end up being almost 75% the total page weight—about 341.6KB of the 460KB total.  Most of the rest is the 104.4KB chewed up by showdown.js, the enhancement script I’m using to allow the use of Markdown in post comments.

Thus, next up on my performance quest is looking into subsetting the fonts I’m using in order to get their weight down, and finding out if there’s anything I can do to subset Showdown as well.

But as of now, I’m well pleased with where I ended up on image optimization.  I just need to go back and do the same for post-specific images I’d left at unrestricted color depths, where I anticipate a similar 90% savings in file sizes.  If you’ve got a lot of images, particularly PNGs, try running them through a process that lets you restrict the color depth, and see how much it saves.  The results might surprise you!


Pseudo-Randomly Adding Illustrations with CSS

Published 7 months, 2 weeks past

I’ve been incredibly gratified and a bit humbled by the responses to the new design.  So first of all, thank you to everyone who shared their reactions!  I truly appreciate your kindness, and I’d like to repay that kindness a bit by sharing some of the techniques I used to create this design.  Today, let’s talk about the ink-study illustrations placed between entries on the site, as well as one other place I’ll get to later.

Very early in the process, I knew I wanted to separate entries with decorations of some sort, as a way of breaking up the stream of text.  Fortunately, Hamonshū provided ample material.  A little work in Acorn and I had five candidate illustrations ready to go.

The five illustrations.

The thing was, I wanted to use all five of them, and I wanted them to be picked on a random-ish basis.  I could have written PHP or JS or some such to inject a random pick, but that felt a little too fiddly.  Fortunately, I found a way to use plain old CSS to get the result I wanted, even if it isn’t truly random.  In fact, its predictability became an asset to me as a designer, while still imparting the effect I wanted for readers.

(Please note that in this article, I’ve simplified some aspects of my actual CSS for clarity’s sake; e.g., removing the directory path from url() values and just showing the filenames, or removing declarations not directly relevant to the discussion here.  I mention this so that you’re prepared for the differences in the CSS shown in this piece versus in your web inspector and/or the raw stylesheet.)

Here’s how it starts out:

#thoughts .entry + .entry::before {
   content: "";
   display: block;
   height: 10em;
   background:
      url(separator-big-05.png) 50% 100% / contain no-repeat;
}

That means, for every blog entry except the first, a block-level bit of generated content is inserted at the beginning of the entry, given a height, and the image separator-big-05.png is dropped into the generated box and sized to be contained within it, which means no part of the image will spill outside the background area and thus be clipped off.  (The file has the number 05 because it was the fifth I produced.  It ended up being my favorite, so I made it the default.)

With that in place, all that remains is to switch up the background image that’s used for various entries.  I do it like this:

#thoughts .entry:nth-of-type(2n+1)::before {
   background-image: url(separator-big-02.png);
}
#thoughts .entry:nth-of-type(3n+1)::before {
   background-image: url(separator-big-03.png);
}
#thoughts .entry:nth-of-type(4n+1)::before {
   background-image: url(separator-big-04.png);
}
#thoughts .entry:nth-of-type(5n+1)::before {
   background-image: url(separator-big-01.png);
}

So every second-plus-one entry (the third, fifth, seventh, etc.) that isn’t the first entry will use separator-big-02.png instead of -05.png.  Unless the entry is an every-third-plus-one (fourth, seventh, tenth, etc.), in which case separator-big-03.png is used instead.  And so on, up through every-fifth-plus-one.  And as you can see, the first image I produced (separator-big-01.png) is used the least often, so you can probably guess where it stands in my regard.

This technique does produce a predictable pattern, but one that’s unlikely to seem too repetitious, because it’s used to add decoration separated by a fair amount of text content, plus there are enough alternatives to keep the mix feeling fresh.  It also means, given how the technique works, that the first separator image on the home page (and on archive pages) is always my favorite.  That’s where the predictability of the approach helped me as a designer.

I use a similar approach for the separator between posts’ text and their comments, except in that case, I add a generated box to the end of the last child element in a given entry:

.single #thoughts article .text > *:last-child:after {
   content: "";
   display: block;
   height: 10em;
   background:
      url(separator-big-05.png) 50% 100% / contain no-repeat;
}

That is, on any page classed single (which is all individual post pages) after the last child element of a .text element (which holds the text of a post), the decoration box is generated.  The default, again, is separator-big-05.png—but here, I vary the image based on the number of elements in the post’s body:

.single #thoughts article .text > *:nth-child(2n+1)::after {
   background-image: url(separator-big-02.png);
}
.single #thoughts article .text > *:nth-child(3n+1)::after {
   background-image: url(separator-big-03.png);
}
.single #thoughts article .text > *:nth-child(4n+1)::after {
   background-image: url(separator-big-04.png);
}
.single #thoughts article .text > *:nth-child(5n+1)::after {
   background-image: url(separator-big-01.png);
}

In other words: if the last child element of the post text is a second-plus-one, separator-big-02.png is used.  If there are 3n+1 (one, four, seven, ten, thirteen, …) HTML elements in the post, separator-big-03.png is used.  And so on.  This is an effectively random choice from among the five images, since I don’t count the elements in my posts as I write them.  And it also means that if I edit a piece enough to change the number of elements, the illustration will change!  (To be clear, I regard this as a feature.  It lends a slight patina of impermanence that fits well with the overall theme.)

I should note that in the actual CSS, the two sets of rules above are merged into one, so the selectors are actually like so:

#thoughts .entry + .entry::before,
   .single #thoughts article .text > *:last-child:after {…}

#thoughts .entry:nth-of-type(2n+1)::before,
   .single #thoughts article .text > *:nth-child(2n+1)::after {…}

#thoughts .entry:nth-of-type(3n+1)::before,
   .single #thoughts article .text > *:nth-child(3n+1)::after {…}

In all honesty, this technique really satisfies me.  It makes use of document structure while having a random feel, and is easily updated by simply replacing files or changing URLs.  It’s also simple to add more rules to bring even more images to the mix, if I want.

And since we’re talking about using structure to vary layout, I also have this @media block, quoted here verbatim and in full:

@media (min-width: 50em) {
   #thoughts .entry:nth-of-type(2n) {
      transform: translate(-1vw,0);
   }
   #thoughts .entry:nth-of-type(3n) {
      transform: translate(3vw,0);
   }
}

This means on the home page and blog archive pages, but only at desktop-browser widths, some entries are shifted a bit to the left or right by fractions of the viewport width, which subtly breaks up the strict linearity of the content column on long pages, keeping it from feeling too grid-like.

To be honest, I have no idea if that side-shifting effect actually affects visitors’ experience of using meyerweb, but I like it.  Sometimes the inter-entry wave art fits together with the side-shift so that it looks like the art flows into the content.  That kind of serendipity always delights me, whether it comes by my hand or someone else’s.  With luck, it will have delighted one or two of you as well.


Hamonshu

Published 7 months, 3 weeks past

I ended my observance of CSS Naked Day 2020 by launching an entirely new design for meyerweb.  I’m calling it Hamonshū after the source from which I adapted most of the graphic elements.  I’ve been working on it sporadically in my free time since mid-January, finally coming to a place I thought was ready to launch in late March.

Naked Day was a convenient way to change over the structure of pages while there was no design, which probably makes it sound like that’s the only reason I even observed it.  To the contrary, I hadn’t planned to launch the new design until June 8th of this year—but once I decided on going style-naked, I realized it was the perfect opportunity to make the switch.

I might still have delayed, if not for everything happening in the world right now.  But Cameron Moll said it best as he recently launched a new design: “Deploying in the middle of a pandemic seems so unimportant at the moment. Or maybe there’s no better time for it.”  That last sentence resonated with me unexpectedly deeply, and came to mind again as I took the CSS away for Naked Day.

I’ll have quite a few things to say about the design in the future: things I learned, techniques I used, bits I really like, that sort of thing.  In this post, I want to say a bit about its genesis.

It all started when someone—I’ve since lost track of who, or even where it happened—brought my attention to Hamonshū, Vols. 1-3, available on the Internet Archive thanks to the Smithsonian Institution.  Hamonshū, a word which I understand roughly translates into English as “wave forms” or “wave design”, is a three-volume set of art studies of water.  Created by Yūzan Mori and published in 1903, I had never heard of it before, but the sketches immediately appealed to me.  You can get an preview of some of Yūzan’s art in this article from Public Domain Review, or just go to the source (linked previously, as well as in the footer of the site) and immerse yourself in it.

As I absorbed Yūzan’s ink studies of ocean waves, rivers, fountains, and more, the elements of a design began to form in my head.  I won’t say I saw it—being aphantasic, I couldn’t—but certain sketches suggested themselves as components of a layout, and stuck with me.

Tall Bamboo and Distant Mountains, after Wang Meng, Wang Hui 王翬, 1694

Early on, I had thought to combine elements from Hamonshū with other artwork, primarily ink landscape paintings from the Qing Dynasty and Edo periods: two such examples being Tall Bamboo and Distant Mountains, after Wang Meng (Wang Hui 王翬, 1694) and View of West Lake (Ike Taiga, 1700s).  I made attempts, but the elements never really combined properly.  I eventually realized I was trying to combine close-up studies of water with adaptations of much larger works, and the scale of the brush strokes was clashing.  At that point, I abandoned the paintings and concentrated exclusively on Hamonshū.

As the various design elements came together, I went looking for fonts to use.  I originally thought to use variable fonts, but I kept coming back to IM Fell, a typeface I’d seen Simon St. Laurent use and had put to my own purposes in an experimental typeset of Neal Stephenson’s Mother Earth Mother Board.  IM Fell has a sort of nautical feel to it, at least to me, which fit nicely with the water elements I was adapting from Hamonshū, so I ended up using it as a “site elements” typeface.  It’s what’s used for the site name in the header, the main navigation links, metadata for posts, sidebar heading text, the h1 on most pages, and so on.

Originally I used IM Fell for the titles of blog posts like this one, but it didn’t feel quite right.  I think it caused the titles to blend into the rest of the design a little too much unless I kept it relatively huge.  I needed something that felt consistent, but distinguished itself at the smaller sizes I needed for post titles.  I went back to Google Fonts and scrolled through the choices until I narrowed down to a few faces, of which Eczar was the eventual winner.  In addition to using Eczar for post titles, I also employ it in the site’s footer, at least wherever IM Fell isn’t used.  The general body copy of the site is Georgia Pro, falling back to Georgia or a generic serif as needed.

One of the limitations I set for myself was to be reasonably lightweight, and that was a major part of the process.  The details merit a post or two of their own, but my overall goal was to get even the post archive pages under a megabyte in total.  I’m pleased to say I was able to get there, for the most part.  As an example, the main post archive page is, as I write this (but before I posted it) 910.98KB, and that includes the various photographs and other images embedded in posts.  The time to DOMContentLoaded over WiFi is consistently below 200ms, 400-500ms on “Regular 3G”, and 500-600ms on “Regular 2G”, all with the local cache disabled, at least when the server is responding well.  I still have work to do in this area, but I was comfortable enough with the current state to launch the design publicly.

Since I was redesigning anyway, I did some sprucing up of various subpages.  Most notable are the Toolbox and Writing pages, which use a number of techniques to improve organization and appearance.  I still think the top part of the Writing page could use some work, but it’s leagues better than it used to be.  The one major page I’d like to further upgrade is CSS Work, but I’m still looking for an approach that is distinct from the other pages, yet thematically consistent.  If I can’t find one, I’ll probably take the same general approach I did for Toolbox.  I also rewrote some of the microcopy, such as the metadata (publication date, categories, etc.) at the bottom of blog posts, to be more evocative of the feel I was going for.

Late in the process, I got a welcome assist from Jesse Gardner, who had seen a preview of article design.  He had the idea to make a traced SVG version of the “Hand Made With Love” necklace charm from the masthead of the previous design, and then he just up and did it and sent me the file.  You’ll find it in the footer of the site.  It isn’t interactive, although it may in the future.  I haven’t decided yet.

I really hope you enjoy the new look.  It’s the first design I’ve done that wasn’t cribbed off someone else’s site in, oh, 15-20 years, give or take, and I’m rather proud of it.  It won’t win any awards, but it makes the statement I want it to make, and visiting my own site gives me a little glow of satisfaction.  I don’t know if I could ask for more than that.


Headings and Labels

Published 2 years, 10 months past

Following on my last two posts about accessibility improvements to meyerweb, I’ve made two more adjustments: better heading levels and added ARIA labels.

For the heading levels, the problem I face is one familiar to many authors: what makes sense as an <h1> in some situations needs to be an <h2> in others.  The most common example is the titles of blog posts like this one.  On its permalink page, the title of the page is the title of the post.  There, it should be an <h1>.  On archive pages, including the home page of meyerweb, there are a number of posts shown one after the other.  In those situations, each post title should be an <h2>.

Part of the redesign’s changes were to write a single PHP routine that generated posts and their markup, which I could then simply call from wherever.  So I added an optional function parameter that allowed me to indicate the context in which a post was being placed.  It goes something like this:

<?php blogpostMarkup("archive"); ?>
function blogpostMarkup($type = "standalone") {
    if ($type == "archive") $titletag = "h2"; else $titletag = "h1";
    // …markup is all generated here…
    echo $output;
}

Or code to that effect.  (I did not go copy-paste from my actual code base.)

So now, heading levels are what they should be, at least on most pages (I may have missed updating some of my old static HTML pages; feel free to point them out in the comments if you find one).  As a part of that effort, I removed the <h1> from the masthead except on the home page, being the one place it makes sense to be an <h1>.

As for ARIA labels, that came about due to a comment from Phil Kragnes on my last post, where he observed that pages often have multiple elements with a role of navigation.  In order to make things more clear to ARIA users, I took Phil’s suggestion to add aria-label attributes with clarifying values.  So for the page-top skiplinks, I have:

<nav role="navigation" aria-label="page" id="skiplinks">

Similarly, for the site-navigation bar, I have:

<nav role="navigation" aria-label="site" id="navigate">

The idea is that screen readers will say “Page navigation region” and “Site navigation region” rather than just repeating “Navigation region” over and over.

Other than cleaning up individual pages’ heading levels and the occasional custom layout fix (e.g., the Color Equivalents Table needed a local widening of the content column’s maximum size), I think the redesign has settled into the “occasional tinkering” phase.  I may do something to spruce up my old Web Review articles (like the very first, written when HTML tags were still uppercase!) and I’m thinking about adding subnavigation in certain sections, but otherwise I think this is about it.  Unless I decide to go really over the top and model my Tools page after Simon St. Laurent’s lovely new Grid design, that is…

Of course, if you see something I overlooked, don’t hesitate to let me know!  I can’t guarantee fast response, but I can always guarantee careful consideration.


Increasing Accessibility

Published 2 years, 10 months past

Thanks to the fantastic comments on my previous post, I’ve made some accessibility improvements.  Chief among them: adding WAI-ARIA role values to various parts of the structure.  These include:

  • role="banner" for the site’s masthead
  • role="navigation" added to the navigation links, including subnavigation links like previous/next posts
  • role="main" for the main portion of a page
  • role="complementary" for sidebars in the blog archives
  • role="article" for any blog post, whether there are several on a page or just one

In addition, I restored skip links to the masthead of most pages (the rest will get them soon).  The links are revealed on keyboard focus, which I’m not sure I like.  I feel like these aren’t quite where they need to be.  A big limitation is the lack of :matches() (or similar) support in browsers, since I’d love to have any keyboard focus in the masthead or navigation links bring up the skip links, which requires some sort of parent selection.  I may end up using a tiny bit of enhancing Javascript to make the links’ UX more robust in JS situations, but still obviously available if JS fails.  And I may replicate them in the footer, as a way to quickly jump back up the page, especially to the navigation.

Speaking of the navigation links, they’ve been moved in the source order to match their place in the visual layout.  My instincts with regard to source order and layout placement were confirmed to be woefully out of date: the best advice now is to put the markup where the layout calls for the content to be.  If you’re putting navigation links just under the masthead, then put their markup right after the masthead’s markup.  So I did that.

The one thing I didn’t change is heading levels, which suffer all the usual problems.  Right now, the masthead’s “meyerweb.com” is always an <h1> and the page title (or blog post titles) are all <h2>.  If I demoted the masthead content to, say, a plain old <div>, and promoted the post headings, then on pages like the home page, there’d be a whole bunch of <h1>s.  I’ve been told that’s a no-no.  If I’m wrong about that, let me know!

There’s still more to do, but I was able to put these into place with no more than a few minutes’ work, and going by what commenters told me, these will help quite a bit.  My thanks to everyone who contributed their insights and expertise!


The Newwwyear Design

Published 2 years, 11 months past

Well, here it is—the first new design for meyerweb since February 2005 (yes, almost 13 years).  It isn’t 100% complete, since I still want to tweak the navigation and pieces of the footer, but it’s well past the minimum-viable threshold.

My core goal was to make the site, particularly blog posts, more readable and inviting.  I think I achieved that, and I hope you agree.  The design should be more responsive-friendly than before, and I think all my flex and grid uses are progressively enhanced.  I do still need to better optimize my use of images, something I hope to start working on this week.

Things I particularly like about the design, in no particular order:

  • The viewport-height-scaled masthead, using a minimum height of 20vh.  Makes it beautifully responsive, always allowing at least 80% of the viewport’s height to be given over to content, without requiring media queries.
  • The “CSS” and “HTML” side labels I added to properly classed pre elements.  (For an example, see this recent post.)
  • The fading horizontal separators I created with sized linear gradients, to stand in for horizontal rules.  See, for example, between post content and metadata, or underneath the navlinks up top of the page.  I first did this over at An Event Apart last year, and liked them a lot.  I may start decorating them further, which multiple backgrounds make easy, but for now I’m sticking with the simple separators.
  • Using string-based grid-template-areas values to rearrange the footer at mobile sizes, and also to make the rare sidebar-bearing pages (such as those relating to S5) more robust.

There are (many) other touches throughout, but those are some high points.

As promised, I did livestream most of the process, and archived copies of those streams are available as a YouTube playlist for those who might be interested.  I absolutely acknowledge that for most people, nine hours of screencasting overlaid with rambling monologue would be very much like watching paint dry in a hothouse, but as Abraham Lincoln once said: for those who like this sort of thing, this is the sort of thing they like.

I was surprised to discover how darned easy it is to livestream.  I know we live in an age of digital wonders, but I had somehow gotten it into my head that streaming required dedicated hardware and gigabit upstream connections.  Nope: my five megabit upstream was sufficient to stream my desktop in HD (or close to it) and all I needed to broadcast was encoding software (I used OBS) and a private key from YouTube, which was trivial to obtain.  The only hardware I needed was the laptop itself.  Having a Røde Podcaster for a microphone was certainly helpful, but I could’ve managed without it.

(I did have a bit of weirdness where OBS stopped recognizing my laptop’s camera after my initial tests, but before I went live, so I wasn’t able to put up a window showing me while I typed.  Not exactly a big loss there.  Otherwise, everything seemed to go just fine.)

My thanks to everyone who hung out in the chat room as I livestreamed.  I loved all the questions and suggestions—some of which made their way into the final design.  And extra thanks to Jen Simmons, who lit the fire that got me moving on this.  I enjoyed the whole process, and it felt like a great way to close the books on 2017.


A Meyerweb Makeover

Published 2 years, 11 months past

This coming week, I’m going to redesign meyerweb.com—which will be its first redesign in twelve and a half years.

I’m doing this as part of Jen Simmons’ #newwwyear initiative.  As Jen put it:

Ok, here’s the deal. Tweet your personal website plan with the hashtag #newwwyear (thanks @jamiemchale!): 1) When will you start? 2) What will you try to accomplish? 3) When is your deadline? Improve an existing site. Start a new one. Burn one down & start over. It’s up to you.

Many of us feel bad about our personal websites. Me included. We keep meaning to make one, improve what’s there, or burn it down and start over. We are busy. Afraid. Overwhelmed. Well, let’s do it. Maybe over the holidays. Maybe after, in the New Year. #newwwyear

On Friday, I announced my plan:

  1. I’ll start Wednesday, December 27th.
  2. I’ll redesign http://meyerweb.com  for the first time in a dozen years, and I’ll do it live on the production site.
  3. My deadline is Wednesday, January 3rd, so I’ll have a week.

I won’t be redesigning all day every day—I still have paying work to do, after all—but I’ll do my best to put in a couple of hours each weekday.

When say I’ll do it live, I mean I’ll be making all my changes here on the production site, with minimal or no testing beforehand—literally opening the style sheet(s) into BBEdit via Transmit, and saving changes up to the server to see what happens.  Stuff will break, and then I’ll fix it, live in the public eye.  It’s possible I’ll try out new ideas and then junk them before moving on to others.  I’m hoping that accidents spark inspiration, as they often do.

(There will be a local copy of the site in case things go so badly that I need to reset to the starting point.  I’m not completely insane, after all.)

I have a vague plan with all this, which is: realign the site’s appearance to be more inviting, more readable, and more visually engaging.  I do have a few past experiments that I’ll fold in, like using relative times (e.g., “Two months ago”) on posts, but a lot of this will be me doing free-association design.  And hopefully a little markup cleanup and enhancement as well.

I’m sticking with WordPress to drive the blog, given that it contains close to two decades of posts and makes it easy to allow comments, a feature I still value; and my hand-built old-school-standards-punk mostly-static templating system for the rest of the site, which let the site be static(ish) way before static was cool.  (No, I will not consider migrating to other CMSes or template systems: with a week set aside for this, I won’t have the time.)

So, that’s the plan: a week for a meyerweb makeover.  I don’t know if I’ll keep up a running commentary on Twitter while I do, or if I’ll take breaks and blog short entries chronicling my progress, or what.  If someone sets up a #newwwyear Slack team, I’ll probably join in.  If the #newwwyear idea excites you, I hope you’ll join in too!


Gridded Headings v. Justified Headings

Published 3 years, 6 months past

Amongst the reactions to Gridded Headings, Benjamin de Cock pointed out there’s another way to arrive at the same place I did.  Instead of this:

grid-template-columns:
    minmax(1em,1fr)
    minmax(min-content,max-content)
    minmax(1em,1fr);

…Benjamin pointed out one could instead do this:

justify-content: center;

That’s right: without explicitly specifying any grid columns, but just setting the grid items themselves to be centered, the same behaviors emerge.  Clever!

What’s interesting is that the behaviors are not precisely the same.  While mostly identical behaviors occur with either approach, there are a few subtle differences and a much different possibility space.  I’ll consider each in turn.

First, the differences.  First of all, the small gutters defined by the first and third grid column tracks—the ones defined to be minmax(1em,1fr)—aren’t present in the justify-content version.  This means the headings will jam right up against the edge of the grid container if things get narrow enough.

Side separation versus side smashing.  Grid on the left, justify-content on the right.

So we either need to re-establish them with grid-template-columns, which would seem to put us right back where we were, or else apply side margins to the heading and subheading.  Something like this:

div h2, div h3 {margin-right: 1rem; margin-left: 1rem;}

Either way, that side separation has to be defined (assuming you want it there).  Having to set those separations as margins feels a little clumsy to me, though not hugely so.  Doing all the sizing and separation in a single grid-template-columns declaration feels cleaner to me, though I admit that may be partly due to my current Gridfatuation.

There is another difference worth exploring.  If the content gets wider than the space available, the grid-template-columns approach means the content will overflow to the right (in LTR writing modes).  If it falls offscreen, it can be scrolled to read.  With justify-content: center, the content stays centered within the box, overflowing to both sides.  The content to the left may not be accessible via scrollbar.

How track sizing and content justification handle overspill.  Grid on the left, justify-content on the right.

So if you have a large headline containing a lengthy unhyphenated word, like “Kazakhstan” or “emoluments”, you might prefer one result over the other.

Beyond that, the further possibilities are a lot richer with Grid than with content justification.  Center-justifying the content means exactly that: the element boxes are centered.  So if you were interested in taking the heading and subheading, acting as an apparent unit, and shift them toward one side or another, this would be much easier to accomplish with Grid.

Suppose we want there to be three times as much space to one side of the headings’ column as the other.  Here’s what that would look like:

grid-template-columns:
    minmax(1em,1fr)
    minmax(min-content,max-content)
    minmax(1em,3fr);

That’s it.  One number changed, and the whole setup is offset from the center without losing the coherence of the original demo.

The same thing could likely be approximated with justify-content using side margins on the heading elements, but it wouldn’t be precisely the same, even with percentages.  fr is a very special beast, and permits very unique results.

The other major difference in possibilities is that with Grid, we can rearrange elements visually without ever touching the source.  Suppose we wanted to put the subhead above the heading in some layouts, but not others.  (Whether those different designs live on different pages or at different breakpoints, it really doesn’t matter.)  With Grid, that’s as simple as rewriting the grid template in a line or three of CSS.  The h2 remains ahead of h3 in the HTML.

With justify-content, you’d still have to write that same grid template, or else switch to flexbox and use flex-direction: column-reverse or some such.  That would work if you want to just switch the display order of two headings in a single column.  It tends to fall down for anything more demanding than that.

This is not to say Benjamin came up with a bad alternative!  I like it quite a bit, precisely because it has similar outcomes to my original idea, thus shedding light on creative ways Grid and content alignment can be combined.  But I like it even more for its differences, which shed even more light on how the two things operate.

In that combination of similarity and difference, I can sense an incredible range of capability, chock full of nuance and brimming with possibility.  There are going to be ways to put these things together that nobody has figured out yet.  I know I keep saying this, but there’s a vast landscape opening, so vast that I don’t think we can even guess how far it extends yet, let alone have mapped its terrain.


Browse the Archive

Earlier Entries