Posts from 2019

Running Code Over Time

Published 4 years, 2 months past

I’m posting this on the last day of 2019.  As I write it, the second post I ever made on meyerweb says it was published “20 years, 6 days ago”.  It was published on the second-to-last day of 1999, which was 20 years and one day ago.

Up top, the date when I wrote this post.  Down below, a five-day error.

What I realized, once the discrepancy was pointed out to me (hat tip: Eric Portis), is the five-day error is there because in the two decades since I posted it, there have been five leap days.  When I wrote the code to construct those relative-time strings, I either didn’t think about leap days, or if I did, I decided a day or two here and there wouldn’t matter all that much.

Which is to say, I failed to think about the consequences of my code running over long periods of time.  Maybe a day or two of error isn’t all that big a deal, in human-friendly relative-time output.  If a post was six years and two days ago but the code says 6 and 1, well, nobody will really care that much even if they notice.  But five days is noticeable, and what’s more, it’s a little human-unfriendly.  It’s noticeable.  It jars.

I think a lot of us tend not to think about running code over long time periods.  I don’t even mean long time periods in “Web years”, though I could — the Web is now just about three decades old, depending on when you reckon the start date.  (Births of the web are like standards — there are so many to choose from!)  I mean human-scale long periods of time, code that is old enough to have been running before your children were born, or maybe even you yourself.  Code that might still be running long after you die, or your children do.

The Web often seems ephemeral.  Trends shift, technologies advance, frameworks flare and fade.  There’s always so much new shiny stuff to try, new things to learn, that it seems like nothing will last.  We say “the Internet never forgets” (even though it does so all the time) but it’s lip service at this point.  And yet, the first Web pages are still online and accessible.

Which means the code that underpins them, from the HTML to the HTTP, is all still running and viable after 30 years.  The foresight that went into those technologies, and the bedrock commitment to consistency over long time frames, is frankly incredible.  It’s inspiring.  Compatibility both forwards and backwards in time, over decades and perhaps eventually centuries, is a remarkable achievement.

As I write this, I have yet to fix my relative-time code.  It’s on my list now, and I plan to get to it soon.  I presume the folks creating Intl.RelativeTimeFormat (hat tip: Amelia Bellamy-Royds) put a lot more thought into their code than I did mine, because they know they’re writing for long time frames.

What I need to do is adopt that same mindset.  I think we all do.  We should think of our code, even our designs, as running for decades, and alter our work to match.  I don’t necessarily know what that means, but we’ll never find out unless we try.


Twenty Years (and Days) Later

Published 4 years, 2 months past

Twenty years and twenty days ago, I published the first blog post on meyerweb.com.  It wasn’t my first blog post; I’d been putting blog-style updates on my CWRU home page since at least 1997, and probably a year or so earlier, albeit without the kind of archiving that would later come to define blogging.  Regardless, December 6th, 1999, is the moment this site effectively came online.

In those days, I just hand-modified the HTML of the site’s home page, copy-and-pasting the least recent entry on the home page to an manually-managed archive page.  A year or so into that, I decided to rework things to automate the process.  Näturally, the solution was to write my posts as XML files, jam them through some hand-authored XSLT, and get HTML out the other side.  Most of which, in fairness, was auto-generated.  My C and V keys breathed small sighs of relief.  It was a few years after that when I migrated to WordPress, doing so primarily to get support for comments on posts, a feature I maintain to this day.

