Published

A web color space that respects *real* lightness

Lea Verou just published a blog post about the LCH color space. This is super exciting, see her post for detail. Specifically, the improvement has to do with the perceptual uniformity and lightness being visually consistent no matter the hue.

The best way to get a feel for this is to experiment with her LCH color picker. Drag the hue value back and forth, and you’ll see that the tonality of the background remains consistent. It doesn’t suddenly feel a lot lighter in yellow than it does in blue. Do the same thing in an HSL color picker and you’ll feel the difference.

This would help a lot with the color on my site. I’ve never been 100% happy with how the color is handled because it is too hard to control the lightness and thus the legibility. See the List page for a clear example of this, posts in June and February are particularly hard to read. LCH would solve this!

Published

Digital coffee 🤖☕️

I’ve been getting a bunch of emails recently with web- and tech-related questions from collaborators, friends, clients, family members, almost everyone I know. I suspect this has to do with the huge shift we’ve all made recently in the way we work and live our lives.

Related to this, I’m offering offering free 30 minute slots every Tuesday afternoon GMT to anyone that wants to have digital coffee over Google Hangouts. I haven’t decided how long to do this, but I’ll try to continue until we’re past the worst of current events.

The point is to offer individuals – particularly those that are self-employed or run small businesses – an opportunity to ask nebulous tech-y questions. But I’m happy to talk about anything! WFH tips, recipe ideas, the best movie you’ve seen recently, great sci fi authors, how to grow herbs indoors (I could use some pointers). Only thing I’d probably rather not talk a lot about is COVID-19, please and thank you.

I can’t promise to have all the answers, but I can promise my insight and some nice face-to-face time. We could all use a bit of that right now.

If you think you’d benefit from this, feel free to sign up for a slot. If you know someone that might benefit from this, point them my way.

This is directly inspired by Carly Ayers’s Digital Coffee as linked to on Google’s Hack to Help: COVID-19 site. Nice idea.

Published

Using CSS, HTML, and maybe a little logic to display images with a consistent surface area

Every once in a while, I have to figure out how to display images on the web with a consistent surface area. It’s usually in relation to making a lot of logos with very different aspect ratios look evenly sized so that none of them stick out like a sore thumb.

I haven’t had to do this in a while but came across a tweet by Nick Sherman that prompted me to think about it again.

To achieve an evenly-sized group of images, you have to calculate a maximum width that is proportionate to the surface area you want. To do this, you need to be able to calculate a square root, you need the width and height of each original image, and all of your images need to be tightly cropped since extra negative space will throw things off visually.

In the past, I’ve achieved this with logic since vanilla CSS doesn’t currently support a sqrt() function (more on this later). I’ve usually used PHP since I tend to work with Kirby CMS pretty often.

The function in PHP:

function max_img_width($img_width, $img_height, $ideal_area) {
  $max_width = round($img_width * sqrt($ideal_area / ($img_width * $img_height)));
  echo $max_width;
}

And the function in use + corresponding HTML:

<img style="max-width: <?php max_img_width(1500, 3000, 40000); ?>px;" src="https://piperhaywood.com/my-image.jpg">

A CSS-only solution that works now

There seems to be a CSS-only way to go about this though. Apparently you can approximate square roots in CSS by using a series of CSS variables and calc(), see more info in this thread.

Here’s the CSS and the image markup:

img {
  --width: 0;
  --height: 0;
  --ideal-area: 40000;
  --area: calc(var(--logo-width) * var(--logo-height));
  --ratio: calc(var(--ideal-area) / var(--area));
  --guess01: calc(calc(var(--ratio) + calc( var(--ratio) / var(--ratio))) / 2);
  --guess02: calc(calc(var(--guess01) + calc( var(--ratio) / var(--guess01))) / 2);
  --guess03: calc(calc(var(--guess02) + calc( var(--ratio) / var(--guess02))) / 2);
  --guess04: calc(calc(var(--guess03) + calc( var(--ratio) / var(--guess03))) / 2);
  --guess05: calc(calc(var(--guess04) + calc( var(--ratio) / var(--guess04))) / 2);
  --guess06: calc(calc(var(--guess05) + calc( var(--ratio) / var(--guess05))) / 2);
  --guess07: calc(calc(var(--guess06) + calc( var(--ratio) / var(--guess06))) / 2);
  --guess08: calc(calc(var(--guess07) + calc( var(--ratio) / var(--guess07))) / 2);
  max-width: calc(var(--width) * var(--guess08) / 2 * 1px);
}
<img style="--width: 1500; --height: 3000;" src="https://piperhaywood.com/my-image.jpg">