A lot has come out of this site, and most of that is due to its blog.  This is where I worked out my CSS reset in public, with the community’s input; where I announced css/edge (in the days before my blog posts had titles) and An Event Apart; where I commented on the issues of the day as the web evolved; where I complained about browser vendors and standards bodies; and where I chronicled some of the very worst moments of my life.  There are posts in the archive that still get decent traffic today.  Here are the top ten from just this month:

  1. The Constants Gardener (August 31st, 2005) – about CSS, variables, and Shaun Inman.
  2. Un-fixing Fixed Elements with CSS Transforms (September 12th, 2011) – how element transforms establish formatting contexts, and how that interacts with fixed positioning.
  3. Reset Reloaded (May 1st, 2007) – when I finalized CSS Rest 1.0, including the much-regretted :focus {outline: 0;} line that set web accessibility back by years (see point #2 in the post and weep).
  4. Resetting Again (January 15th, 2008) – a small update to Reset 1.0.
  5. Inadvertent Algorithmic Cruelty (December 24th, 2014) – how good design can lead to very bad outcomes.
  6. Reset Reasoning (April 18th, 2007) – an early explanation for why I was working on a reset at all.
  7. Content Blocking Primer (September 19th, 2015) – written when iOS shipped content blockers, it still feels timely, which depresses me.
  8. JavaScript Will Save Us All (October 22nd, 2008) – an argument you could use in support of Houdini today, and an argument I’m much less certain about the rightness of today.  (Be careful what you wish for, etc.)
  9. Wanted: Layout System (February 17th, 2009) – basically, me begging for Grid years before Grid was a thing (while deriding attempts to get partway there through display trickery, something else I’m less righteous about today).
  10. Formal Weirdness (May 15th, 2007) – why form elements are weird, as a way of understanding why styling them is so restricted and difficult.

Looking over that list, 2007 was a big year for meyerweb, and 2008 wasn’t too shabby either.  Not that 2019 was terrible: the site still gets about 13,000 visits a day, and the blog portion is probably half to two-thirds of that traffic.

I won’t deny that blogging has been harder of late.  There are a few reasons, from social media releasing a lot of the “talk to the world” pressure that drove the original blogs to time available to write to having trouble feeling like what I have to say is of value.  On that last, I need to to remind myself of what I would tell anyone who asked: speaking is valuable, whether or not anyone listens, and what you can’t ever know is who will hear what you have to say at exactly the moment they need to hear it.

And so, in 2020, I’m going to do my best to rededicate myself to posting here, at a minimum of once a month but hopefully closer to once a week.  It will be the same blend I’ve always maintained, mixing technical posts with personal expression at will, sometimes in the same post.

Here’s to another twenty years — if not more — of blogging.


“Flexible Captioned Slanted Images” at 24 ways

Published 4 years, 2 months past

We have a lot of new layout tools at our disposal these days — flexbox is finally stable and interoperable, and Grid very much the same, with both technologies having well over 90% support coverage. In that light, we might think there’s no place for old tricks like negative margins, but I recently discovered otherwise.

That’s the opening paragraph to my 24ways piece “Flexible Captioned Slanted Images”, which I now realize I should have called “Accessible Flexible Captioned Slanted Images”.  Curse my insufficient title writing!  In just about 2,000 words, I explore a blend of new CSS and old layout tricks to take an accessible markup structure and turn it into the titular slanted images, which are fully flexible across all screen sizes while being non-rectangular.

It’s just my second piece for 24ways, coming a dozen years and a day after the first — and is very possibly my last, as Drew closed out this year by putting 24ways on hiatus.  Fifteen years is a heck of a run for any project, let alone an annual side project, and I salute everyone involved along the way.  Content is hard.  Managing content is harder.  Here’s to everyone who put in the time and energy to make such a valuable resource.  If you’ve never been through the 24 ways archives, now’s your chance.  I promise it will be very much worth your time.


So Full of Fire

Published 4 years, 9 months past

I was recently at a conference where someone thanked me for my openness about Rebecca and grieving, and expressed their condolences.  And then they said, “She was obviously very sweet — ” to which I must’ve pulled a face, because they said stumbled to a stop and then said, “No?”

I reflected for a few moments.  Eventually I said something to the effect of her being more sassy than sweet.  I believe the words “a real firecracker” were used.  She was never malicious.  She was usually laughing.  She had her sweet side.  But it was just one of many sides.

I was reminded of this today when I came across a post by Elizabeth K., who has worked for years at the kids’ preschool.

I witnessed [Rebecca’s] defiance more than once.  But especially this one time, when Kat, never losing her temper and never wavering on the rules, amazingly sat calmly on the couch in our office as Becca refused to say “please” for a lollipop.  There were many “NO!s” when countlessly reminded all she needed to do was utter a simple word.  She never gave in.  She left without a lollipop.  She held her ground.  She was three.

You might say that every kid does that sometimes, but with Rebecca, it was pretty common.  She wanted things her way, and she was incredibly tenacious about it, willing to forfeit the thing she wanted rather than yield.  Filled with fire and determination, practically vibrating with the force of her will.  We had occasional fears about what she’d be like as a teenager, never suspecting.  We’d already quarter-jokingly agreed with her best friend’s parents that, when we eventually had to bail the two of them out of juvenile detention, neither of us would blame the others.

It’s incredible to think what I’d have given to have that experience.  And how angry and unthinkingly ungrateful I’d have been, had that come to pass.

Elizabeth’s post ends:

…I love to visit the Kindergarten classes because many of the students are children who were in our Early Childhood Center and Daycare program the year before.  So I was welcomed with lots of “Lizzy!”s and “Look what I made!”s.  I was looking at Ruthie’s art project when Becca and I caught each other’s eye.  I told Ruthie how great her picture was and then said to Becca “You know what today is?” to which I got the famous side-eye.  “It’s no-hug day.  There are no hugs allowed today.”

She thought about it for a second and then leapt into my arms.  One of those great big hugs.  She loosened her grip, turned her head and whispered into my ear, “You were fooling.”  Sharp as whip.

“Yep.  But I got a hug.”  She gave me another classic Becca face, [smiled], and went back to her friends.

I count myself lucky to have been witness to her spark and her sparkling personality.  To say she will be missed does not cover it – not at all.


Half a Decade

Published 4 years, 9 months past

Rebecca has been dead for half a decade now.

I feel like I’ve run out of words.  How many times, how many ways can I say that nothing is quite right, nor ever will be?  That I miss the girl she would be today, eleven years old?  That I’ve learned to hear around the void she left, but it’s always there in quiet moments, omnipresent, like tinnitus of the soul?

Five years gone.  It will never be okay.  I will never be okay, no matter what I answer when asked how I’m doing.  I lie, all the time, to strangers and friends.  To customer service reps.  Librarians.  Other parents at school.  Myself.

“Hey, how are you?”

“I’m all right.”  Liar.  But better that than dropping a tragedy bomb on an unsuspecting soul.

A cashier asked me this morning how I was doing today, and I didn’t answer, because the words froze in my heart and I doubted that they cared all that much anyway.  I waited a beat or two, silent, and then said, “How ’bout you?”

“Doin’ okay,” they said, as if I’d answered them.  Maybe it was true.  Maybe they were lying.  Or maybe they didn’t have any particular reason to think about what they said and whether or not it was true, or false, or not even wrong.

I’ve said I’m used to it, and that was the truth.  I’m not over it, will never be over it so long as I live, but I’m used to it.

Being used to this hurts, when I think about it.  So I try not to think about it, and that hurts too.  Not like a sword through the heart, not like unending fire, more like a dull ache.  My aging body is starting to produce more and more of those.  I resent it for living years beyond what Rebecca got.  Snarl at reality for offering no way to give my years to her.

I’ve said all these things before, one way or another.

Five years.

No words.


D-Day

Published 4 years, 9 months past

Today was D-Day for our family.  I mean, yes, three generations ago, the Allied invasion of Europe commenced, and that’s a moment of which to take note.

But for us, this was an entirely different D-Day: Driving Day.

Carolyn passed the test and was granted a Learner’s Permit from the State of Ohio.  She is now legally allowed, under certain conditions, to drive on public and private roads.  Just as she’s wanted pretty much since the day she realized driving was a thing she’d be allowed to do someday.  So, a decade or more.

Before anyone asks, no, I am not terrified.  I’ve already done some basic winter-driving lessons with her in parking lots, back when things were icy, and what I observed told me what I’d always expected — that she’ll be a capable, confident driver.  There will always be fear in the back of my brain, but that was going to be true regardless.  More than anything, I’m grateful that she’ll have this opportunity.  I expect dings and dents and scrapes.  I expect she’ll learn quickly, as she usually does.  And I expect that, after a time, I’ll entrust her to drive her little brother to and from his activities.

Just like I expected, and rightly so, that she’d be one of the few people on this Earth with a legitimately good-looking license photo.  It’s a gift.

Happy D-Day to you, Carolyn.  May the road always rise to meet you.

  • D-Day was published on .
  • It was assigned to the Carolyn category.
  • There has been one reply.

The Broken Physics of “The Umbrella Academy” Finale

Published 4 years, 10 months past

Not long ago, Kat and I got around to watching The Umbrella Academy’s first season on Netflix.  I thought it was pretty good!  It was a decent mix of good decisions and bad decisions by people in the story, I liked most of the characters and their portrayals, and I thought the narrative arcs came to good places. Not perfect, but good.

Except.  I have to talk about the finale, people.  I have to get into why the ending, the very last few minutes of season one, just didn’t work for me.  And in order to do that, I’m going to deploy, for the first time ever, a WordPress Spoiler Cut™ on this here blog o’ mine, because this post is spoilerrific.  Ready?  Here we go.

Massive, massive spoilers and a fair amount of science ahead!

Color Easing Isn’t Always Easy

Published 4 years, 10 months past

A fairly new addition to CSS is the ability to define midpoints between two color stops in a gradient.  You can do this for both linear and radial gradients, but I’m going to stick with linear gradients in this piece, since they’re easier to show and visualize, at least for me.

The way they work is that you can define a spot on the gradient where the color that’s a halfway blend between the two color stops is located.  Take the mix of #00F (blue) with #FFF (white), for example.  The color midway through that blend is #8080FF, a pale-ish blue.  By default, that will land halfway between the two color stops.  So given linear-gradient(90deg, blue 0px, white 200px), you get #8080FF at 100 pixels.  If you use a more generic 90deg, blue, white 100%, then you get #8080FF at the 50% mark.

linear-gradient(90deg, blue, white 100%)

If you set a midpoint, though, the placement of #8080FF is set, and the rest of the gradient is altered to create a smooth progression.  linear-gradient(blue 0px, 150px, white 200px) places the midway color #8080FF at 150 pixels.  From 0 to 150 pixels is a gradient from #F00 to #8080FF, and from 150 pixels to 200 pixels is a gradient from #8080FF to #FFF.  In the following case, #8080FF is placed at the 80% mark; if the gradient is 200 pixels wide, that’s at 160 pixels.  For a 40-em gradient, that midpoint color is placed at 32em.

linear-gradient(90deg, blue, 80%, white 100%)

You might think that’s essentially two linear gradients next to each other, and that’s an understandable assumption.  For one, that’s what used to be the case.  For another, without setting midpoints, you do get linear transitions.  Take a look at the following example.  If you hover over the second gradient, it’ll switch direction from 270deg to 90deg.  Visually, there’s no difference, other than the label change.

linear-gradient(<angle>, blue, white, blue)

That works out because the easing from color stop to color stop is, in this case, linear.  That’s the case here because the easing midpoints are halfway between the color stops — if you leave them out, then they default to 50%.  In other words, linear-gradient(0deg, blue, white, blue) and linear-gradient(0deg, blue, 50%, white, 50%, blue) have the same effect.  This is because the midpoint easing algorithm is based on logarithms, and is designed to yield linear easing for a 50% midpoint.

Still, in the general case, it’s a logarithm algorithm (which I love to say out loud).  If the midpoint is anywhere other than exactly halfway between color stops, there will be non-linear easing.  More to the point, there will be non-linear, asymmetrical easing.  Hover over the second gradient in the following example, where there are midpoints set at 10% and 90%, to switch it from  270deg to 90deg, and you’ll see that it’s only a match when the direction is the same.

linear-gradient(<angle>, blue, 10%, white, 90%, blue)

This logarithmic easing is used because that’s what Photoshop does.  (Not Mosaic, for once!)  Adobe proposed adding non-linear midpoint easing to gradients, and they had an equation on hand that gave linear results in the default case.  It was also what developers would likely need to match if they got handed a Photoshop file with eased gradients in it.  So the Working Group, rather sensibly, went with it.

The downside is that under this easing regime, it’s really hard to create symmetric non-linear line gradients.  It might even be mathematically impossible, though I’m no mathematician.  Regardless, its very nature means you can’t get perfect symmetry.  This stands in contrast to cubic Bézier easing, where it’s easy to make symmetric easings as long as you know which values to swap.  And there are already defined keywords that are symmetric to each other, like ease-in and ease-out.

If you’re up for the work it takes, it’s possible to get some close visual matches to cubic Bézier easing using the logarithmic easing we have now.  With a massive assist from Tab Atkins, who wrote the JavaScript I put to use, I created a couple of CodePens to demonstrate this.  In the first, you can see that linear-gradient(90deg, blue, 66.6%, white) is pretty close to linear-gradient(90deg, blue, ease-in, white).  There’s a divergence around the 20-30% area, but it’s fairly minor.  Setting an interim color stop would probably bring it more in line.  That’s partly how I got a close match to linear-gradient(90deg, blue, ease-out, white), which came out to be linear-gradient(90deg, blue, 23%, #AFAFFF 50%, 68%, white 93%).

Those examples are all one-way, however — not symmetrical.  So I set up a second CodePen where I explored recreations of a few symmetrical non-linear gradients.  The simplest example matches linear-gradient(90deg, blue, ease-in, white, ease-out, blue) with linear-gradient(90deg, blue, 33.3%, white 50%, 61.5%, #5050FF 75%, 84%, blue 93%), and they only get more complex from there.

I should note that I make no claim I’ve found the best possible matches in my experiments.  There are probably more accurate reproductions possible, and there are probably algorithms to work out what they would be.  Instead,  I did what most authors would do, were they motivated to do this at all: I set some stops and manually tweaked midpoints until I got a close match.  My basic goal was to minimize the number of stops and midpoints, because doing so meant less work for me.

So, okay, we can recreate cubic Bézier easing with logarithmic midpoints.  Still, wouldn’t it be cool to just allow color easing using cubic Béziers?  That’s what Issue #1332 in the CSS Working Group’s Editor Drafts repository requests.  From the initial request, the idea has been debated and refined so that most of the participants seem happy with a syntax like linear-gradient(red, ease-in-out, blue).

The thing is, it’s generally not enough to have an accepted syntax — the Working Group, and more specifically browser implementors, want to see use cases.  When resources are finite, requests get prioritized.  Solving actual problems that authors face always wins over doing an arguably cool thing nobody really needs.  Which is this?  I don’t know, and neither does the Working Group.

So: if you have use cases where cubic Bézier easing for gradient color stops would make your life easier, whether it’s for drop shadows or image overlays or something I could never think of because I haven’t faced it, please add them to the GitHub issue!


Browse the Archive

Earlier Entries