I’d want to do some more browser testing since this results in a pretty gnarly calc() situation by --guess08, but at first glance this seems like it might be a worthwhile solution. It doesn’t give us exactly proportionate surface areas but it gets very close. It only starts to fall apart with super skyscraper-y and letterbox-y images.

A few quick notes regarding why this is written as it is and ways that it could be tweaked:

I capped the number of guesses at eight because any more seemed to just fail, Chrome and Safari wouldn’t interpret such a big calc() equation.

I set the default width and height to zero so that there is no max width restriction if the image tag is missing the width and height CSS variables. This could be changed, as could the ideal area variable (increase to get larger images, decrease to get smaller).

The 1px value in the max-width calculation is required so that the value is interpreted as a unit. That said, it doesn’t have to be pixels! Could change this to another unit like 1em or 1%.

If I wanted to display these evenly centred, I’d probably give the images some margin and then wrap them in a container with styles as below:

.container {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

Could also use CSS grid for a more consistent spacing result.

And a final reminder: this only visually scales the images. Try to avoid loading a 3000px wide image if you’re going to be displaying it around 200px wide, your users and the planet will thank you.

A CSS-only solution that might work in the future

So apparently more complex math functions including sqrt() might be coming to CSS in the future! See this issue raised by Lea Verou in the CSS specifications editor’s drafts repo and the exponential functions section from CSS Values and Units Module Level 4 in the W3C editor’s draft from 3 February 2020 (a couple days ago!).

I’m not sure when this would become part of the spec and no idea if / when the browsers might implement them, but here is a snippet that should work with that new function in theory:

img {
  --width: 0;
  --height: 0;
  --ideal-area: 40000;
  max-width: calc(var(--width) * sqrt(calc(var(--ideal-area) / calc(var(--width) * var(--height)))) / 2 * 1px);
}

I’m happy that Nick asked the question on Twitter, I actually need this on an upcoming project where I’ve only got Twig to work with which doesn’t support square roots, and I’d prefer to avoid JavaScript in this instance. Hopefully this is the solution, will update here if so.

A picture says a thousand words, so see Nick’s very nice demo of area-based image sizing with CSS to check out one possible outcome.


Edit 05.02.20

Edited a few words for clarity, added Nick’s demo, added future example incorporating a CSS-based sqrt() function.

Thanks Sam Baldwin for bringing future math function support in CSS to my attention!

Edit 06.02.20

Simplified the PHP + HTML example.

The original PHP + HTML example used a --max-width CSS variable instead of just applying a max-width directly. I used a CSS variable because I thought that they were compliant with a strict Content Security Policy that includes the style-src directive set to unsafe-inline. That assumption was incorrect, though there does seem to be some discussion about the topic.

Thanks Lizzie Malcolm for questioning the CSS var usage in the PHP example!

Edit 18.02.20

Changed parenthesis-enclosed arithmetic so that each is enclosed in calc(). Plain CSS seems to interpret arithmetic enclosed in parenthesis just fine, but SASS doesn’t seem to like it.

Published

Switching from Google Analytics to Matomo (f.k.a. Piwik) on WordPress

It’s a new decade, time to leave Google Analytics.

A big part of me wants to say screw it, just get rid of analytics altogether. But I find it interesting. I’ve never used it to decide what to write, and I don’t think I ever will, but it’s just fascinating to find out what makes the rounds. I’ll never know why a short post about repairing my mom’s straw bag was my most popular post for years, but I’m glad to know a lot of people checked it out.

So I decided to keep my Google Analytics property in place and just locked it down as much as I could. I adjusted the script to respect users’ Do Not Track browser settings (Paul Fawkesley has a short article about how to do this). I also configured Google Analytics to anonymise IP addresses, and I deliberately disabled Data Collection for Advertising Features, Demographics and Interest Reports, User-ID, and all data-sharing settings. I also set a low data retention policy to make sure old data would get deleted.

None of this changed the fact that I was still sharing data with Google.

Read more

Published

Date-based colour

Read “Dynamic, Date-Based Color with JavaScript, HSL, and CSS Variables” by Rob Weychert

This is such a useful article. His implementation on Tinnitus Tracker is definitely more involved than what I’ve done on this site, particularly what he’s done to account for inherent saturation levels and lightness vs luminance. And his colour wheel mapping is slightly offset from mine. I feel like August is the reddest month! I’ve wanted to reconsider the colour here for a while, particularly since the accessibility of some of the hues isn’t up-to-snuff. Rob’s write-up might make that adjustment a bit more straightforward which is a big relief.

I remember being really interested in where Grant Custer went with colour on his blog when I started screwing around with colour on this site. See his blog in 2013 on the Internet Archive. I wanted to see whether or not there was some way to ambiguously reflect where I was in the world, particularly since I live so far away from most of my family.

The first version of the colour experimentation on this site mapped the HSL values to the season, temperature, and time of day where I was at the time the site was visited. This is an example from Paris in late 2016. The hue value was mapped to the date/season (same as now), and the lightness was mapped to the time of day using Moment.js and Moment Timezone. The goal was to map the saturation to the weather where I was using the OpenWeatherMap API with stormy and cloudy days being less saturated, but that never came to be since the weather descriptions weren’t consistent enough. I ended up mapping the saturation to the temperature instead, but I don’t think it was quite as effective.

When I turned the site in to a blog first and foremost, I dropped the location and weather aspect. It could be fun to return to it since it might bring a bit more variation, particularly on the list page. Might be a little wild though, and it might be a massive headache to introduce location and weather on old posts… At bare minimum, I could probably incorporate the time of day as lightness. We’ll see!

Published

gemmacope.land

gemmacope.land

Gemma Copeland’s new site is online! This was really fun, one of the truest collaborations I’ve done in a while. Minimal JavaScript, Eleventy + Netlify, Arena API fun, unicode arrows, accessibility at the fore. It was an exercise in playful sufficiency, hopefully we’ve created a functional sandbox that she can work with for some years to come.

I’m hoping to write a bit more about the development at some point, particularly on working with the Arena API. Ran in to some interesting hurdles with block ordering! In the meantime, see the repository on GitHub and check out the making-of post on her website.

Published

Notes from Redecentralize 2019

Been a busy few days with Redecentralize on Friday followed by MozFest over the weekend. Redecentralize was a one-day unconference at 4th Floor Studios in Whitechapel. The event was expertly organised by Ira Bolychevsky and her crack team.

It was a day of thought-provoking conversations and notebook scribbling. This is an attempt to decode the scribbles, make some follow-up plans, and to generally summarise the day from my perspective. There was a lot going on so I can’t cover it all, but I’m going to keep an eye out for other people’s notes via the Redecentralize newsletter.

\              \                      \                   \
\\\   \   \    \\            \        \\       \       \  \\
\\\\\ \\\ \\\  \\\   \    \  \\     \ \\\  \   \\  \   \\ \\\ \
\\ \\\\\\\\\\\ \\\\ \\\\  \\\\\\   \\\\\\\\\\\ \\\ \\\ \\\\\\\\
\\   \\\  \\\\\\\ \\\\\\\\\\\\\\\\\\\\\\ \\ \\\\\\\\\\\\\\\\  \
 \     \    \\  \   \    \\\  \  \\\   \  \   \\\ \\\ \\\  \   
              \            \       \            \   \   \

Read more