Fuzzy LogicFuzzy Logic is the personal website of Laurence Hughes, a web developer based in Glasgow, Scotland.2024-03-12T14:52:15Zhttps://fuzzylogic.me/Laurence Hugheslaurence@fuzzylogic.meData Visualization Design Guidelines (by Smashing Mag)2024-03-12T14:52:15Zhttps://fuzzylogic.me/posts/data-vis-smashing/<p>Here are a bunch of great tips and resources for creating charts and graphs, condensed into a 6-minute read.</p>
<p>It’d be interesting to look at the key recommendations in this article and compare our web-based charts at work against them.</p>
<p>My thanks to Vitaly and the Smashing team for this roundup.</p>
The Rescue2024-03-06T11:36:16Zhttps://fuzzylogic.me/posts/the-rescue/<p>This retelling of an incredible story featuring unbelievable examples of human skill, endurance and hope is the best TV programme I’ve watched in years.</p>
<blockquote>
<p>Chronicling the story that transfixed the world in 2018 – the daring rescue of 12 boys and their coach from deep inside a flooded cave in northern Thailand. This film shines a light on the high-risk world of cave diving, the astounding courage and compassion of the rescuers and the shared humanity of an international community that united to save the boys.</p>
</blockquote>
Recently read: Lost Connections by Johann Hari2024-03-04T10:00:00Zhttps://fuzzylogic.me/posts/just-read-lost-connections/<p>When chatting with a consellor in January about some bouts of low mood and mental fatigue, I described one symptom as a strange sense of <em>disconnection</em>. And while the recent lockdowns during the pandemic were obvious contributors to that, they didn’t feel like the full story.</p>
<p>Reassuringly it seems I’m far from alone in feeling this way, since one of her suggestions was to read Johann Hari’s bestselling book <a href="https://uk.bookshop.org/p/books/lost-connections-why-you-re-depressed-and-how-to-find-hope-johann-hari/910739?ean=9781408878729">Lost Connections: why you’re depressed and how to find hope.</a></p>
<p>Hari argues that the primary factors causing depression and anxiety are environmental and societal – not the “chemical imbalance” nor the pill-based solution story we’ve been sold for so long.</p>
<p>Hari frames depression and anxiety as natural reactions to and signifiers of an imbalance caused by unmet human psychological needs. The modern world can be lonely and runs on dubious values. We need community, meaningful values, interaction with the natural world, a sense of worth and being respected, a secure future, and release from any shame resulting from previous mistreatment.</p>
<p>On the whole I really enjoyed this book – well, as much as you can enjoy a book about depression!</p>
Live at the Liquid Room, Tokyo (review by Pitchfork)2024-02-25T14:44:01Zhttps://fuzzylogic.me/posts/pitchfork-review-mills-liquid-room/<p>Pitchfork’s review of Jeff Mills’ seminal mixtape is the best-written and most enjoyable music article I’ve read in years. The mixtape in question is also very close to my heart.</p>
<blockquote>
<p>this is a mix without equal, the Techno Bible, unequivocally The One.</p>
</blockquote>
<blockquote>
<p>Then, as now, Liquid Room stands as a high-water mark of a Black artform built around space travel and the necessity of forward motion: ’90s techno at its most unyielding and free.</p>
</blockquote>
<p>Agreed! Fun fact: in 1996, having played the shit out of my cassette copy for a few months, I went to see Jeff DJ at the Arena in Glasgow in 1996 and he signed the inlay! I would normally be embarassed at having done this… but not in this case.</p>
Weekend in the ‘hood2024-02-15T09:20:00Zhttps://fuzzylogic.me/posts/southside-february-weekend/<p>Last weekend was pretty dull and rainy in Glasgow but Clair and I visited a bunch of great local places to keep the spirits up.</p>
<p>On Friday night we ate at <a href="https://wasabiglasgow.co.uk/">Wasabi</a> for the first time. It’s a lovely little spot on Pollokshaws Road with a <a href="https://wasabiglasgow.co.uk/">nicely-sized menu</a>. Between us we had Chicken Karage, Avocado Maki, King Prawn Tempura and Beef Ramen. We loved it and will be back.</p>
<p>On Saturday early afternoon we took Rudy for a walk around Pollokshields including Maxwell Park. We were then able to leave him nicely tired and chillin’, and headed to the <a href="https://www.tramway.org/event/b1e2f38f-38c8-4135-b8ef-b103009c4ee4">FONDS exhibition at the Tramway</a>.</p>
<p>Next was a visit to Pisces although we were runnning a bit early so stopped for a drink at Heraghty’s. Tom and Nessa have been telling me they do a good pint of Guinness so I gave it a try.</p>
<p>At Pisces (which was once the site of the legendary <em>Greek Golden Kebab</em>) we both tried the Smash burger and fries, and it was pretty tasty.</p>
<p>We’d hoped to visit the ‘hood’s latest cafe, bar and restaurant <a href="https://www.instagram.com/henrysglasgow/?hl=en">Henry’s</a> for a nightcap, but on arrival there it was jam-packed so we resolved to come back another time.</p>
Weekend at Charlton Gate cottage, Northumberland2024-01-30T09:14:53Zhttps://fuzzylogic.me/posts/northumberland_trip/<p>Prior to Christmas we’d been talking about giving ourselves the present of a trip to London. However the train prices were pretty offensive so we opted for a different type of weekend trip – one that was rural, cosy and Rudy-friendly.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1706961167/Rudy_CharltonGate_1300_nsq6ub.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1706961167/Rudy_CharltonGate_1300_nsq6ub.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1706961167/Rudy_CharltonGate_1300_nsq6ub.jpg" width="1300" height="1733" alt="A happy border terrier sits for the camera outside a rural cottage" />
</picture>
<figcaption>Happy Rudy outside Charlton Gate cottage in Northumberland</figcaption>
</figure>
<p>Friday’s check-in wasn’t til 4pm so we started with a drive to North Berwick. There, we visited the <a href="https://www.lobstershack.co.uk/">Lobster Shack</a>. Clair had fish and chips while I had seafood chowder (which Clair admitted was the pick of the dishes). The weather was of the good January sort – chilly but sunny so we had a wee stroll along the beach and let Rudy have a run.</p>
<p><a href="https://www.airbnb.co.uk/rooms/51219157?source_impression_id=p3_1706962399_4Fe%2BGwkjVw%2BncR1l">Charlton Gate cottage</a> was perfect. We were in splended isolation, except for the neighbouring sheep and grouse. The cottage itself was comfortable with all the cooking and telly-watching facilities you’d need, plus a comfy bed.</p>
<p>On Saturday we visited Newbiggin-by-the-sea for more beach-walking fun.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1706962553/Laurence_Rudy_Newbiggin_1300_tiu1fd.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1706962553/Laurence_Rudy_Newbiggin_1300_tiu1fd.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1706962553/Laurence_Rudy_Newbiggin_1300_tiu1fd.jpg" width="1300" height="1733" alt="A smiling man wearing a green jacket and blue beanie hat crouches beside his happy border terrier dog on the beach" />
</picture>
<figcaption>Laurence and Rudy take a break on their beach walk (while Clair takes the photo)</figcaption>
</figure>
<p>Later that day we also paid a brief visit to Morpeth, which is a lovely town.</p>
<p>I really enjoyed my morning walks with Rudy. It was so peaceful and the sky and scenery were beautiful.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1706963031/morning_walk_charlton_gate_1300_hlvxxg.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1706963031/morning_walk_charlton_gate_1300_hlvxxg.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1706963031/morning_walk_charlton_gate_1300_hlvxxg.jpg" width="1300" height="1733" alt="A beautiful morning sky over fields" />
</picture>
<figcaption>Morning sky as Laurence and Rudy go on their Sunday morning walk in Northumberland</figcaption>
</figure>
<p>Thanks as always to my fam Clair and Rudy for a beautiful weekend.</p>
Bye, Twitter2024-01-24T20:17:15Zhttps://fuzzylogic.me/posts/i-just-deactivated-my-twitter-account/<p>I just deactivated my Twitter (X) account. Within the wider current context of other small, positive changes I’m making, it feels like the time is right.</p>
<p>I gave it a little thought, but not much. There were plenty of reasons to deactivate (for my own good and because X under Elon is x-crutiating) and not many good reasons to stay.</p>
<p>I used their <em>download your archive</em> feature before deactivating.</p>
<p>I guess I might lose a bit of touch with some web and music folks but I’m sure I’ll catch up with them in other ways.</p>
<p>And I s’ppose someone might try to get in touch via Twitter and find I’m no longer there, but if they want to find me online, I’m sure they will.</p>
<p>One less avenue for procrastination!</p>
January blues-banishing in Edinburgh2024-01-21T09:14:53Zhttps://fuzzylogic.me/posts/january-blues-banishing-in-edinburgh/<p>I’m starting 2024 as I mean to continue – by seeing and hanging out with friends more often. Yesterday <a href="https://tomchurchill.com/">Tom</a> and I had a great day moseying around Edinburgh.</p>
<p>After meeting at Waverley and grabbing a quick coffee and bite, we headed to the Scottish National Gallery on The Mound. Tom was keen to see the <a href="https://www.nationalgalleries.org/exhibition/turner-january">Turner watercolours exhibition</a> which is on every January – apparently the ideal time of year to best show off the works. I probably wouldn’t have visited this unprompted but I’m glad I did. My favourites were perhaps <a href="https://www.nationalgalleries.org/art-and-artists/19242?collection=46&artwork=37">The Falls of Clyde</a> and <a href="https://www.nationalgalleries.org/art-and-artists/19238?collection=46&artwork=10">Lake Albano</a>.</p>
<p>From there we made the short walk to Cockburn Street and into an old haunt, <a href="https://undergroundsolushn.com/">Underground Solush’n</a>, for some record shopping. I got a few, with the pick being the album <a href="https://devendrabanhart.bandcamp.com/album/flying-wig">Flying Wig by Devendra Banhart</a>.</p>
<p>Next stop was St Andrew’s Square for a saunter around the menswear floor in Harvey Nichols. Neither of us were in the market for anything in particular but still it was nice to browse their sale including coats by Copenhagen-based brand <a href="https://www.nn07.com/en/uk/">NN.07</a> as sported by Jeremy Allen White in <a href="https://m.imdb.com/title/tt14452776/">The Bear</a>.</p>
<p>We hopped on an Edinburgh tram outside (first time for both of us) headed for Port of Leith. We caught the <a href="https://www.tripadvisor.co.uk/Attraction_Review-g186525-d10061789-Reviews-Leith_Market-Edinburgh_Scotland.html">Leith Saturday market</a> where Tom was beguiled by a purveyor of exotic olive oil (I can't believe I'm typing this) before we stumbled upon a great wee record stall. To my surprise it wasn’t just the usual selection of records no-one wants but instead had plenty of gems. I picked up two LPs from my wishlist – Vangelis's Earth (featuring the glorious <a href="https://youtu.be/sYXL2WwQn1I?si=GWxoTE0aCFwwwl5G">Let it happen</a>) and Spacek’s <a href="https://www.discogs.com/release/218037-Spacek-Curvatia">Curvatia</a>.</p>
<p>All that record shopping gives you an appetite so it was off to <a href="https://teuchtersbar.co.uk/teuchters-landing-bar-edinburgh/">Teuchter’s Landing</a> for some food and refreshments. With Burns Night just around the corner we honoured the bard by enjoying haggis, neeps and tatties and a dram (Craigellachie 13y).</p>
<p>Our final stop was the <a href="https://www.fishersrestaurants.co.uk/shore-bar-and-restaurant/">Shore Bar</a> where we caught up with a couple of Edinburgh-dwelling pals, Gav and Nick.</p>
<p>After all that I was back on the train home by around 10 pm – mission accomplished.</p>
Sunday dinner at Ox and Finch2024-01-17T20:17:15Zhttps://fuzzylogic.me/posts/sunday-dinner-ox-finch/<p>My generous nieces and nephews clubbed together to give us the Christmas present of a voucher for <a href="https://www.oxandfinch.com/">Ox and Finch</a>. Keen to use it, we got together with James and Grant for a lovely Sunday dinner.</p>
<p>It’s a “small plates” affair, so sharing is the order of the day. We had sourdough and butter (the bread in good restaurants is always amazing), whipped feta with honey, fried artichokes with garlic yoghurt, and – my two favourites – the crab tubetti and beef tartare. To drink I had a white wine – the ‘le campuget’ grenache viognier – then their <em>px old fashioned</em> (the <em>px</em> standing for pedro ximénez).</p>
<p>We also shared the warm ginger cake with poached pear, while James had the affogato.</p>
<p>It was fantastic and – thanks to that thoughful gift – didn’t cost us a penny. What a great Christmas present.</p>
Teabag on a spoon technique2024-01-15T17:17:15Zhttps://fuzzylogic.me/posts/teabag-on-spoon/<p>At work today I mentioned Mr Scruff’s tip for quick tea-making. My teammates laughed and said they felt like they were on an episode of <em>Would I lie to you?</em> I had to prove I wasn’t talking rubbish and went looking for the tip online. It has all but disappeared from the web but thanks to <a href="https://archive.org/web/">Wayback Machine</a> I was able to find a cache of the page from 2007.</p>
<p>So here is the tea-making tip, listed in full for posteri-tea! (Sorry…)</p>
<p>Mr Scruff starts by saying:</p>
<blockquote>
<p>Some people ask me about the teabag on a spoon technique, which I learnt from Peter Parker of Fingathing. Here is the full breakdown of the method for making black tea in a mug with a teabag.</p>
</blockquote>
<p>And here are the steps:</p>
<ol>
<li>Boil the kettle with fresh water… no reboiling!</li>
<li>Warm the mug… you can do this by pouring in a little warm water from the kettle while it is boiling, swishing it around & emptying it. This will help keep your brew warm for longer, essential for forgetful types like myself!</li>
<li>Pour milk into the cup. If this offends you, you can add it later.</li>
<li>Take a spoon (tablespoons are best, but a teaspoon will do)</li>
<li>Place the teabag on the spoon, and hold it horizontally over the mug.</li>
<li>When the kettle has boiled, hold it over the teabag, and pour as slowly as possible from as high as possible, without making the water splash upwards off the teabag. If you are doing this correctly, you will see little bubbles in the teabag, which is a sign of the oxygen in the boiling water doing its job.</li>
<li>When the cup is full, add the milk if you have not done so, and examine your brew. If your tea is the correct colour (mine is a kind of brick red/malty brown) then you can discard the teabag. If it is not strong enough for your taste, then delicately lower the teabag onto the top of the tea, and slip the spoon out from under it. Leave it there until the brew is strong enough, and gently remove the bag with the spoon. There is no need to stir the bag or squash it in any way..tease the flavour out!</li>
<li>Add sugar/salt/cheese/pickle to taste.</li>
<li>Sit down and enjoy your brew!</li>
<li>Repeat from stage 1.</li>
</ol>
<p>Cheers!</p>
<p>PS if you don’t already know Mr Scruff I heartily recommend <a href="https://www.mrscruff.com/">getting acquainted</a>.</p>
My 2023 in review2024-01-02T15:49:53Zhttps://fuzzylogic.me/posts/my-2023-in-review/<p>How was 2023 for you? For me, it was like this.</p>
<h2 id="music-gigs" tabindex="-1">Music gigs <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#music-gigs" aria-hidden="true">#</a></h2>
<p>In welcome contrast to the Covid years I went to a variety of in-person events, including seven gigs:</p>
<ul>
<li>Apiento in London,</li>
<li>Melting Pot at Queen’s Park Rec (where I saw Luke Una and Odyssey),</li>
<li>Melting Pot vs Let’s Go Way Back at BAAD,</li>
<li>Om Unit at Sleazy’s,</li>
<li><a href="https://fuzzylogic.me/posts/henke-tramway/">Robert Henke at Tramway</a>,</li>
<li>A Certain Ratio at Stereo in November, and</li>
<li>Sleaford Mods in December.</li>
</ul>
<p>Of those, my highlights were definitely Robert Henke and A Certain Ratio.</p>
<h2 id="music-buying%2C-listening-and-playing" tabindex="-1">Music buying, listening and playing <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#music-buying%2C-listening-and-playing" aria-hidden="true">#</a></h2>
<p>I’m still buying music on vinyl and more, albeit at a slightly reduced rate. My taste continues to shift organically and I really enjoy exploring. My highlights included <a href="https://www.discogs.com/release/28911571-Skinshape-Craterellus-Tubaeformis">Skinshape’s Craterellus Tubaeformis</a>, <a href="https://www.discogs.com/release/26602412-A-Certain-Ratio-1982">A Certain Ratio’s 1982</a> and <a href="https://www.discogs.com/release/28178659-Jamma-Dee-Perceptions">Jamma-Dee’s Perceptions</a>.</p>
<p><a href="https://fuzzylogic.me/tags/radio/">I recorded three radio shows</a> and was pretty pleased with them, on the whole.</p>
<h2 id="seeing-friends" tabindex="-1">Seeing friends <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#seeing-friends" aria-hidden="true">#</a></h2>
<p>My April trip to London with <a href="https://tomchurchill.com/">Tom</a> was a real highlight of the year. We went record and clothes shopping, caught up with friends, listened to great music in brilliant venues, and enjoyed some lovely food and drinks. If Carlsberg did weekends, they’d struggle to top that one.</p>
<p>There were lots of other fun get-togethers.</p>
<p>When I look back, I realise that I’ve done not too badly at keeping in touch with friends in 2023. Obviously there are those that I saw too rarely or not at all, and I’ll try to rectify that in the new year.</p>
<p>One sadder entry: in late August, my close pal Simon’s mum died. It was a beautiful ceremony for an inspirational lady.</p>
<h2 id="travel" tabindex="-1">Travel <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#travel" aria-hidden="true">#</a></h2>
<h3 id="abroad" tabindex="-1">Abroad <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#abroad" aria-hidden="true">#</a></h3>
<p><a href="https://fuzzylogic.me/tags/travel/">I travelled</a> to six different countries, if you include England.</p>
<p>First stop was Amsterdam in June for work: I attended the CSS Day conference for the second year running.</p>
<p>Also in June. Clair and I went to Sicily for Fiona’s 40th birthday, staying in Palermo then Taormina.</p>
<p>In August Clair and I enjoyed ten days in Geneva and Annecy.</p>
<p>In November <a href="https://fuzzylogic.me/posts/marbella-with-mum-and-dad/">I took my parents for a week in Marbella</a>.</p>
<h3 id="in-scotland" tabindex="-1">In Scotland <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#in-scotland" aria-hidden="true">#</a></h3>
<p>I enjoyed a couple of trips around Scotland.</p>
<p>There was our March <a href="https://fuzzylogic.me/posts/weekend-at-drinkbetween-cottage/">weekend at Banchory Farm in Fife</a>.</p>
<p>Then in July I had an overnight stay in Alyth.</p>
<h2 id="eating-out" tabindex="-1">Eating out <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#eating-out" aria-hidden="true">#</a></h2>
<p>While in London, Tom and I enjoyed a nice breakfast at Fallow on Clair’s recommendation. (Although she was subsequently horrified at me missing the foodie opportunity by only ordering scrambled eggs on toast! My excuse is I was hungover and needed comfort food). On the same trip we had amazing sushi at <a href="https://brilliantcornerslondon.co.uk/">Brilliant Corners</a> in Dalston. It really is my happy place.</p>
<p>In Spring, Clair and I had an overdue catchup with Charlie over a lovely lunch at <a href="https://inverrestaurant.co.uk/">Inver</a>.</p>
<p>I made a first visit to Dishoom in Edinburgh, alongside two good pals, and it lived up to the hype.</p>
<p>In autumn I enjoyed a lovely Saturday afternoon at <a href="https://www.crabshakk.co.uk/">Crabshakk</a> on Byres Road with Gillian, Tom and Nessa.</p>
<p>On Hogmanay, <a href="https://fuzzylogic.me/posts/brett-hogmanay-23/">Clair and I ate at Brett</a> and loved it.</p>
<p>Special mention has to go to our evening at Café du Soleil in Geneva where we both had our first taste of fondue. Cheese heaven.</p>
<h2 id="family" tabindex="-1">Family <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#family" aria-hidden="true">#</a></h2>
<p>All the major family-related activity seemed to happen in June. Sadly, my Aunt Elsie died. She was in her nineties and the last ten years had seen a steep decline.</p>
<p>On a happier note my niece Caitlin married her partner Ross in June in a beautiful wedding at Lochside House Hotel.</p>
<p>My niece Charlotte had her second child – Mason, a brother for Marc.</p>
<p>That eventful June aside, everything seems to be ticking along. My mum and dad are well. Clair had a challenging year with work, but the work she does is brilliant and with fantastic clients. She’s generally doing well and happy in her new fitness groove, which makes me happy too.</p>
<p>Rudy, our nervous border terrier, has been a mixed bag behaviour-wise, but mostly good. There are lots of signs of improvement. And regardless of the behavioural issues he is just a wee legend who’s full of love and we adore him.</p>
<h2 id="books" tabindex="-1">Books <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#books" aria-hidden="true">#</a></h2>
<p>It wasn’t a productive year for reading; I just couldn’t find the motivation. Still, <a href="https://fuzzylogic.me/tags/book/">I read a few</a>.</p>
<ul>
<li>Possibilities, Herbie Hancock’s autobiography</li>
<li>Open, Andre Agassi’s autobiography</li>
<li><a href="https://fuzzylogic.me/posts/join-the-future/">Join the Future</a></li>
<li>The Islander</li>
</ul>
<p>And I started The Candy House.</p>
<p>The good news is that they are all great, and recommended.</p>
<h2 id="films" tabindex="-1">Films <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#films" aria-hidden="true">#</a></h2>
<p>Of note were Aftersun and Oppenheimer, the latter of which I saw at the GFT in July.</p>
<p>I also saw <a href="https://fuzzylogic.me/posts/captain-fantastic/">Captain Fantastic</a> which isn’t new but is… fantastic!</p>
<h2 id="other-arts" tabindex="-1">Other arts <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#other-arts" aria-hidden="true">#</a></h2>
<p>In January we visited the Tramway theatre and checked out two exhibitions. The first was <a href="https://www.tramway.org/event/4abdfe69-2eea-4921-a9f4-aee500f041af">a selection of works by Glasgow artist Norman Gilbert</a>, and the second the installation <a href="https://www.tramway.org/event/d0c95f0d-cec7-4467-beed-aef300fb7d34">The Rumble of a Tireless Land</a> by Iza Tarasewicz.</p>
<p>In July I went to <a href="https://fuzzylogic.me/posts/banksy-at-goma/">Banksy’s <em>Cut and run</em> exhibition</a> at the GOMA, which I loved. Later that month I saw the excellent <a href="https://www.tron.co.uk/shows/moorcroft-2/">Moorcroft at the Tron</a> theatre.</p>
<p>In September I went to the Armadillo to see the updated version of The Celtic Story with Marty and Michael (with thanks to Gillian for the tickets). I had first seen this thirty years previous and it was nice to revisit the club’s history.</p>
<h2 id="tv" tabindex="-1">TV <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#tv" aria-hidden="true">#</a></h2>
<p>Back in January I loved <a href="https://fuzzylogic.me/posts/mystery-road-origin/">Mystery Road – Origin</a>.</p>
<p>Later in the year, the Succession finale really lived up to its billing – a fitting end to a brilliant show.</p>
<p>Latterly I really enjoyed <a href="https://www.imdb.com/title/tt7472896/">Mr Inbetween</a>. Scott Ryan, the lead, is a talent.</p>
<h2 id="other-noteworthy-stuff" tabindex="-1">Other noteworthy stuff <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#other-noteworthy-stuff" aria-hidden="true">#</a></h2>
<p><a href="https://fuzzylogic.me/posts/making-coffee-with-sage-barista-touch/">I learned to make coffee from whole beans.</a></p>
<p>I’ve been learning Spanish, using <a href="https://www.languagetransfer.org/complete-spanish">Language Transfer’s course</a> and am enjoying that.</p>
<h2 id="work" tabindex="-1">Work <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#work" aria-hidden="true">#</a></h2>
<p>I’m lucky – I have a good job with great benefits. I work with smart and lovely people. Even still, me and my job don’t always see eye to eye.</p>
<p>In the positive column for 2023:</p>
<ul>
<li>our team was instrumental in implementing a brand refresh</li>
<li>we made material progress in promoting company-wide accessible practices</li>
<li>I began learning how to write documentation more formally, and we have made strides on that front</li>
<li>at scoring I seem to be progressing and had some nice feedback</li>
<li>I’m trying to get better at empowering others. I’m having some success but have <em>lots</em> of room for improvement</li>
<li>I went to three inspiring conferences: CSS Day, Design Systems Day in Edinburgh, and my employer’s own internal staff conference which was excellent.</li>
</ul>
<p>In the negative column:</p>
<ul>
<li>I had at least one mental blowout. It was caused by thinking too deeply about a complex and frustrating area. It left me in pretty bad shape mentally, and needing time off.</li>
<li>latterly I lost energy and focus. I couldn’t find energy to read the various articles I receive by subscription, nor write on my blog. This marked a change for me – I’m usually pretty motivated in that regard.</li>
</ul>
<h2 id="health" tabindex="-1">Health <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#health" aria-hidden="true">#</a></h2>
<p>My physical health was fine. I’m doing enough exercise to keep my weight in check. I can’t remember being ill very often, although being stuck in bed with the cold on my birthday was no fun. I could always be fitter but generally speaking I’m physically fit and well.</p>
<p>A couple of small but impactful changes of note: after Clair told me about <a href="https://theguardian.com/lifeandstyle/2022/may/15/go-with-your-gut-tim-spector-power-of-microbiome">Tim Spector</a> and how we shoud avoid spiking our blood sugar, I cut out the large glass of Tropicana orange juice I drank daily for years. I also cut down the amount of granola I eat at breakfast and swapped in nuts and seeds, or a breakfast of brown toast and eggs. This is no doubt having a positive impact on my weight but also, I hope, keeping me healthier long-term. On a similar note, I now try hard to go to sleep earlier and avoid feeling the need to snooze the alarm.</p>
<p>As for mood and mental stability, that’s less straightforward. Firstly I’ve noticed changes to preferences and comfort zones. There are situations I used to enjoy – such as larger gatherings – and now don’t. Generally I’m OK with this. It could be a post-pandemic effect, or a symptom of ageing. Regardless it feels natural so I’m adapting. As long as I find time to see the important people in my life one way or another, it’s fine.</p>
<p>More concerning were the too-regular occurences of low mood, low energy, frustration and mental fatigue. Working on a Design System team <a href="https://amyhupe.co.uk/articles/burn-baby-burnout/">can feel overwhelming</a> or futile or both. Working primarily from home saves time and money but can feel claustrophobic, and mixes parts of life that should be separate. I also generally find too many things vying for my attention and struggle to focus. A big, noticeable change is that my mental resilience isn’t what it was.</p>
<p>While low mood has a significant negative impact on me, it can impact others too. At times I’ve struggled to see the bigger picture and dropped the ball, forgetting people I should prioritise.</p>
<p>In summary my mental health wasn’t always great and it was time to acknowledge that properly. Since then I’ve done this and I feel better for it. There’s a journey ahead. Maybe I’ll write about it more soon.</p>
<h2 id="let%E2%80%99s-go-round-again" tabindex="-1">Let’s go round again <a class="direct-link" href="https://fuzzylogic.me/posts/my-2023-in-review/#let%E2%80%99s-go-round-again" aria-hidden="true">#</a></h2>
<p>So long, 2023 – you were mostly pretty good and I’m grateful. Even the bad bits have given me helpful pause for thought. I’ve been making positive change already, so onwards and upwards.</p>
Revealing back to top link, by David Darnes2024-01-01T22:50:01Zhttps://fuzzylogic.me/posts/back-to-top-with-modern-css/<p>David cleverly uses CSS alone (and only a few lines) to show a “back to top” link only after the user has started scrolling, then pin its position to the bottom-left of the screen.</p>
<p>The clever <code>margin-top: 110vh</code> combined with <code>position: sticky</code> – since <code>110vh</code> is slightly more than 100% of the page’s height – gives the link a <em>starting position</em> that is not initially visible but becomes visible once the user starts scrolling. The <code>bottom: 0</code> then ensures that when the user continues scrolling vertically the link “sticks” to the bottom-left of the page.</p>
<p>So little code and so clever!</p>
<p>PS if you’re wondering why you’d want a “back to top” link in the first place, it’s to let a user who has scrolled far down a long page to easily get back to options located at the top. See <a href="https://www.nngroup.com/articles/back-to-top/">NN Group’s Back-to-Top Button Design Guidelines</a>.</p>
Hogmanay lunch at Brett2023-12-31T17:17:15Zhttps://fuzzylogic.me/posts/brett-hogmanay-23/<p>Clair and I just rounded off the year in style with lunch and drinks at <a href="https://www.barbrett.co.uk/">Bar Brett</a> on Great Western Road. We had a bird’s eye view too, sat overlooking the pass watching the chefs at work.</p>
<p>Between us we enjoyed a variety of small dishes including oysters, sourdough bread with chicken fat butter, cod toast, smoked beetroot with tahini, clams, lobster ravioli, mushroom XO linguine, Peterhead Coley with curried mussel sauce and a Basque cheesecake.</p>
<p>We tried a few glasses of wine: Veiled Vineyards Old Vine Semillon (white), a Delamotte Blanc de Blancs (champagne), and Le Grand A (Burgundy white) – all lovely.</p>
<p>Brett is fantastic and the staff made us feel very welcome.</p>
Post-Xmas Panzanella2023-12-29T20:18:15Zhttps://fuzzylogic.me/posts/post-xmas-panzanella/<p>We just enjoyed a lovely festive visit to Doug and Zoe’s house where we hung out with them and their girls Zara and Nina. As an unexpected bonus our friend Pablo also stopped by.</p>
<p>After the rush and stress of organising Christmas it was just what the doctor ordered. Doug made a delicious and light panzanella salad. I taught Zara how to play hangmam on good ol’ pencil and paper. We enjoyed a chat and a laugh.</p>
<p>Cheers, pals!</p>
It's 2023, here is why your web design sucks (by Heather Buchel)2023-11-04T17:34:01Zhttps://fuzzylogic.me/posts/heather-buchel-its-2023-heres-why-your-design-sucks/<p>Heather explores why we no longer have “web designers”.</p>
<blockquote>
<p>It's been belittled and othered away. It's why we've split that web design role into two; now you're either a UX designer and you can sit at that table over there or you're a front-end developer and you can sit at the table with the people that build websites.</p>
</blockquote>
<p>Heather makes lots of good points in this post. But the part that resonates most with me is the observation that we have split design and engineering in a way that is dangerous for building proper websites.</p>
<blockquote>
<p>We all lost when the web design role was split in two.</p>
</blockquote>
<blockquote>
<p>if our design partners are now at a different table, how do we expect them to acquire the deeply technical knowledge they need to know? The people we task with designing websites, I've found, often have huge gaps in their understanding of… the core concepts of web design.</p>
</blockquote>
<p>Heather argues that designers don’t need to learn to code but that “design requires a deep understanding of a subject”. Strong agree!</p>
<p>Likewise, the arrival and evolution of the front-end role such that i) developers are separate from designers; and ii) within developers there’s a further split where the majority lack “front of the front-end” skills has meant that:</p>
<blockquote>
<p>We now live in a world where our designers aren't allowed to… acquire the technical design knowledge they need to actually do their job and our engineers never learn about the technical design knowledge that they need to build the thing correctly.</p>
</blockquote>
<p>Heather’s post does a great job of articulating the problem. They understandably don’t have the answers, but suggest that firstly education gaps and secondly how companies hire are contributing factors. So changes there could be impactful.</p>
Robert Henke CBM 8032 AV at Tramway, 29-09-232023-11-04T09:28:35Zhttps://fuzzylogic.me/posts/henke-tramway/<p>Over the years I’ve seen Herr Henke (of <a href="https://www.discogs.com/artist/534-Monolake">Monolake</a> fame) doing variously-themed live shows and in a variety of locations. I loved <a href="https://roberthenke.com/concerts/cbm8032av.html">this particular show</a> and it was made even better by catching him at <a href="https://www.tramway.org/about-tramway/">The Tramway Theatre</a>, one of my favourite venues and just 10 minutes walk from home.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1699098198/298b1573-3ca0-4405-ba9a-afff00f94c89_o1paex.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1699098198/298b1573-3ca0-4405-ba9a-afff00f94c89_o1paex.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1699098198/298b1573-3ca0-4405-ba9a-afff00f94c89_o1paex.jpg" width="1300" height="732" alt="Robert Henke’s set-up for the CBM 8032 AV show" />
</picture>
<figcaption>Robert Henke’s set-up for the CBM 8032 AV show</figcaption>
</figure>
<p>Here’s a little <a href="https://roberthenke.com/concerts/cbm8032av.html">about CBM 8032 AV</a> in the great man’s own words:</p>
<blockquote>
<p>CBM 8032 AV is an exploration of the beauty of simple graphics and sound, using computers from the early 1980’s. Everything presented within the project could have been done already in the 1980, but it needed the cultural backdrop of today to come up with the artistic ideas driving it. On stage are five carefully restored Commodore CBM 8032 computers, running custom software developed by the artist and his team. Three computers create sound, one machine is responsible for the graphics and one is controlling all the others, with their green cathode ray tube displays facing the audience, operated by the artist during the show.</p>
</blockquote>
<p>I was there with Tom and Simon. Here’s a little phone recording captured by Tom.</p>
<div class="l-frame"><iframe title="Short clip of Robert Henke’ CBM 8032 AV show, live in Glasgow" width="560" height="315" src="https://www.youtube-nocookie.com/embed/CDs_LSEDHkM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<p>We left in agreement that Robert really is a genius. I’ve always loved his music and he is still doing fresh, inventive and wonderful things.</p>
<p>Additional info:</p>
<ul>
<li><a href="https://www.tramway.org/event/941c88f0-1649-4260-8f1e-afff00f70935">Tramway event page for CBM 8032 AV</a></li>
</ul>
Celtic FC podcast – John Kennedy interview2023-11-01T12:28:35Zhttps://fuzzylogic.me/posts/celtic-fc-podcast-john-kennedy-interview/<p>This is a great one-hour interview and a fantatic insight into John Kennedy’s brief but eventful career – the highs and the crushing lows.</p>
<div class="l-frame"><iframe title="Celtic FC podcast – John Kennedy interview" width="560" height="315" src="https://www.youtube-nocookie.com/embed/T4eFdi_mvj4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<p>I already liked John Kennedy but after hearing him speak so candidly and well, and getting more of an insight into his “don’t waste a minute” attitude, he’s gone even further up in my estimations.</p>
Marbella with Mum and Dad2023-11-01T09:20:00Zhttps://fuzzylogic.me/posts/marbella-with-mum-and-dad/<p>My folks haven’t managed a holiday outside of Scotland in a long time. So it’s been nice to spend a week together in Spain.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1698837341/IMG_3723_1_af9w8l.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1698837341/IMG_3723_1_af9w8l.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1698837341/IMG_3723_1_af9w8l.jpg" width="1300" height="976" alt="Laurence on holiday in Marbella with Mum and Dad" />
</picture>
<figcaption>On holiday in Marbella with Mum and Dad</figcaption>
</figure>
<p>Here we are, just about to board the No. 3 bus to Marbella’s old town.</p>
It all means nothing in the end (a talk by Amy Hupe)2023-10-02T16:34:01Zhttps://fuzzylogic.me/posts/it-all-means-nothing/<p>In this talk at State of the Browser, Amy offers some suggestions for making work feel more meaningful.</p>
<div class="l-frame"><iframe title="It all means nothing in the end (talk by Amy Hupe)" width="560" height="315" src="https://www.youtube.com/embed/Q0v2YJLq8n8?si=NYC7NO8N1kqBvkBP" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<p>Don’t treat work like an end in itself; treat it as a means to the end of fulfilling your purpose.</p>
<p>What are your key skills, experiences and values? Write them down, them summarise how these come together as your “core perspective” or <em>purpose</em>.</p>
<p>Now, we want to find ways to fulfil that purpose, and to do that we can set <em>goals</em>.</p>
<p>When considering candidate goals, ask:</p>
<ul>
<li>Does this connect to my purpose?</li>
<li>Do I actually care about achieving this goal?</li>
<li>Is this a goal I can actually achieve?</li>
<li>How will I know if I’m making progress?</li>
</ul>
Postcard from lockdown2023-09-05T20:17:15Zhttps://fuzzylogic.me/posts/postcard-from-lockdown/<p>I found this postcard from Lockdown. (Actually it’s a post-it note however that doesn’t sound as good). It provides a record of a difficult moment. I was suffering from isolation during lockdown and the only times I was getting out was to walk a reactive dog who lost his shit in a fairly upsetting way on a regular basis. Anyway I must have felt moved to empty my thoughts on paper (not someting I do too often) either for my own sanity or to help gather my thoughts to be able to confide in someone, likely Clair.</p>
<blockquote>
<p>Minimal time out of the house. Most of that’s with him. My nerves are shattered. My concentration’s broken all the time. I can feel my mental health dipping.</p>
</blockquote>
<p>Of course I’m aware that this pales in comparison to challenges people on the front-line of Covid/lockdown were dealing with. And in fact, I don’t think feeling a degree of shame at expressing mental health issues will ever leave me – I know it’s not just whining, but it can feel that way. Nonetheless, it wasn’t a fun time. Just noting it before I bin the post-it.</p>
Sicilian-style Pasta Alla Norma with aubergine (and artichoke!)2023-08-29T18:34:01Zhttps://fuzzylogic.me/posts/pasta-alla-norma/<p>This recipe from Gousto, with a few tweaks from Clair, is a straight winner. Although I’m sure it’s delicious as they list it, Clair substituted linguine for rigatoni and as a treat added some <a href="https://www.waitrose.com/ecom/products/waitrose-sliced-artichoke-hearts/017483-8480-8481">artichoke hearts</a> which took it to the next level.</p>
<p>Delicious, and a perfect example of a vegetarian meal where I didn’t miss meat at all.</p>
<p>I’ll have a go at this one myself soon. I think most people would enjoy it!</p>
Blog development decisions2023-08-28T09:14:53Zhttps://fuzzylogic.me/posts/development_decisions/<p>Here are some recurring development decisions I make when maintaining my personal website/blog, with some accompanying rationale.</p>
<h2 id="where-should-landmark-related-html-elements-be-in-the-source%3F" tabindex="-1">Where should landmark-related HTML elements be in the source? <a class="direct-link" href="https://fuzzylogic.me/posts/development_decisions/#where-should-landmark-related-html-elements-be-in-the-source%3F" aria-hidden="true">#</a></h2>
<p>I set one <code>header</code>, one <code>main</code> and one <code>footer</code> element as <em>direct children</em> of the body element.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>header</span><span class="token punctuation">></span></span>…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>header</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span>…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>footer</span><span class="token punctuation">></span></span>…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>footer</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>This isn’t arbitrary. A <code>header</code> at this level will be treated as a <code>banner</code> landmark. A <code>footer</code> is regarded as the page’s <code>contentinfo</code> landmark. Whereas when they are nested more deeply such as within a “wrapper” div they are not automatically given landmark status. You’d have to bolt-on ARIA attributes. My understanding is that it’s better to use elements with implicit semantics than to bolt on semantics manually.</p>
<h2 id="how-should-i-centre-the-main-content-in-a-way-that%E2%80%99s-responsive-and-supports-full-width-backgrounds%3F" tabindex="-1">How should I centre the main content in a way that’s responsive and supports full-width backgrounds? <a class="direct-link" href="https://fuzzylogic.me/posts/development_decisions/#how-should-i-centre-the-main-content-in-a-way-that%E2%80%99s-responsive-and-supports-full-width-backgrounds%3F" aria-hidden="true">#</a></h2>
<p>My hard-learned approach is to use composition rather than try to do everything with “god” layouts.</p>
<p>I mentally break the page up from top to bottom into slices that correspond to logical groups of content and/or parts that need a dedicated full-width background. I give each slice <code>padding</code> on all sides. The lateral padding handily gives you the gutters you need on narrow screens. (You <em>could</em> use a <a href="https://every-layout.dev/layouts/box/">Box</a> layout for these sections. I tend not to consider them to be “true boxes” because usually their lateral padding differs from their vertical padding. So I just apply their styles on a case by case basis.)</p>
<p>Within each section, nest a dedicated <a href="https://every-layout.dev/layouts/center/">Center</a> layout to handle your fluid width-constraining wrappers.</p>
<p>This approach offers the best of all worlds. It doesn’t constrain your markup, which I find useful for achieving appropriate semantics and accessibility. You don’t need to put a “wrapper div” around everything. Instead you can have landmark-related elements as direct children of <code>body</code>, applying padding to those and nesting centred wrappers inside them.</p>
<p>By making proper use of <code>padding</code>, this approach also avoids problems of “collapsing margins” and other margin weirdness that make life difficult when you have sections with background colours. You don’t want to be using vertical margins in situations where “boxes with padding” would be more appropriate. Relatedly, I find that flow (or <a href="https://every-layout.dev/layouts/stack/">stack</a>) layouts generally work best <em>within</em> each of your nested wrappers rather than at the top level.</p>
<h2 id="how-should-i-mark-up-lists-of-articles%3F" tabindex="-1">How should I mark up lists of articles? <a class="direct-link" href="https://fuzzylogic.me/posts/development_decisions/#how-should-i-mark-up-lists-of-articles%3F" aria-hidden="true">#</a></h2>
<p>Should they be a bunch of sibling <code>article</code>s? Should they be in a list element like a <code>ul</code>?</p>
<p>Different switched-on developers tackle this differently, so it’s hard to offer a definitive best approach. Some developers even do it differently across different pages on their own site! Here are some examples in the wild:</p>
<ul>
<li><a href="https://tink.uk/">Leonie Watson’s homepage</a> employs a list of <code>article</code> elements with no wrapping list</li>
<li><a href="https://www.matuzo.at/">Manuel Matuzovic’s homepage</a> does the same as Léonie’s</li>
<li><a href="https://adrianroselli.com/posts">Adrian Roselli’s posts page</a> uses the same structure as above whereas <a href="https://adrianroselli.com/">Adrian’s homepage</a> uses a <code>ul</code> with no <code>article</code> elements!</li>
<li><a href="https://tetralogical.com/blog/">Tetralogical’s blog section</a> employs sibling <code>section</code> elements whereas <a href="https://tetralogical.com/news/">their news section</a> uses an <code>ol</code> but with nothing special nested inside</li>
<li><a href="https://ethanmarcotte.com/wrote/">Ethan Marcotte’s journal</a> uses nested lists to group by years then months, with each teaser marked up as an <code>article</code> inside an <code>li</code></li>
</ul>
<p>So, clear as mud!</p>
<p>I currently use sibling <code>article</code>s with no wrapping list. Using <code>article</code> elements feel right because each (per <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article">MDN’s definition of article</a>) “represents a self-contained composition… intended to be independently distributable or reusable (e.g., in syndication)”. I could be persuaded to wrap these in a list because that would announce to screen reader users upfront that it’s a list of articles and say how many there are. (It tends to make your CSS a tad gnarlier but that’s not the end of the world.)</p>
<h2 id="should-a-blog-post-page-be-marked-up-as-an-article-or-just-using-main%3F" tabindex="-1">Should a blog post page be marked up as an article or just using main? <a class="direct-link" href="https://fuzzylogic.me/posts/development_decisions/#should-a-blog-post-page-be-marked-up-as-an-article-or-just-using-main%3F" aria-hidden="true">#</a></h2>
<p>I mark it up as an <code>article</code> for the same reasons as above. That article is nested inside a <code>main</code> because all of my pages have one <code>main</code> element wrapping around the primary, non-repeated content of the page.</p>
<h2 id="to-be-continued" tabindex="-1">To be continued <a class="direct-link" href="https://fuzzylogic.me/posts/development_decisions/#to-be-continued" aria-hidden="true">#</a></h2>
<p>I’ll add more to this article over time.</p>
Chris Packham interview in The Guardian2023-08-25T06:31:44Zhttps://fuzzylogic.me/posts/2023-08-25-chris-packham-interview-in-the-guardian/<p>The naturalist, TV campaigner and activist on growing up, autism and asking himself “what is the best use of me?”.</p>
<blockquote>
<p>He’s such a brilliant, sensitive soul, but it must be hard work being Chris Packham.</p>
</blockquote>
<p>Growing up I was never a fan of nature programmes like <em>The Really Wild Show</em> so I didn’t pay Chris Packham too much attention. However in the last few years I've grown really fond of him. That's in part due to his revelations about his punky musical leanings and attitude, but more so due to his candid description of his autism, then his work to bring the true nature of autism and neruodivergency into the public eye and in doing so help others.</p>
<p>He’s also quite inspirational in trying to do the right thing in many ways, despite significant challenges.</p>
<p>This was an enjoyable and insightful interview although some of the parts about his losing beloved animals alongside other dark moments make for tough reading. Still though, I'm now considering reading <a href="https://uk.bookshop.org/p/books/fingers-in-the-sparkle-jar-a-memoir-chris-packham/3973406?ean=9781785033506">Fingers in the sparkle jar</a>.</p>
3 questions to evaluate design patterns and avoid unnecessary work that degrades UX (by Adam Silver)2023-08-24T08:46:01Zhttps://fuzzylogic.me/posts/2023-08-24-3-questions-to-evaluate-design-patterns-and-avoid-unnecessary-work-that-degrades-ux-adam-silver-designer-london-uk/<p>Adam offers tips for how to proceed when we are presented with a request for a shiny new pattern which is not grounded in research but rather follows a fad.</p>
<blockquote>
<p>The purpose of design is to solve actual problems. Not made up “I’m bored so I’ll come up with something new” problems.</p>
</blockquote>
<blockquote>
<p>So how can we evaluate these patterns, avoid unnecessary work and ultimately avoid patterns that degrade UX?</p>
</blockquote>
<p>He recommends we should start by asking three questions:</p>
<ol>
<li>Does research show this pattern solves a problem?</li>
<li>Are there any potential usability issues with this pattern?</li>
<li>How much effort is it to build?</li>
</ol>
Just normal web things.2023-08-23T21:31:57Zhttps://fuzzylogic.me/posts/2023-08-23-just-normal-web-things/<p>Heather suggests that in developers’ excitement to do cool new stuff and use cool new tools and techniques “we stopped letting people do very normal web things”. Things like:</p>
<ul>
<li>the ability to copy text so you can then paste it</li>
<li>ensuring elements which navigate also behave like normal links by offering standard right-click and keyboard shortcut options etc. Which is to say – please use the anchor element and leave it alone to do its thing</li>
<li>letting people go back using the back button</li>
<li>letting people scroll with native scrollbars. Relatedly, letting people get to the links at the bottom of the page rather than having infinite scrolling results which mean that the footer is always just beyond reach!</li>
<li>letting the user’s browser autocomplete form fields rather than making them type it</li>
</ul>
A blog post which uses every HTML element (by Patrick Weaver)2023-08-23T16:35:17Zhttps://fuzzylogic.me/posts/2023-08-23-a-blog-post-which-uses-every-html-element-by-patrick-weaver/<p>An interesting article which helps the author – and his readers – understand some of the lesser-used and more obscure HTML elements.</p>
<p>While Patrick confesses he is still learning certain things and therefore I won’t regard his implementations as <em>gospel</em> in the way I might an article by someone with greater HTML and accessibility expertise such as Adrian Roselli, I see this as another useful resource to help me when deciding whether or not an HTML choice is the semantic and or correct tool for a given situation.</p>
<p>Thanks, Patrick!</p>
Shoelace: a forward-thinking library of web components2023-08-23T16:12:39Zhttps://fuzzylogic.me/posts/2023-08-23-shoelace-a-forwardthinking-library-of-web-components/<p>I’m interested by Shoelace’s MO as a collection of pre-rolled, customisable web components. The idea is that it lets individuals and teams start building with web components – components that are web-native, framework-agnostic and portable – way more quickly.</p>
<p>I guess it’s a kind of Bootstrap for web components? I’m interested to see how well it’s done, how customisable the components are, and how useful it is in real life. Or if nothing else, I’m interested to see how they built their components!</p>
<p>It’s definitely an interesting idea.</p>
<p>I'll delve into Shoelace in more detail in the future when I have time, but in the meantime I was able to very quickly knock together <a href="https://codepen.io/fuzzylogicx/pen/rNoVJrQ">a codepen that renders a <em>Dropdown</em> instance</a>.</p>
<p>Thanks to Chris Ferdinandi for <a href="https://gomakethings.com/shoelace/">sharing Shoelace</a>.</p>
Progress over perfection: a better way to accessibility (meryl.net)2023-08-23T15:27:25Zhttps://fuzzylogic.me/posts/2023-08-23-progress-over-perfection-a-better-way-to-accessibility-merylnet/<p>This post from earlier this year offers a similar encouraging message to Henny Swan’s recent <a href="https://fuzzylogic.me/posts/the-only-accessibility-practitioner-in-the-room/"><em>The only accessibility specialist in the room</em></a>. It contains advice that’s worth remembering when we have one of those ”what’s the point?’ moments!</p>
<p>Advice like:</p>
<ul>
<li>Get started; don't wait until everything is done and perfect</li>
<li>Small steps make a big difference</li>
<li>Educate, don't berate</li>
<li>Think of accessibility as an ongoing journey with no finish line</li>
</ul>
Component specifications, by Nathan Curtis2023-08-20T09:27:01Zhttps://fuzzylogic.me/posts/component-specifications/<p>Nathan on how complex components require comprehensive specifications rather than ill-advised assumptions, and how Figma can be used to guide engineers to reliably build such components.</p>
<blockquote>
<p>I’m still amazed when designers schlep together a few pictures, publish a configurable Figma component, point their developer counterparts at the main component and say “Use Figma’s inspect tool.”</p>
</blockquote>
<blockquote>
<p>Things have changed. Components are more complicated. Designers are delivering to many different developers. Accessibility has risen to the fore. For design systems that scale, teams are finding it necessary to write down all the details again.</p>
</blockquote>
<p>At work in our project to improve our component documentation across the component life-cycle, we’ve been following Nathan’s advice and using his plug-in to assist with the “specification” aspect.</p>
Ben Lomond, bagged2023-08-14T14:17:15Zhttps://fuzzylogic.me/posts/ben-lomond/<p>Had a great day with Mark and Alan on Saturday climbing <a href="https://www.walkhighlands.co.uk/lochlomond/ben-lomond.shtml">Ben Lomond</a>. Although I’m not much of a hill-walker I reckon that’s the third <a href="https://www.visitscotland.com/things-to-do/outdoor-activities/walking/mountains-hills/munro-bagging">Munro I have bagged</a>.</p>
<p>We were staying overnight at our friend Jim’s family cabin at Rowardennan and it was a short walk from there to the mountain. The start is steep and the weather progressively worsened until the rain was horizontal, but nonetheless we reached the summit (3200 feet above sea level) in around two hours then skipped back down in just one more hour. We were pretty proud of ourselves to complete the walk in just over three hours!</p>
<p>After that we enjoyed steak pie, fish and chips and victory pints at the Rowardennan hotel. A perfect day.</p>
<p>Mind you, over the last couple of days I’ve been feeling pain in muscles I didn’t know existed!</p>
Lately… (08-04-2023)2023-08-04T21:45:53Zhttps://fuzzylogic.me/posts/recent-stuff-080423/<p>I’ve been:</p>
<ul>
<li>reading <a href="https://blackwells.co.uk/bookshop/product/9781788705776">The Islander</a> by Chris Blackwell and Paul Morley</li>
<li>watching <a href="https://www.imdb.com/title/tt15398776/">Oppenheimer</a> on the big screen and <a href="https://www.imdb.com/title/tt14452776/">The Bear</a> on TV</li>
<li>listening to <a href="https://www.discogs.com/release/26602412-A-Certain-Ratio-1982">1982</a> by A Certain Ratio and Matt Wilde’s <a href="https://fuzzylogic.me/posts/matt-wilde-hello-world/">Hello World</a></li>
<li>out to see <a href="https://www.tron.co.uk/shows/moorcroft-2/">Moorcroft</a> at the Tron and thinking about it ever since</li>
<li>enjoying collaborating and socialising with teammates in the office but not loving the commute</li>
<li>at one wedding (Lou and Tom) and one funeral (Aunt Elsie)</li>
<li>losing sleep while Rudy goes through a night-whines phase</li>
<li>starting to re-find some form at table tennis training</li>
<li>wanting to write regular posts like this – this is the test run!</li>
</ul>
Specs and standards2023-08-04T09:09:24Zhttps://fuzzylogic.me/posts/specs-and-standards/<p>Something Adrian Roselli said recently has stuck with me. The gist was that when developers need definitive guidance they shouldn’t treat MDN as gospel, but rather refer to the proper specifications for web standards.</p>
<p>Note: this post is a work in progress. I’ll refine it over time.</p>
<h2 id="html" tabindex="-1">HTML <a class="direct-link" href="https://fuzzylogic.me/posts/specs-and-standards/#html" aria-hidden="true">#</a></h2>
<p><a href="https://html.spec.whatwg.org/multipage/">The HTML Living Standard</a></p>
<p>The <a href="https://html.spec.whatwg.org/dev/"><em>Edition for Web Developers</em></a> version looks handy. It seems to be streamlined and you can also use the forward-slash key to jump straight into a search then type something like “popover” to access that specification quickly.</p>
<h2 id="wcag-accessibility" tabindex="-1">WCAG Accessibility <a class="direct-link" href="https://fuzzylogic.me/posts/specs-and-standards/#wcag-accessibility" aria-hidden="true">#</a></h2>
<p><a href="https://www.w3.org/WAI/WCAG21/quickref/#info-and-relationships">How to Meet WCAG (Quick Reference)</a></p>
<p>Adrian referenced the above in one of his blog articles.</p>
<h2 id="aria" tabindex="-1">ARIA <a class="direct-link" href="https://fuzzylogic.me/posts/specs-and-standards/#aria" aria-hidden="true">#</a></h2>
<p><a href="https://www.w3.org/TR/html-aria/">W3C’s ARIA in HTML document</a></p>
<p>Adrian will quote or reference this when talking about roles, landmarks and the like… for example when <a href="https://twitter.com/aardrian/status/1587524667325177864">he tweeted about developers using <code>section</code></a>.</p>
<p>Note: the above resource somewhat confusingly describes itself as a W3C <em>recommendation</em>. But despite that naming it should be regarded as definitive guidance. That description links to an explainer of W3C recommendation confirming that these are specifications which have been endorsed by W3C, that software manufacturers should implement, and that may be cited as W3C standards. My understanding is that if a specification is at an earlier stage it will be described as a W3C proposed recommendation.</p>
<h2 id="miscellaneous-notes" tabindex="-1">Miscellaneous notes <a class="direct-link" href="https://fuzzylogic.me/posts/specs-and-standards/#miscellaneous-notes" aria-hidden="true">#</a></h2>
<p>How useful is MDN? I’ve read before that it’s not definitive. But it has recently had some <a href="https://adrianroselli.com/2018/09/hack-on-mdn.html">good people work to improve its references to accessibility</a></p>
<blockquote>
<p>MDN typically references WHATWG HTML, which often gets accessibility… well, not quite right. Part of my efforts included updating the accessibility content to point to the W3C specs wherever appropriate.</p>
</blockquote>
Blockquotes in screen readers, by Adrian Roselli2023-07-29T12:50:01Zhttps://fuzzylogic.me/posts/blockquotes-in-screen-readers/<p>Adrian tests how blockquotes, marked up in a variety of ways, are announced in different screen readers.</p>
<p>He concludes that his personal choice is as follows:</p>
<pre><code><main>
<!-- other content -->
<blockquote>
<p>A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.</p>
<footer>— <cite>Douglas Adams, <a href="https://en.wikipedia.org/wiki/Mostly_Harmless">Mostly Harmless</a></cite></footer>
</blockquote>
<!-- other content -->
</main>
</code></pre>
<hr />
<p>He avoids the <code>cite</code> <em>attribute</em> completely because it creates noise in JAWS, and recommends against using <code>figure</code> with <code>figcaption</code> because it results in unnecessarily verbose and duplicate announcements.</p>
<p>In his chosen approach the <code>footer</code> is used mainly as a sensible styling hook, since in the context of a <code>main</code> (as opposed to as a direct child of <code>body</code>) it is not regarded a landmark and is strictly presentational. The <code>cite</code> element has semantic intent – it’s <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite">the element for marking up the title of a cited creative work</a> – even if those semantics are not always exposed to users.</p>
<p>So there’s an action for my team at work, because our blockquote component currently uses <code>figure</code> and <code>figcaption</code>. Perhaps at the time of build we took advice from one of the MDN or W3C pages which Adrian has now shown weren’t ideal.</p>
Use z-index only when necessary2023-07-24T13:17:15Zhttps://fuzzylogic.me/posts/you-dont-always-need-z-index/<p>There’s a great section on <a href="https://every-layout.dev/layouts/imposter/">Source order and layers</a> in Every Layout’s <em>Imposter</em> layout. It’s a reminder that when needing to layer one element on top of the other you should:</p>
<ol>
<li>favour a modern layout approach such as CSS Grid over absolute positioning; and</li>
<li>not apply <code>z-index</code> unless it’s necessary.</li>
</ol>
<blockquote>
<p>which elements appear over which is, by default, a question of source order. That is: if two elements share the same space, the one that appears above the other will be the one that comes last in the source.</p>
</blockquote>
<blockquote>
<p><code>z-index</code> is only necessary where you want to layer positioned elements irrespective of their source order. It’s another kind of override, and should be avoided wherever possible.</p>
</blockquote>
<blockquote>
<p>An arms race of escalating z-index values is often cited as one of those irritating but necessary things you have to deal with using CSS. I rarely have z-index problems, because I rarely use positioning, and I’m mindful of source order when I do.</p>
</blockquote>
To delete something, use a form rather than a link2023-07-23T16:34:01Zhttps://fuzzylogic.me/posts/to-delete-something-use-a-form-rather-than-a-link/<p>In web-based products from e-commerce stores to email clients to accounting software you often find index pages where each item in a list (or row in a table) has a <em>Delete</em> option. This is often coded as a link… but it shouldn’t be.</p>
<p>I liked this comment by Rails developer Dan where he advises a fellow Rails developer that to create his Delete control he should use a form rather than a link, via Rails’s <code>button_to</code> method.</p>
<p>Dan mentions that in the past Rails UJS set an unsdesirable historical precedent by including a pattern of hijacking links for non-GET reqests.</p>
<p><a href="https://html.spec.whatwg.org/dev/links.html#:~:text=Hyperlinks,a%20browser%20or%20download%20them.">But per the HTML standard, links are for navigation:</a></p>
<blockquote>
<p>Hyperlinks… are links to other resources that… cause the user agent to navigate to those resources, e.g. to visit them in a browser or download them.</p>
</blockquote>
<p>And <a href="https://discuss.hotwired.dev/t/destroy-record-in-turbo-frame/2731/8">as Dan goes on to say</a> that’s why links make a GET request.</p>
<blockquote>
<p>A GET request is a visit, it says “show me this” and it’s idempotent. When you make the same request it’ll show the same thing.</p>
</blockquote>
<p>If on the other hand you want a control that performs an action (in this case request an entity to be deleted) then the appropriate HTML element is usually a button, and in this case a submit button within a form.</p>
<p>Relatedly, Jeremy Keith previously wrote about how to use request methods properly in his excellent post <a href="https://adactio.com/journal/17768">Get safe</a>.</p>
Matt Wilde’s debut LP, Hello World2023-07-16T05:48:00Zhttps://fuzzylogic.me/posts/matt-wilde-hello-world/<p>Love <a href="https://www.mattwilde.com/">Matt Wilde’s</a> music and his new LP <em>Hello World</em> is even better than expected. Beautiful laid-back and understated vibe from start to finish. Lovely artwork too.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1689517837/IMG_3578_bohtyr.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1689517837/IMG_3578_bohtyr.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1689517837/IMG_3578_bohtyr.jpg" width="1400" height="1050" alt="My copy of Matt Wilde’s new LP 'Hello World' plus the 'Band on the Wall' tote bag sent by the label" />
</picture>
<figcaption>Lovely LP (music and art) with bonus BOTW tote bag</figcaption>
</figure>
<p>Cheers also to <a href="https://twitter.com/botwrecs">Band on the Wall recordings</a> for the surprise tote bag!</p>
A well known URL for your personal avatar (by Jim Neilsen)2023-07-15T17:11:01Zhttps://fuzzylogic.me/posts/well-known-avatar/<p>I really like Jim’s idea of putting an avatar file somewhere that’s memorable and easy to access by me wherever I am and that also (in the future) might be automatically grabbable by any platform that needs my avatar.</p>
<p>So I’ve put my avatar at <a href="https://fuzzylogic.me/.well-known/avatar">fuzzylogic.me/.well-known/avatar</a>.</p>
<p>Great idea, Jim!</p>
The fear of keeping up (on gomakethings)2023-07-14T19:27:01Zhttps://fuzzylogic.me/posts/the-fear-of-keeping-up/<p>Great post by Chris here on the double-edged-sword of our rapidly-evolving web standards, and how to stay sane. On the one hand the latest additions to the HTML, CSS and JavaScript standards are removing the need for many custom tools which is positive. However:</p>
<blockquote>
<p>it can also leave you feeling like it’s impossible to keep up or learn it all. And that’s because you can’t! The field is literally too big to learn everything. “Keeping up” is both impossible and overrated. It’s the path to burnout.</p>
</blockquote>
<p>Chris’s suggestion – something I find reassuring and will return to in moments of doubt – is that we focus on:</p>
<ul>
<li>a good understanding of the fundamentals,</li>
<li>staying aware of general trends in the industry (such as important forthcoming native HTML elements; and the different approaches to building a website etc),</li>
<li>problem-solving: being good at “solving problems with tech” rather than just knowing a bunch of tools.</li>
</ul>
Making coffee with the Sage Barista Touch2023-07-14T09:14:53Zhttps://fuzzylogic.me/posts/making-coffee-with-sage-barista-touch/<p>Clair recently brought her fancy coffee machine home from work. It’s a Sage Barista Touch. Since then, I’ve been learning what’s involved in making a coffee by grinding fresh from whole beans, barista-style!</p>
<p>It’s more complicated than I would have thought, and has involved lots of learning and trial and error.</p>
<p>Here are my go-to resources and my rules-of-thumb. I’m not saying they’re perfect, but they’re working for me! Any additional tips from people more in the know are, of course, very welcome.</p>
<h2 id="dialling-in%3A-my-rule-of-thumb" tabindex="-1">Dialling in: my rule of thumb <a class="direct-link" href="https://fuzzylogic.me/posts/making-coffee-with-sage-barista-touch/#dialling-in%3A-my-rule-of-thumb" aria-hidden="true">#</a></h2>
<p>Overall I want:</p>
<ul>
<li>a good taste, as a result of</li>
<li>a grind of 18-19g, and</li>
<li>a pull where liquid flows from 7 seconds or more, and</li>
<li>a conventional yield such as a 2oz double-espresso.</li>
</ul>
<p>Once you’ve achieved the above from a process of trial and error, dial in the settings (grind, dose) and log any additional notes so that you can easily repeat the same process achieving the same results.</p>
<h2 id="how-it-works-in-practice" tabindex="-1">How it works in practice <a class="direct-link" href="https://fuzzylogic.me/posts/making-coffee-with-sage-barista-touch/#how-it-works-in-practice" aria-hidden="true">#</a></h2>
<p>If I buy a new bag of coffee beans for a coffee I’m trying for the first time, here’s how I’d set about dialling in.</p>
<p>Note: before you start, you want your coffee’s roast date to be no more than 3 weeks ago and you’ll need coffee scales and one or two espresso shot glasses with measuring lines.</p>
<p>Fill up the tank with fresh water. Use the hot water feature to pour out some hot water into your mug to warm everything up.</p>
<p>Start with a grind size of 12 and a grind time of 20 seconds (they’re sensible middling starting points).</p>
<p>Place your portafilter with funnel attached on your scales (turned off) then turn on the scales so that they’re zeroed appropriately.</p>
<p>Remove the portafilter and grind out coffee based on the previously set grind time. Use the scales to check how much you’ve ground. Remove some, or grind and add more, til you have 18g. Jot down how much time it takes to grind 18g.</p>
<p>Settle, level (roughly) and tamp the coffee in the basket.</p>
<p>Remove the funnel then screw the portafilter in so that it’s ready to brew.</p>
<p>Place your espresso measuring mug under the portafilter, ready to receive brewed coffee.</p>
<p>Start brewing and note the point when liquid starts flowing. If it starts flowing before seven seconds, set the grind size finer. Get this aspect locked down first.</p>
<p>Once we’ve achieved a good begin-flow point and a steady flow, I want to identify the number of seconds it takes to achieve my target yield – meaning the time at which the crema hits the <em>2oz double espresso</em> line.</p>
<p>Once you’ve hit your yield, and so long as the time was between 25-35 seconds, taste it. If you like it you could dial in that brew time and stop there. If it’s at say 28+ seconds (indicating that the water’s taking a long time to make its way though the coffee) I might also try increasing the grind size by one (larger grind = less dense = water gets through faster) and seeing if I can achieve the target yield within a few less seconds.</p>
<p>Another little tweak I sometimes make to achieve the balance of begin-flow-time, steady flow and yield is to slightly increase or reduce the amount of coffee. For example adding a few milligrams (a dose of 18.5g versus 18g) might start the flow just a little later, when that’s what you need.</p>
<p>If you tried different settings, compare the taste in separate shot glasses. Go with the one you like! Dial in (save/overwrite) your grind size, grind time and brew time. I’ve noticed that the grind size can move a bit of its own accord between uses, so noting the settings for this coffee down somewhere is a good idea too.</p>
<p>Now that you have a good shot of espresso, you could make (for example) a flat white… or add water and a drop of milk for an americano… or just have the espresso itself if you’re feeling Italian.</p>
<h2 id="resources" tabindex="-1">Resources <a class="direct-link" href="https://fuzzylogic.me/posts/making-coffee-with-sage-barista-touch/#resources" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://assets.sageappliances.com/BES880/SES880_UK_IB_B18_WEB.pdf">Sage Barista Touch intruction manual</a></li>
<li><a href="https://youtu.be/rnrvcU6OUDM?si=3LKGmBDODbR73sSB">Dialling in tutorial for the Sage Barista Touch</a> by American barista Matt Davis</li>
<li><a href="https://www.youtube.com/watch?v=60RQmVvDFr4">Dave Wells’s instructional video</a></li>
<li><a href="https://www.youtube.com/playlist?list=PLRSnFecax3hF0lck1JIwiCCvCT8zJNRhW">Breville’s video tutorial playlist</a></li>
</ul>
Lighter meditteranean veg lasagne recipe, by Gousto2023-07-11T16:34:01Zhttps://fuzzylogic.me/posts/gousto-veg-lasagne/<p>This lasagne was meat-free, fun to cook, easy on the eye and tasted great.</p>
I’ve just read Join the Future, by Matt Anniss2023-07-09T09:20:00Zhttps://fuzzylogic.me/posts/join-the-future/<blockquote>
<p>It’s important to set the record straight. Normally when people talk about the early UK scene the same few things get mentioned. The real underground never gets talked about."</p>
</blockquote>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1689329837/join_the_future_resized_1733x1300_itczyh.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1689329837/join_the_future_resized_1733x1300_itczyh.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_55,w_1292/v1689329837/join_the_future_resized_1733x1300_itczyh.jpg" width="1733" height="1300" alt="Matt Anniss’s book 'Join the Future'" />
</picture>
<figcaption>My copy of Join the Future</figcaption>
</figure>
<p>I loved this! It tells the stories behind many of the lesser-reported UK scenes and record labels. And it really helped to join a lot of musical dots for me, covering music I first heard on cassettes as a teenager thirty years ago. (That includes fairly obscure labels such as <a href="https://www.discogs.com/label/3894-Chill">Chill</a> – that brilliant quote about “setting the record straight” was from their A+R man Tim Raidl).</p>
<p>I also loved Matt’s passion for telling the stories of these people and communities.</p>
<p>Highly recommended.</p>
Banksy’s Cut and Run exhibition2023-07-06T22:17:15Zhttps://fuzzylogic.me/posts/banksy-at-goma/<p>Clair and I, along with our pal Fiona, just went to see <a href="https://cutandrun.co.uk/">Banksy’s Cut and run exhibition</a> at the GOMA in Glasgow. I loved it!</p>
<p><a href="https://cutandrun.co.uk/">Banksy describes it</a> as follows:</p>
<blockquote>
<p>I’ve kept these stencils hidden away for years, mindful they could be used as evidence in a charge of criminal damage. But that moment seems to have passed, so now I’m exhibiting them in a gallery as works of art. I’m not sure which is the greater crime.</p>
</blockquote>
<p>He mentions that one of the main reasons he chose Glasgow’s GOMA is because the ever-present cone on the head of the Duke of Wellington statue outside is his favourite work of art in the UK.</p>
<blockquote>
<p>…the statue out the front has had a cone on its head continuously for the past 40 odd years. Despite the best efforts of the council and the police, every time one is removed another takes its place."</p>
</blockquote>
<p>I really enjoyed the way the exhibition was arranged and presented with the various use of corridors, rooms, concourses and other objects such as elevators and phone booths.</p>
<p>I liked Banky self-effacing introduction saying that really he was cheating and gets (steals) all his inspiration from others, or <em>real</em> artists.</p>
<p>I loved where he talked about the light-switch moment about not needing to add a background but rather to make the real-life location the background, and how that then fires the imagination with the challenge “How much of the environment can you integrate into the piece?”. How much space could there be between the girl and the balloon?</p>
<p>Lastly, the final area is a treat. It simulates Banksy’s bedroom growing up and the music, art and films which influenced him. There’s a great description of how the graffitied sign in Jaws – where a sign presenting Amity Island as a paradise is doctored with a shark fin and “Help!” speech bubble – was an early example of art that really spoke to him. In this graffiti he saw a wonderful combination of satire, powerless people finding a way to make their voice heard, humour, art and rebellion.</p>
How I use github.com as my JAMstack CMS2023-07-03T17:20:01Zhttps://fuzzylogic.me/posts/how-i-use-github-as-jamstack-cms/<p>Here are my quick links and tips for creating a markdown-file-based blog post using only <a href="http://github.com/">github.com</a> and no CMS. I’ve put these on this site so that they’re on the web therefore I can access them wherever I am.</p>
<p>Why do I create posts this way? Because I’ve tried <a href="http://forestry.io/">forestry.io</a> (now <em>Tina</em>) and Netlify CMS and I no longer have the time or inclination to maintain their dependencies, load their JavaScript or make ongoing updates as they evolve. I’ve also found them a little flaky. So instead let’s see how this lo-fi approach works.</p>
<p>This post is mainly for my own reference but who knows, maybe it’ll be useful to someone else too.</p>
<p>Step 1:</p>
<p><a href="https://github.com/fuzzylogicxx/fuzzylogic/new/v3/posts">Create a new markdown file in my posts directory</a></p>
<p>Step 2: use one of these previous posts as a template (use the “copy raw file” icon-button then paste into my new markdown file):</p>
<ul>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/basic_entry.md">Standard blog entry</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/template-post-bookmark.md">Bookmark</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/captain-fantastic.md">Short note</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/join-the-future.md">Note with photo</a></li>
<li><a href="https://fuzzylogic.me/posts/i-ve-started-reading-the-15-minute-city-by-natalie-whittle/">Book I’ve started reading</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/captain-fantastic.md">Film I just watched</a></li>
<li><a href="https://fuzzylogic.me/posts/plant43-%E2%80%93-light-pollution/">(Video of) record I bought/love</a></li>
<li><a href="https://fuzzylogic.me/posts/fuzzy-logic-laurence-hughes-march-23-clyde-built-radio/">Mix I’ve just recorded</a></li>
</ul>
<h2 id="useful-references" tabindex="-1">Useful references <a class="direct-link" href="https://fuzzylogic.me/posts/how-i-use-github-as-jamstack-cms/#useful-references" aria-hidden="true">#</a></h2>
<hr />
<p>date: 2023-07-03T17:20:01Z<br />
title: How I use <a href="http://github.com/">github.com</a> as my JAMstack CMS<br />
description: Quick links and tips to create a blog post using <a href="http://github.com/">github.com</a><br />
tags:</p>
<ul>
<li>entry</li>
<li>howto<br />
noteWithTitle: false<br />
linkTarget: ''<br />
mainImage.url: ''<br />
mainImage.alt: ''<br />
mainImage.aspectRatioWidth: ''<br />
mainImage.aspectRatioHeight: ''<br />
mainImage.srcsetWidths: ''<br />
mainImage.sizes: ''<br />
mainImage.isAnchor: false</li>
</ul>
<hr />
<p>Here are my quick links and tips for creating a markdown-file-based blog post using only <a href="http://github.com/">github.com</a> and no CMS. I’ve put these on this site so that they’re on the web therefore I can access them wherever I am.</p>
<p>Why do I create posts this way? Because I’ve tried <a href="http://forestry.io/">forestry.io</a> (now <em>Tina</em>) and Netlify CMS and I no longer have the time or inclination to maintain their dependencies, load their JavaScript or make ongoing updates as they evolve. I’ve also found them a little flaky. So instead let’s see how this lo-fi approach works.</p>
<h2 id="this-post-is-mainly-for-my-own-reference-but-who-knows%2C-maybe-it%E2%80%99ll-be-useful-to-someone-else-too." tabindex="-1">This post is mainly for my own reference but who knows, maybe it’ll be useful to someone else too. <a class="direct-link" href="https://fuzzylogic.me/posts/how-i-use-github-as-jamstack-cms/#this-post-is-mainly-for-my-own-reference-but-who-knows%2C-maybe-it%E2%80%99ll-be-useful-to-someone-else-too." aria-hidden="true">#</a></h2>
<p>Step 1:</p>
<p><a href="https://github.com/fuzzylogicxx/fuzzylogic/new/v3/posts">Create a new markdown file in my posts directory</a></p>
<p>Step 2: use one of these previous posts as a template (use the “copy raw file” icon-button then paste into my new markdown file):</p>
<ul>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/basic_entry.md">Standard blog entry</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/template-post-bookmark.md">Bookmark</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/captain-fantastic.md">Short note</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/join-the-future.md">Note with photo</a></li>
<li><a href="https://fuzzylogic.me/posts/i-ve-started-reading-the-15-minute-city-by-natalie-whittle/">Book I’ve started reading</a></li>
<li><a href="https://github.com/fuzzylogicxx/fuzzylogic/blob/v3/posts/captain-fantastic.md">Film I just watched</a></li>
<li><a href="https://fuzzylogic.me/posts/plant43-%E2%80%93-light-pollution/">(Video of) record I bought/love</a></li>
<li><a href="https://fuzzylogic.me/posts/fuzzy-logic-laurence-hughes-march-23-clyde-built-radio/">Mix I’ve just recorded</a></li>
</ul>
<h2 id="useful-references-1" tabindex="-1">Useful references <a class="direct-link" href="https://fuzzylogic.me/posts/how-i-use-github-as-jamstack-cms/#useful-references-1" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://fusionauth.io/dev-tools/date-time#convert-from-strings">grab current datetime in right format</a> (see the <em>Date/time</em> field under <em>Convert from strings</em>)</li>
<li><a href="https://fuzzylogic.me/tags/">All of my tags</a></li>
<li><a href="https://fuzzylogic.me/posts/my-new-syntax-for-responsive-and-modern-blog-images/">Images: how I optimise, host, and code for performance and responsiveness</a></li>
<li><a href="https://www.11ty.dev/docs/dates/">Set frontmatter date to <code>Created</code></a></li>
</ul>
<h2 id="other-notes" tabindex="-1">Other notes <a class="direct-link" href="https://fuzzylogic.me/posts/how-i-use-github-as-jamstack-cms/#other-notes" aria-hidden="true">#</a></h2>
<p>Reminder to self: create a bookmark for this post on all my devices. Name it “Nu Gh post”. (see the <em>Date/time</em> field under <em>Convert from strings</em>)</p>
<ul>
<li><a href="https://fuzzylogic.me/tags/">All of my tags</a></li>
<li><a href="https://fuzzylogic.me/posts/my-new-syntax-for-responsive-and-modern-blog-images/">Images: how I optimise, host, and code for performance and responsiveness</a></li>
<li><a href="https://www.11ty.dev/docs/dates/">Set frontmatter date to <code>Created</code></a></li>
</ul>
<h2 id="other-notes-1" tabindex="-1">Other notes <a class="direct-link" href="https://fuzzylogic.me/posts/how-i-use-github-as-jamstack-cms/#other-notes-1" aria-hidden="true">#</a></h2>
<p>Reminder to self: create a bookmark for this post on all my devices. Name it “Nu Gh post”.</p>
Secrets To Block Like a Pro Tutorial A-Z2023-07-02T17:20:01Zhttps://fuzzylogic.me/posts/secrets-to-block-like-a-pro-pech-pong/<p>In this tutorial video Seth Pech shares what he’s learned about that most foundational (and important) of table-tennis shots – the block.</p>
<div class="l-frame">
<iframe title="Pech Pong’s secrets to block like a pro tutorial" width="560" height="315" src="https://www.youtube.com/embed/J0tdMgyyCpE" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
</div>
<p>Fundamentals:</p>
<ol>
<li>keep the racket in front rather than blocking on the side of your body. You can see it better and transition faster</li>
<li>for the basic block just use the opponent’s energy – don’t add anything</li>
<li>for backhand, block in your normal backhand posture (rather than a lollipop, or poking) to aid transitioning to attack</li>
<li>don’t bend your wrist back lots – it’s painful. Bend it back just a little.</li>
<li>timing: catch it on rise or at top of the bounce, rather than just off the bounce</li>
<li>against a heavy-spin loop, let the ball come to you and push down on it. Don’t move into it</li>
</ol>
<p>Backhand punch block:</p>
<ol>
<li>have a relaxed wrist</li>
<li>small backswing – imagine your hand hitting a sheet of paper and getting a nice “smack” on it for a “pop” sound</li>
<li>catch ball at the top of the bounce. Going early makes it hard to get over the net.</li>
<li>ascend <em>very slightly</em> through shot for a tiny bit of topspin (but tiny, as it’s still a punch)</li>
</ol>
Super-reliable forehand loop technique2023-07-02T16:20:01Zhttps://fuzzylogic.me/posts/super-reliable-forehand-topspin-technique/<p>Nice video here from Tom Lodziak in which coach Emma Harradine demonstrates a forehand loop (against backspin) that just looks <em>so</em> spinny, safe and reliable.</p>
<p>I’ve always liked the idea of this shot – the archetypal third ball in the rally – being like a well-oiled machine, but have never quite nailed it. So I’m gonna study this!</p>
<div class="l-frame">
<iframe title="Emma Haradine’s super-reliable forehand loop technique" width="560" height="315" src="https://www.youtube.com/embed/XcS7ol2GP10" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
</div>
<p>The key points are:</p>
<ol>
<li>Drop the right knee and put weight on right foot</li>
<li>Rotate hips and upper body so that non-playing shoulder, elbow face table and non-playing upper-arm is horizontal like table surface</li>
<li>Drop bat below height of the ball</li>
<li>Brush the ball</li>
<li>Contact ball at top of its bounce – don’t let it drop</li>
<li>Rotate hips, upper-body</li>
<li>The key is consistency and spin. This shot is a set-up not a winner</li>
<li>Next shot can be more direct and faster, but don’t blast it either – there’s no need. Going for position is really effective.</li>
</ol>
The New CSS (by Mattias Ott)2023-07-01T17:20:01Zhttps://fuzzylogic.me/posts/the-new-css-by-matthias-ott/<p>Matthias feels that the recent slew of additions to CSS have completely changed the game.</p>
<blockquote>
<p>this time, something feels different… the changes coming to CSS are so fundamental on so many levels that it almost feels like a singularity. There is now the CSS before and the CSS after the early 2020s.</p>
</blockquote>
<blockquote>
<p>Want to emulate and confidently design a layout that leverages the potential of CSS Grid in any of the major design tools like Figma, Adobe XD, or Sketch? Not possible. Want to define a color in one of the wide gamut color spaces like OKLCH, which result in more vibrant and natural colors on modern screens, maybe by using a color picker? Not possible. You want to simulate fluid typography that dynamically scales font sizes based on the viewport or container size and also define minimum and maximum values like you can do it in CSS with clamp()? Not possible. Or how about defining a fallback font in case your web font doesn’t load? Good luck using any screen design tool on the market. Not only are all of those things – very clearly – important design decisions, but they are also easily possible with just a few lines of CSS. In this new era of CSS, the design tools are now the limiting factor.</p>
</blockquote>
<p>He also hopes and suggests that CSS might become more respected and teams might “shift left” with regard to prototyping in the browser.</p>
<blockquote>
<p>What I expect to see overall is that the perception and thus the role of CSS in the design process will change from being mainly a presentational styling tool at the end of the waterfall to a tool that is being used at the heart of making design decisions early on. The value of a designer who knows how to prototype and build web components with modern CSS will therefore increase a lot. As a design engineering freelancer, I’m noticing this already.</p>
</blockquote>
Brothy fragrant chicken thigh and spinach noodle soup2023-06-29T18:34:01Zhttps://fuzzylogic.me/posts/brothy_chicken_thigh_soup_recipe/<p>A tasty and healthy asian-style recipe from Gousto, which I enjoyed cooking and eating and would like to make again.</p>
<h2 id="ingredients-(for-two-people)" tabindex="-1">Ingredients (for two people) <a class="direct-link" href="https://fuzzylogic.me/posts/brothy_chicken_thigh_soup_recipe/#ingredients-(for-two-people)" aria-hidden="true">#</a></h2>
<ul>
<li>Diced chicken thigh (250g)</li>
<li>Dried chilli flakes (0.5 tbsp)</li>
<li>Fine egg noodle nests (2)</li>
<li>Ginger and garilc paste (15g)</li>
<li>Pho broth base (25g)</li>
<li>Soy sauce (8ml)</li>
<li>Spinach (80g)</li>
<li>Toasted sesame oil (10ml)</li>
<li>Vegetable oil</li>
</ul>
<h2 id="instructions" tabindex="-1">Instructions <a class="direct-link" href="https://fuzzylogic.me/posts/brothy_chicken_thigh_soup_recipe/#instructions" aria-hidden="true">#</a></h2>
<p>Take chicken out of fridge, open the packet and let it air.</p>
<p>Boil a full kettle.</p>
<p>Heat a large, wide-based pan with a drizzle of veg oil over a high heat.</p>
<p>Once hot add your diced chicken thigh with your soy sauce and cook for an initial 5-6 min or until beginning to brown.</p>
<p>Was your spinach and pat it dry with kitchen paper.</p>
<p>Dissolve your pho broth paste in 600ml boiled water – this is your stock.</p>
<p>Reboil a kettle.</p>
<p>Add your fine egg noodles to a large bowl, cover them with boiled water and stir for 10 secs to separate the noodles. Set aside to soak for 4 min.</p>
<p>Once te chicken as ad an initial 5-6 min, add your ginger and garilc paste and half your chilli flakes and cook for a further 2-3 min or until fragrant.</p>
<p>Once fragrant add the stock to the pan with the chicken and bring to the boil over a high heat.</p>
<p>Once boiling, reduce the heat to medium and cook for a final 3 min or until the chicken is cooked through (no pink meat!).</p>
<p>Add the spinach to the pan and mix everything together until the spinach has slightly wilted – this is your fragrant chicken thigh and spinach broth.</p>
<p>Drain the soaked noodles.</p>
<p>Add the drained noodles to a bowl and pour in the fragrant chicken thigh and spinach broth.</p>
<p>Drizzle over your toasted sesame oil and sprinkle over the remaining chilli flakes.</p>
<p>Enjoy!</p>
Accessibility Personas2023-06-24T17:34:01Zhttps://fuzzylogic.me/posts/accessibility-personas/<p>This interesting website from the GDS accessibility team sets out seven personas, each with different access needs.</p>
<blockquote>
<p>You can use these profiles to experience the web from the perspective of the personas and gain more understanding of accessibility issues.</p>
</blockquote>
<p>The site explains how to set up a device or browser to give each persona its own profile simulating the persona’s condition(s) and runs the assistive technology they use to help them.</p>
The only accessibility specialist in the room – Tetralogical blog2023-06-22T15:57:01Zhttps://fuzzylogic.me/posts/the-only-accessibility-practitioner-in-the-room/<p>Henny Swan, director at Tetralogical, with some great advice for those whom accessibility responsibility often falls to.</p>
<p>Henny advises:</p>
<p>On <em>responsibility</em>: accessibility is everyone’s responsibility all the time, not just your responsibility all the time. Establish that you can support accessibility, but others also need to do accessibility work and make accessibility-related decisions.</p>
<p>On <em>relationship-building</em>: build relationships with decision-makers with authority to embed accessibility and practitioners ready to build up their skills.</p>
<p>On <em>sustainability and scalability</em>: look for ways to scale what you do through demonstration and documentation.</p>
<p>On <em>expectations</em>: manage expectations and be clear about what you can do. You can give advice, but teams themselves need to make informed decsions. Also – you won’t know everyting, and sometimes you need the help of expert consultancy.</p>
<p>On having <em>support</em> to hand: build a support network through community groups and mentor programmes. I’ve also taken Henny’s advice and subscribed to the <a href="https://webaim.org/discussion/">WebAIM accessibility discussion list</a>.</p>
Goldman Sachs Design System2023-06-20T11:27:01Zhttps://fuzzylogic.me/posts/goldman-sachs-design-system/<p>This Design System reference website sports a smart architecture with some interesting sections.</p>
<p>The components are neatly organised into categories. And I like the <em>Foundations</em> area which includes a <a href="https://design.gs.com/foundation/design-system-concepts">Design System Concepts</a> section serving as a glossary of property and anatomical terms, plus an Accessibility section with neat diagrams.</p>
<p>I think what I like best about this site/system is its organisation and naming.</p>
The web is fundamentally designed to be accessible to all2023-06-13T22:02:26Zhttps://fuzzylogic.me/posts/the-web-is-supposed-to-be-accessible-to-all/<p>Working as a web developer, you’ll meet colleagues who don’t realise that <strong>accessibility should be non-negotiable</strong>. So I’m bookmarking for ready access Tim Berners-Lee’s oft-quoted but still powerful statement of intent from 1997.</p>
<blockquote>
<p>The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect.</p>
</blockquote>
<p>This particular W3C WAI page goes on to say:</p>
<blockquote>
<p>The Web is fundamentally designed to work for all people, whatever their hardware, software, language, location, or ability. When the Web meets this goal, it is accessible to people with a diverse range of hearing, movement, sight, and cognitive ability.</p>
</blockquote>
<blockquote>
<p>Thus the impact of disability is radically changed on the Web because the Web removes barriers to communication and interaction that many people face in the physical world. However, when websites, applications, technologies, or tools are badly designed, they can create barriers that exclude people from using the Web.</p>
</blockquote>
<blockquote>
<p>Accessibility is essential for developers and organizations that want to create high-quality websites and web tools, and not exclude people from using their products and services.</p>
</blockquote>
A UX observation regarding good design, by Adam Silver2023-06-13T17:57:01Zhttps://fuzzylogic.me/posts/adam-silver-more-devs-that-care-about-good-design-than-designers/<p>A spicy but somewhat relatable thought from Adam Silver:</p>
<blockquote>
<p>UX observation: I think there might be more devs who care about good design than there are designers. By “good” I mean works for everyone (is accessible) rather than looks nice. What do you think?</p>
</blockquote>
<p>The ensuing conversation is pretty interesting. I particularly liked these contributions from <a href="https://twitter.com/martynhoyer">Martin Hoyer</a>:</p>
<blockquote>
<p>Absolutely. Thinking about the design code-first and understanding how HTML works is so valuable. I don’t think designers should learn HTML but they shouldn’t be the first people to decide how something is built!</p>
</blockquote>
<p>He goes on to describe how he thinks design <em>should</em> be done as follows:</p>
<blockquote>
<p>In an ideal world (and I don’t think I’ve ever fully achieved this) I’d like to get some requirements (from product I guess), build a prototype in code, then collaboratively iterate on the design from there. Maybe call it a design sprint or whatever!</p>
</blockquote>
Add Opacity to an Existing Color (by Chris Coyier)2023-05-17T16:34:01Zhttps://fuzzylogic.me/posts/add-opacity-to-existing-color/<p>Applying opacity to an existing colour value is a pretty common design requirement, and here Chris presents five ways to achieve it.</p>
<p>I’ll admit that the explosion of colour models is one aspect of CSS that leaves me dizzy, so this explanation framed around a practical requirement really helps. The main approaches presented by Chris are:</p>
<ul>
<li><a href="https://codepen.io/chriscoyier/pen/bGmKMGV">8 digit hex code</a></li>
<li><a href="https://codepen.io/chriscoyier/pen/eYPKVYb">relative colour syntax</a> (currently <a href="https://caniuse.com/css-relative-colors">only supported in Safari</a>)</li>
<li>using a format other than hex such as HSL since it’s easier to apply transparency</li>
<li>using (in a progressively enanced approach) HDR-display-friendly colours, via <a href="https://css-tricks.com/the-expanding-gamut-of-color-on-the-web/">a new colour format</a> such as <code>oklch</code></li>
</ul>
Fuzzy Logic show (April 23), Radio Buena Vida2023-04-24T17:20:00Zhttps://fuzzylogic.me/posts/fuzzy-logic-show-rbv-220423/<p>My latest radio show is dedicated to Ryuichi Sakamoto, who sadly died recently. I played a couple of tracks by the great man alongside more of my favourite music.</p>
<p><a href="https://soundcloud.com/radiobuenavida/fuzzy-logic-w-laurence-hughes-radio-buena-vida-220423">Listen to the show on Soundcloud.</a></p>
<p>Here’s the tracklist:</p>
<ol>
<li>Ryuichi Sakamoto & Alva Noto - Aurora</li>
<li>Matt Wilde - Who Cares</li>
<li>Kaidi Tatham - Funky Fool</li>
<li>Mac DeMarco - 20180702 2</li>
<li>Robert Ffrench - I am wondering</li>
<li>Ryuichi Sakamoto - Plastic Bamboo</li>
<li>Kraftwerk - Vitamin</li>
<li>Mac DeMarco - 20180924</li>
<li>Gal Costa - Relance (Bernhard Pinheiro edit)</li>
<li>Imagination - So good, so right (12″ mix then dub)</li>
<li>Romaal Kultan - Between Us, Part One</li>
<li>Jayme Marques - Berimbao</li>
<li>Souldrummers - Space And Time</li>
</ol>
<p>I really enjoyed this one and I’m pleased with how it turned out. Thanks to Susan and Speedy for having me back.</p>
W3C and Smart Interface pattern websites2023-04-15T06:56:56Zhttps://fuzzylogic.me/posts/w3c-and-smart-interface-pattern-websites/<p>Two lovely new websites (or website updates) appeared on my radar this last week that I wanted to note here for future front-end inspiration.</p>
<p>Vitaly Friedman’s <a href="https://smart-interface-design-patterns.com/">Smart Interface Patterns</a> has had some lovely animation and component work from Clearleft alumni <a href="https://www.cassie.codes/">Cassie Evans</a> and <a href="https://www.trysmudford.com/">Trys Mudford</a>. Given Vitaly’s obsession with creating accessible, user-friendly components and the collaborators he has on board, I expect this site to be choc-full of well crafted nuggets for reference! It looks ace, too.</p>
<p>I noted a while ago that <a href="https://fuzzylogic.me/posts/w3c-design-system/">the W3C had a new Design System</a>, and now <a href="https://beta.w3.org/">the W3C has a new website</a> in beta too. I imagine it might use components from that Design System alongside other carefully-considered patterns of markup, style and behaviour.</p>
<p>Nice job on these sites, to all concerned!</p>
First play with CSS Container Queries2023-04-10T19:42:17Zhttps://fuzzylogic.me/posts/first-play-with-css-container-queries/<p>In responsive design we generally want a single component to get different styles in different contexts. Up until recently the prevailing method of context-awareness was to use a CSS media query to query the <em>viewport</em> size. This wasn’t ideal. For example you might want an component to be styled differently when in a narrow context such as a sidebar (regardless of the device size), and viewport-based queries don’t help with that.</p>
<p>But everything has changed. We can now use CSS to query the size of any given container and <a href="https://caniuse.com/css-container-queries">this feature is supported in all major browsers</a>.</p>
<p>There’s a bit of new syntax to learn, so I recently had <a href="https://codepen.io/fuzzylogicx/pen/xxaeVbQ?editors=1100">my first play with container queries</a> on codepen.</p>
<p>My pen is pretty trivial, but the goal was specifically to do the most minimal test that lets me test-drive the key syntax. It turns out that it’s quite straightforward.</p>
<p>Define an element as a container:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.sidebar</span> <span class="token punctuation">{</span><br /> <span class="token property">container</span><span class="token punctuation">:</span> ctr-sidebar / inline-size<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Change the styles of another element (<code>.foo</code>) when it’s inside that container and the container’s inline-size (the logical property name for <code>width</code>) matches a given query:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@container</span> ctr-sidebar <span class="token punctuation">(</span><span class="token property">max-width</span><span class="token punctuation">:</span> 300px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.foo</span> <span class="token punctuation">{</span><br /> // context-specific styles go here <br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Note that you could also omit the <code>ctr-sidebar</code> context in the above query, if you wanted the change to apply in <em>all</em> defined containers.</p>
Collaboration versus handoff, and avoiding broken promises2023-04-09T10:20:03Zhttps://fuzzylogic.me/posts/handoff-versus-collaboration/<p>I’m a fan of web designers and developers collaborating closely rather than designers throwing mock-ups over the wall. Recently I read two newsletters relating to this topic, or perhaps more accurately about perceived divisions between design and development and some better, more modern ways of thinking.</p>
<p>The first, <a href="https://mailchi.mp/smashingmagazine.com/better-design-estimates-1134673?e=854bbd5846">The best handoff is no handoff</a> from Smashing Magazine, presents alternatives to waterfall including <a href="https://danmall.com/posts/hot-potato-process/">The Hot Potato Process</a> espoused by Brad Frost and Dan Mall.</p>
<p>The second, <a href="https://tinyletter.com/clearleft/letters/march-2023-at-clearleft-promises">Promises</a> from Clearleft argues that presenting flat designs for <em>sign-off</em> at an early stage of a project doesn’t make sense given the nature of the web, and that it makes promises that can’t be kept.</p>
<blockquote>
<p>In practice, sign-off leads to disappointment for everyone involved. A design created in isolation in a graphics-design tool almost never survives contact with the reality of the web. The client is disappointed that the final output doesn’t match what was signed off. The developer is disappointed that they weren’t consulted sooner. The designer is disappointed that the code doesn’t match the design.</p>
</blockquote>
<p>Clearleft argue instead for presenting the coded page in the browser because it avoids broken promises and presents reality.</p>
The new HTML search element2023-04-03T08:55:20Zhttps://fuzzylogic.me/posts/the-new-html-search-element/<p>My work colleague <a href="https://twitter.com/ryandeegan">Ryan</a> recently drew my attention to the new HTML <code>search</code> element. This morning I read <a href="https://www.scottohara.me/blog/2023/03/24/search-element.html">Scott O’Hara’s excellent primer</a>. Scott worked on implementing <code><search></code>, and his article cleared up my questions around what it is and when we can start using it.</p>
<p>Firstly <code><search></code> is not a “search input” – it’s not a replacement for any existing <code>input</code> elements. Instead it’s a native HTML element to create a <code>search</code> <a href="https://www.w3.org/TR/wai-aria-1.2/#landmark_roles">landmark</a>, something that until now we could only achieve by applying <code>role="search"</code> to another element.</p>
<p>Landmarks are an important semantic structure allowing screen reader users to orient themselves and jump to important areas of a web page. Existing landmark-signalling elements you might know include <code><header></code>, <code><main></code>, <code><footer></code>. So you would use <code><search></code> to <em>wrap around</em> a search function, thus providing additional accessibility. And it lets you do so with a native HTML element instead of re-purposing another element by adding ARIA properties, per <a href="https://www.w3.org/TR/using-aria/#rule1">the first rule of ARIA use</a>. It’d look something like this:</p>
<pre><code><search>
<form action="/path/to/search/">
<label for="query">Find an article</label>
<input id="query" name="q" type="search">
<button type="submit">Go!</button>
</form>
</search>
</code></pre>
<p>So as Scott himself admits:</p>
<blockquote>
<p>To be brutally honest, this is not the most important element that’s ever been added to the HTML specification. It <em>is</em> however a nice little accessibility win.</p>
</blockquote>
<h2 id="do-i-have-a-use-for-this%3F" tabindex="-1">Do I have a use for this? <a class="direct-link" href="https://fuzzylogic.me/posts/the-new-html-search-element/#do-i-have-a-use-for-this%3F" aria-hidden="true">#</a></h2>
<p>If you have a search function or search page and currently miss the opportunity to offer a <em>search</em> landmark you could do so and improve the user experience.</p>
<h2 id="can-i-use-the-%3Csearch%3E-element-today%3F" tabindex="-1">Can I use the <code><search></code> element today? <a class="direct-link" href="https://fuzzylogic.me/posts/the-new-html-search-element/#can-i-use-the-%3Csearch%3E-element-today%3F" aria-hidden="true">#</a></h2>
<p>As Scott mentions, it’s not yet available in browsers (although it likely will arrive soon). So if you added <code><search></code> (just as I’ve typed it there) to a page, it wouldn’t currently create a search landmark. So you <em>could</em> wait for a while before using the element. Alternatively, because HTML’s design is intentionally geared toward a progressive enhancement mindset, you could take <a href="https://adactio.com/links/20054">Jeremy Keith’s approach</a> and safely use the following today:</p>
<pre><code><search role="search">
...
</search>
</code></pre>
<p>Jeremy knows that when browsers encounter an HTML element they don’t know, they don’t break but rather treat it as an anonymous element and carry on. So he includes <code><search></code> to start adopting the new element today, but bolts on <code>role=search</code> temporarily to manually provide the landmark until browsers understand <code>search</code>. He’ll then remove the <code>role=search</code> part once support for <code>search</code> is widespread.</p>
Possibilities, Herbie Hancock’s memoir2023-04-02T10:00:00Zhttps://fuzzylogic.me/posts/finised-reading-herbie-hancock-possibilities/<p>I’ve been listening to lots of jazz of late and <a href="https://fuzzylogic.me/posts/herbie-hancock-at-edinburgh-playhouse/">loved seeing Herbie Hancock live in August 22</a>.</p>
<p>So I thought I’d explore further and listen to <a href="https://books.apple.com/fr/audiobook/herbie-hancock-possibilities-unabridged/id1531547010">the audio recording of Herbie’s autobiography Possibilities</a>, narrated by the great man himself.</p>
<p>I really enjoyed it. Herbie’s story is really interesting and entertaining. He’s been at the forefront of so many iconic scenes – from playing in Miles Davis’s band, to writing many classics of his own, to breaking new ground with his Mwandishi sextet and the Headhunters.</p>
<p>I love his carefree and curious spirit and his willingness to experiment with technology (from the fender Rhodes, to other synths, to the internet) and take risks in other aspects of life.</p>
<p>What a talent and what a guy!</p>
Fuzzy Logic show (March 23), Clyde Built Radio2023-03-27T17:20:00Zhttps://fuzzylogic.me/posts/fuzzy-logic-laurence-hughes-march-23-clyde-built-radio/<p>I recorded my second radio show of 2023 live at the Clyde Built Radio studio at the weekend. It was great playing records there on a sunny Sunday with the clocks just gone forward and the Barras buzzing as it hosted a Hong Kong street market.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1680028894/clyde_1400_mar2023_mozjpg_iejw5x.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1680028894/clyde_1400_mar2023_mozjpg_iejw5x.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_auto,w_1292/v1680028894/clyde_1400_mar2023_mozjpg_iejw5x.jpg" width="1400" height="1050" alt="Laurence at the Clyde Built Radio studio in March 2023" loading="lazy" decoding="async" />
</picture>
<figcaption>At the Clyde Built Radio studio</figcaption>
</figure>
<p>This month I went for a set of reggae, electronics and other assorted good vibes.</p>
<p><a href="https://soundcloud.com/clydebuiltradio/fuzzy-logic-w-laurence-1">Listen to the show on Soundcloud.</a></p>
<p>Here’s the tracklist:</p>
<ol>
<li>Mali-I - Next Level Intro</li>
<li>Robert Ffrench - You are so special</li>
<li>Radio Trip - No Oud</li>
<li>Lucas Croon - Japon</li>
<li>Babeth - Orchestra Reggae</li>
<li>Tyrone Evans - Rise Up (Version)</li>
<li>Gateway Shuffle - Snapping</li>
<li>Cloud - Moon Rock</li>
<li>Azura - Theme from Azura</li>
<li>Visage - Pleasure Boys</li>
<li>Romaal Kultan - Meditate</li>
<li>Language - Tranquility Bass</li>
</ol>
<p>Thanks to <a href="https://www.instagram.com/a.rodger.s/">Amy</a> for arranging, and to Matthew, the engineer on the day.</p>
Quick circle (by Adam Argyle)2023-03-26T17:20:00Zhttps://fuzzylogic.me/posts/quick-circle-by-adam-argyle/<p>I’m wary of list-based clickbait – and Adam’s recent <a href="https://web.dev/6-css-snippets-every-front-end-developer-should-know-in-2023">6 CSS snippets every front-end developer should know in 2023</a> feels like that – however I like this modern and minimal approach to creating a circle. I’ve previously seen <code>aspect-ratio: 1</code> used to create a square box and it’s a lovely shorthand for “make width and height equal”. It makes sense that you can use it for a circle too, just by adding some <code>border-radius</code>.</p>
<pre><code>.circle {
inline-size: 25ch;
aspect-ratio: 1;
border-radius: 50%;
}
</code></pre>
Modern Font Stacks2023-03-26T16:07:46Zhttps://fuzzylogic.me/posts/modern-font-stacks/<blockquote>
<p>System font stack CSS organized by typeface classification for every modern OS. The fastest fonts available. No downloading, no layout shifts, no flashes — just instant renders.</p>
</blockquote>
<p>This is a great resource for when you want a particular style of font (workhorse sans-serif, grotesque, monospace, display slab serif etc) and to favour a system font rather than a custom font to get performance and simplicity benefits allied to having many weights and characters natively available.</p>
<p>To grab a stack, just copy the <code>font-family</code> declaration from its card then paste that into your CSS.</p>
<p>To easily preview how custom text of your choice would look in each stack, use the handy form at the top of the page.</p>
<p>Aside from its utility I also love this page as a learning resource. For each font category, the font and weight your browsing context is currently using is highlighted in blue with a solid underline, while those available but not currently in use and those unavailable are also separately highlighted. This gives you even more information than Firefox’s font panel or the <a href="https://chrome.google.com/webstore/detail/whatfont/jabopobgcpjmedljpbcaablpmlmfcogm">WhatFont</a> extension for Chrome.</p>
<p>Notes:</p>
<ul>
<li>if you notice support for a font when you wouldn’t expect it (because your OS doesn’t include it), it’s worth remembering that you may have previously installed it locally. This was the case for me with <em>Inter</em> in the <a href="https://modernfontstacks.com/?stack=neo-grotesque">Neo-Grotesque</a> stack. You can click the little “info” icon links beside each stack’s title for <a href="https://github.com/system-fonts/modern-font-stacks#neo-grotesque">detailed info on that stack including which OSs use which font</a></li>
<li>the declaration <code>font-family: system-ui, sans-serif</code> as a means of serving the Operating System’s default sans-serif seemed suspiciously simple given the complicated iterations I’ve seen previously. However after some digging I confirmed that <a href="https://caniuse.com/font-family-system-ui">Firefox added support for <code>system-ui</code> a few years ago</a> so <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1226042#c15">previous, verbose alternatives</a> are no longer necessary.</li>
</ul>
5 things I learned working on a design system for a year (by Anda Popovici)2023-03-19T16:34:01Zhttps://fuzzylogic.me/posts/5-things-i-learned-working-on-a-design-system-for-a-year-by-anda-popovici/<p>I was delighted to discover that my talented colleague <a href="https://www.andapopovici.com/">Anda</a> has her own website and uses it to write articles like this! This one is obviously pretty relevant to me too, given that I work on the same team.</p>
<p>I particularly liked the fifth lesson – “You are an integral part of the company”. This is an aspect of Design System work that I care about because it’s important to me to work on impactful things that get into a lot of users’ hands.</p>
Design Systems should avoid “God components” and Swiss Army Knives2023-03-17T13:44:20Zhttps://fuzzylogic.me/posts/design-systems-should-avoid-god-components-and-swiss-army-knives/<p>Something we often talk about in our Design System team is that components should not be like Swiss Army Knives. It’s better for them to be laser-focused because by limiting their scope to a single task they are more reusable and support a more extensible system through composition.</p>
<p>Discussions often arise when we consider the flip-side – components which do too much, know too much, or care too much! When they cover too much ground or make assumptions about their context, things go wrong. Here are some examples.</p>
<h2 id="card" tabindex="-1">Card <a class="direct-link" href="https://fuzzylogic.me/posts/design-systems-should-avoid-god-components-and-swiss-army-knives/#card" aria-hidden="true">#</a></h2>
<p>In websites where many elements have a “rounded panel”-like appearance so as to pop off the background, you can run into problems. Because of the <em>somewhat</em> Card-like appearance, people start to regard many semantically distinct things as “Cards” (rather than limiting the meaning of Card to <a href="https://www.bbc.co.uk/gel/features/cards">a more conventional definition</a>). Here are some of the problems this can cause:</p>
<ul>
<li>If the name covers a million use cases, then how can you <em>describe</em> it sensibly, or define its boundaries?</li>
<li>When do you stop piling on different things it can mean? How do you stop it growing? How do you avoid bloat?</li>
<li>Ongoing naming/confusion issues: you’re setting yourself up for continued confusion and code disparity. If something is “semantically” a note, or a comment, or a message etc then you can expect that future staff are gonna describe it as that rather than a Card! They’ll likely (understandably) write code that feels appropriate too. The problem will continue.</li>
</ul>
<p>I appreciate that often we need pragmatic solutions, so if our designs have lots of similar-looking elements then there is still something we can do. If the repeated thing is more of a “shape” than a something with common-purpose, then just call it out as that! That could either be by name – for example Every Layout have a <a href="https://every-layout.dev/layouts/box/"><em>Box</em> layout</a> which could be a starting point – or by categorisation i.e. by moving the non-ideally named thing into a clearly demarcated <em>Utilities</em> (or similar) category in your Design System.</p>
<h2 id="flex" tabindex="-1">Flex <a class="direct-link" href="https://fuzzylogic.me/posts/design-systems-should-avoid-god-components-and-swiss-army-knives/#flex" aria-hidden="true">#</a></h2>
<p>It seems that a number of Design Systems have a <em>Flex</em> component. My feeling, though, is that these represent an early reaction to the emergence of CSS’s Flexbox, rather than necessarily being sensible system-friendly or consumer-friendly components. CSS layout covers <em>a lot</em> and I think breaking this down into different smaller tools (Stack, Inline, Grid etc) works better.</p>
<h2 id="button" tabindex="-1">Button <a class="direct-link" href="https://fuzzylogic.me/posts/design-systems-should-avoid-god-components-and-swiss-army-knives/#button" aria-hidden="true">#</a></h2>
<p>I’ve talked before about <a href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/">the “Everything is a button” mindset and how it’s harmful</a>. Buttons and links are fundamentally different HTML elements with totally different purposes, and bundling them together has various ill effects that I see on a regular basis.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/design-systems-should-avoid-god-components-and-swiss-army-knives/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://fuzzylogic.me/posts/2021-05-24-shifting-left-how-introducing-accessibility-earlier-helps-the-bbcs-design-system-or-by-sophie-beaumont-or-bbc-design-engineering/">Shifting left: how introducing accessibility earlier helps the BBC’s design system (by Sophie Beaumont)</a></li>
</ul>
SaaS startups will have to care about productivity again, by DHH2023-03-13T21:26:49Zhttps://fuzzylogic.me/posts/saas-startups-will-have-to-care-about-productivity-again-by-dhh/<blockquote>
<p>Getting to profitability is no longer a distant, post-IPO nice-to-have, but a short-term necessity for survival. But how to do that without cutting off the legs of the product team? By using better tools and techniques, that's how.</p>
</blockquote>
<p>DHH of 37 Signals and Basecamp offers three pieces of advice for productivity and profitability.</p>
<blockquote>
<p>1: Unless market conditions demand otherwise, delay native app development for as long as possible.</p>
<p>2: Hire full-stack developers, and don't let them split the frontend and backend into separate jurisdictions.</p>
<p>3: Hire designers who work natively with the web.</p>
</blockquote>
<p>I’m not a fan of the term “full-stack” and also think it underestimates the complexity/speciality required to work (properly) as a front-end developer. However that aside, I think there is sense in these, even though others I know would disagree.</p>
Weekend at Banchory Farm, Fife2023-03-06T17:20:01Zhttps://fuzzylogic.me/posts/weekend-at-drinkbetween-cottage/<p>Me, Clair and Rudy just enjoyed a lovely weekend break. We stayed at <a href="https://www.banchoryfarm.co.uk/general-5">Drinkbetween cottage on Banchory Farm</a>. While only 70 minutes drive from home it provided some lovely countryside isolation, with the bonus of nice nearby towns to visit nearby too.</p>
<p>The cottage has recently been restored by the farm owners and was the perfect environment to relax.</p>
<p>Our nearest neighbours were some colourful pheasants, a flock of sheep and three highland cows grazing in the fields opposite. Beyond them, there was a view onto the firth of forth and Forth bridges.</p>
<p>On the Saturday we enjoyed a short trip to the nearby towns of Aberdour via Burntisland, and moseyed down to the lovely Silver beach where we stopped for a coffee at <a href="https://www.tripadvisor.co.uk/Restaurant_Review-g551742-d3472542-Reviews-Sands-Aberdour_Fife_Scotland.html">Sands</a>.</p>
<p>Clair brought and made beautiful food and at night we watched <a href="https://fuzzylogic.me/posts/captain-fantastic/">Captain Fantastic</a>.</p>
<p>It was a reminder of just how great a well-needed change of pace and scenery you can get in a short distance and space of time.</p>
Captain Fantastic2023-03-05T20:17:15Zhttps://fuzzylogic.me/posts/captain-fantastic/<p>Clair and I loved this story of Viggo Mortensen’s Ben Cash and family temporarily leaving their off-grid existence in the Pacific Northwest to enter civilisation. It poses some interesting questions about parenting, lifestyle and morality but mainly, it’s just a lot of fun.</p>
<div class="l-frame">
<iframe title="Official Trailer for movie “Captain Fantastic”" width="560" height="315" src="https://www.youtube.com/embed/w5jeBvjcJe4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
</div>
<p>Judging by his movie review for The Guardian, <a href="https://www.theguardian.com/film/2016/sep/11/captain-fantastic-review-viggo-mortensen">Mark Kermode seemed to like Captain Fantastic too</a>.</p>
Fuzzy Logic show (Feb ‘23), Clyde Built Radio2023-02-26T11:06:08Zhttps://fuzzylogic.me/posts/fuzzy-logic-laurence-hughes-feb-23-clyde-built-radio/<p>Having pre-recorded previous shows, I recently made a first visit to <a href="https://www.clydebuiltradio.com/">Clyde Built Radio’s</a> station at the Barras market for a live show and really enjoyed it. It’s such a great location and it was a nice change to spin records on a Sunday morning.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1677414630/clyde_1400_feb2023_mozjpg_yxhxkz.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1677414630/clyde_1400_feb2023_mozjpg_yxhxkz.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_auto,w_1292/v1677414630/clyde_1400_feb2023_mozjpg_yxhxkz.jpg" width="1400" height="1050" alt="Three records – by Bitchin Bajas, Isotope 217 and Visions of Tomorrow – that featured on Laurence Hughes’s February 2023 Clyde Built Radio show" loading="lazy" decoding="async" />
</picture>
<figcaption>Featured sounds from Bitchin Bajas, Isotope 217 and Visions of Tomorrow</figcaption>
</figure>
<p>I started off gently with atmospheric music from Detroit’s Ian Finklestein followed by a modern take on Steve Reich from Bitchin Bajas. From there it was into some hazy electronics and a dash of 80s boogie before landing on sounds from house music legends Abacus and Larry Heard.</p>
<p><a href="https://soundcloud.com/clydebuiltradio/fuzzy-logic-w-laurence-hughes">Listen to the show.</a></p>
<p>Here’s the tracklist:</p>
<ol>
<li>Ian Finklestein – Ago-ra</li>
<li>Bitchin Bajas – Amorpha</li>
<li>Isotope 217 – Audio Boxing</li>
<li>Coral D & PST – Send it</li>
<li>Komiko – Feel Alright</li>
<li>Visions of Tomorrow – Galaxy</li>
<li>Wheelup – Infinity feat. Abacus</li>
<li>Cy Gorman – Dewy Drip</li>
<li>Peech Boys – Don’t make me wait (Dub)</li>
<li>Purelink – Dozen Sunbeams (Nice Girl version)</li>
<li>Abacus – The Lower End Theory</li>
<li>Ossie – I hurt you</li>
<li>Fingers Inc – Bye Bye</li>
</ol>
<p>Thanks to <a href="https://www.instagram.com/a.rodger.s/">Amy</a> for the invite, and <a href="https://www.instagram.com/brandonleevear/">Brandon</a>, the engineer on the day.</p>
Displaying tables on narrow screens2023-02-25T14:24:43Zhttps://fuzzylogic.me/posts/displaying-tables-on-narrow-screens/<p>Responsive design for tables is tricky. Sure, you can just make the table’s container horizontally scrollable but that’s more a developer convenience than a great user experience. And if you instead try to do something more clever, you can run into challenges <a href="https://fuzzylogic.me/posts/tables-and-pseudo-tables-lessons-and-tactics/">as I did in the past</a>. Still, we should strive to design good narrow screen user experiences for tables, alongside feasible technical solutions to achieve them.</p>
<p>In terms of UI design, I was interested to read Erik Kennedy’s recent newsletter on <a href="https://ckarchive.com/b/75u7h8hk4mne3"><em>The best way to display tables on mobile</em></a>. Erik lists three different approaches, which are (in reverse order of his preference):</p>
<ol reversed="">
<li>Hide the least important columns</li>
<li>Cards with rows of Label-Value pairs</li>
<li>More radical “remix” as a “Mobile List”</li>
</ol>
<p>Another article worth checking is Andrew Coyle’s <a href="https://coyleandrew.medium.com/the-responsive-table-44d533fde1e9">The Responsive Table</a>. He describes the following approaches:</p>
<ol>
<li>Horizontal overflow table (inc. fixed first column)</li>
<li>Transitional table</li>
<li>Priority responsive table</li>
</ol>
<p>For the transitional table, Andrew links to Charlie Cathcart’s <a href="https://codepen.io/pixelchar/full/rNaKLM">Responsive & Accessible Data Table</a> codepen. It looks similar (perhaps better looking but not quite as accessible) to Adrian Roselli’s <a href="https://adrianroselli.com/2017/11/a-responsive-accessible-table.html">Responsive Accessible Table</a>.</p>
Native CSS Nesting2023-02-18T10:33:25Zhttps://fuzzylogic.me/posts/native-css-nesting/<p>I’ve started reading some entries from Manuel Matuzovic’s <a href="https://www.matuzo.at/blog/2022/100-days-of-more-or-less-modern-css/">100 days of (more or less) modern CSS</a> series, and began with the excellent <a href="https://www.matuzo.at/blog/2023/100daysof-day99/">Day 99: Native Nesting</a>. It clearly explains how to use the <a href="https://webkit.org/blog/13813/try-css-nesting-today-in-safari-technology-preview/">now-agreed syntax</a> for various common scenarios.</p>
<p>The syntax is pretty close to what we’re used to doing with Sass, which is great!</p>
<p>Also, I’m now also clear that nested selectors must always start with a symbol rather than a letter. Often they would naturally do so anyway, for example when nesting a class since that already starts with a symbol (a full stop). But in cases where they wouldn’t – essentially only when nesting an “element selector” – we start it with an “&”. So:</p>
<pre><code>main {
& article { ... }
}
</code></pre>
<p>Straightforward enough!</p>
<p>Regarding <a href="https://caniuse.com/css-nesting">browser support for CSS nesting</a>, at the time of writing it is available in Chrome and Safari Technology Preview only.</p>
<p>I would therefore only use it for demos and for the most non-essential enhancements. We’ll need to hold off any <em>full-scale switch</em> from Sass nesting to CSS nesting for large and important production websites until this is in Firefox and standard Safari, and until a sufficient percentage of users has the up-to-date versions. So a little while away yet, but given the current rate of browser updates, likely sooner than we might think!</p>
No Style Design System2023-02-17T20:03:00Zhttps://fuzzylogic.me/posts/no-style-design-system/<p>Adam Silver’s collection of accessible form-related components – a companion to his book Form Design Patterns – is a brilliant reference.</p>
<p>In there you’ll find Autocomplete, date fields, validation and lots of other tricky components and patterns.</p>
The Component Gallery2023-02-16T09:03:21Zhttps://fuzzylogic.me/posts/the-component-gallery/<p>The component gallery is an up-to-date list of interface component examples. It’s really helpful for looking up existing naming conventions. It also contains <a href="https://component.gallery/design-systems/">a list of Design Systems</a>.</p>
Use the dialog element (reasonably), by Scott O’Hara2023-02-03T09:03:21Zhttps://fuzzylogic.me/posts/use-the-dialog-element-reasonably-by-scott-o-hara/<p>Here’s an important update on <em>native modal dialogues</em>. TL;DR – it’s now OK to use <code>dialog</code>.</p>
<p>Last year <a href="https://fuzzylogic.me/posts/refactoring-a-modal-dialogue-in-2022/">I posted that Safari now supported the HTML <code>dialog</code> element</a> meaning that we were within touching distance of being able to adopt it with confidence. My caveat was:</p>
<blockquote>
<p>However first I think we’d need to make an informed decision regarding our satisfaction with support, based on the updated advice in Scott O’Hara’s article <a href="https://www.scottohara.me/blog/2019/03/05/open-dialog.html">Having an Open Dialog</a>.</p>
</blockquote>
<p>(Accessibility expert Scott O’Hara has been diligently testing the <code>dialog</code> element for <em>years</em>.)</p>
<p>However the happy day has arrived. The other day Scott posted <a href="https://www.scottohara.me/blog/2023/01/26/use-the-dialog-element.html">Use the dialog element (reasonably)</a>. It includes this advice:</p>
<blockquote>
<p>I <em>personally</em> think it’s time to move away from using custom dialogs, and to use the <code>dialog</code> element instead.</p>
</blockquote>
<p>That’s an important green-light!</p>
<p>And this of course means that we can stop DIYing modal dialogues from <code>div</code>s plus super-complicated scripting and custom ARIA, and instead let a native HTML element do most of the heavy lifting for us.</p>
<p>From a Design System perspective, I’d previously suggested to my team that when we revisit our <em>Modal</em> component we should err toward a good custom dialogue library first, however I’m now likely to recommend we go for native <code>dialog</code> instead. Which is great!</p>
Web Components Guide2023-01-14T10:03:21Zhttps://fuzzylogic.me/posts/web-components-guide/<p>This new resource on Web Components from Keith Cirkel and Kristján Oddsson of GitHub (and friends) is looking great so far.</p>
<p>As <a href="https://twitter.com/fuzzylogicx/status/1614202359520919553">I recently tweeted</a>, I love that it’s demoing “vanilla” Web Components first rather than using a library for the demos.</p>
<p>So far I’ve found that the various web component development frameworks (<a href="https://lit.dev/">Lit</a> etc) are cool, but generally I’d like to see more demos that create components <em>without</em> using abstractions. The frameworks include dependencies, opinions and proprietary syntax that (for me at least) make an already tricky learning curve more steep so they’re not (yet) my preferred approach. Right now I want to properly understand what’s going on at the web standards level.</p>
<p>Aside from tutorials this guide also includes a great <a href="https://webcomponents.guide/learn/"><em>Learn</em></a> section which digs into JavaScript topics such as Classes and Events and why these are important for Web Components.</p>
<p>I hope that in future the guide will cover testing Web Components too.</p>
<p>Lastly, I like the <a href="https://webcomponents.guide/tutorials/mastodon-toot-embed/">Embed Mastodon Toot</a> web component tutorial, and to help it sink in (and save the code for posterity) I’ve <a href="https://codepen.io/fuzzylogicx/pen/RwBgveM">chucked the code into a pen</a>.</p>
Mystery Road – Origin2023-01-12T21:03:21Zhttps://fuzzylogic.me/posts/mystery-road-origin/<p>This is the best TV I’ve watched in a while, and Clair and I eagerly binged it in two days. I loved how it looked, the atmospheric music, the characters, the acting and the issues. I’ll now need to watch the other two <em>Mystery Road</em> series.</p>
A Designer’s Guide to Documenting Accessibility & User Interactions (by Stephanie Walter)2023-01-06T21:03:21Zhttps://fuzzylogic.me/posts/a-designer-s-guide-to-documenting-accessibility-user-interactions-by-stephanie-walter/<p>My teammate Colin just shared this brilliant designers’ guide to documenting accessibility and user interactions. It’s really thorough and includes some pretty clever annotation techniques.</p>
<p>I agree with Stephanie that unless you ask the questions and document the answers regarding how a design will translate to an accessible reality then it can fall short at lots of points from the start to the implementation. This called to mind a similar perspective from Sophie Beaumont on <a href="https://fuzzylogic.me/posts/2021-05-24-shifting-left-how-introducing-accessibility-earlier-helps-the-bbcs-design-system-or-by-sophie-beaumont-or-bbc-design-engineering/">how the BBC shift left regarding accessibility</a>.</p>
<p>This type of annotation and discussion also feels like another healthy way for designers and engineers to talk to (and learn from) each other more.</p>
<p>I really like Stephanie’s conclusion that you won’t always have time for all of the techniques she mentions, so pick your battles.</p>
Lean “plugin subscription form” by Chris Ferdinandi 2023-01-02T21:03:21Zhttps://fuzzylogic.me/posts/lean-plugin-subscription-form-by-chris-ferdinandi/<p>I enjoyed this two-part tutorial from Chris arising from his critique of a subscription form plugin which includes the entire React library to achieve what could be done with a lightweight HTML and vanilla JavaScript solution. Chris advocates a progressively-enhanced approach. Instead of rendering the form with JavaScript he renders it in HTML and argues that not only is there no need for the former approach – because forms natively work without JavaScript – but also it only introduces fragility where we could provide resilience.</p>
<p>Part one: <a href="https://gomakethings.com/using-a-wrecking-ball-for-a-problem-that-requires-hammer/">Using a wrecking ball when a hammer would suffice</a></p>
<p>Part two: <a href="https://gomakethings.com/more-html-less-javascript/">More HTML, less JavaScript</a></p>
<p>I also recreated the front-end parts in <a href="https://codepen.io/fuzzylogicx/pen/yLqJzmZ">a codepen</a> to help this sink in.</p>
<p>Lastly, as someone who always favours resilience over fragility I wanted to take a moment to consider the part that Chris didn’t cover – why JavaScript is required <em>at all</em>. I guess it’s because, being a plugin, this is intended for portability and you as author have decided you want the error and success messaging to be “white-labelled” on the consuming website rather than for the user to be taken to a separate website. You don’t know the context’s stack so to provide a universally-supported solution you use JavaScript to handle the messaging, which then means you need to use JS to orchestrate everything else – preventing default submission, validating, fetch-based submission and API response handling.</p>
BadBadNotGood at QMU, Glasgow2022-12-14T11:16:58Zhttps://fuzzylogic.me/posts/badbadnotgood-at-qmu-glasgow/<p>Went to see BadBadNotGood with Marty, Jenni and Zippy last night, and they were fantastic.</p>
<p>We braved -7° conditions to meet at Tennent’s Bar on Byres Rd where we watched Argentia beat Croatia in the World Cup semi-final. Then onto the QMU, which provided a real nostalgia hit – I think the last time we were there was to see Roni Size and Reprazent in the <em>Brown Paper Bag</em> era.</p>
<p>We wangled a standing position on the balcony which was ideal as we could see the band, the visuals (lovely 16mm and 35mm film projections created specially for the music) and generally hear things much better. Each band member – drummer, bassist, saxophonist and keyboard player – are outstanding musicians, and together they’re incredibly tight. Led by drummer Alex Sowinski’s good vibes on the mic, they finished off their tour hitting all the right notes to send us into Christmas on a high.</p>
<p>Last thing to mention is I have BadBadNotGood to thank for introducing me to the music of <a href="https://undergroundsolushn.com/arthur-verocai-arthur-verocai.html">Arthur Verocai</a>, via <a href="https://youtu.be/BUePFld3UHo">his amazing string arrangements on Talk Memory</a>. And for that I’m very thankful!</p>
Visit to North Berwick2022-12-10T14:23:19Zhttps://fuzzylogic.me/posts/visit-to-north-berwick/<p>During a recent November week off I enjoyed a first visit to North Berwick. It’s a beautiful seaside town and I was lucky enough to get lovely cold-but-sunny winter weather.</p>
<p>Here are some of the things I did:</p>
<ul>
<li>Stayed at the Marine Hotel. This was a treat as it was quite posh, but I save money these days from being at home a lot and it was only for a couple of days so I’m gonna allow myself this one. The breakfast (porridge followed by cooked breakfast) was amazing and I also loved the pool and outdoor jacuzzi!</li>
<li>Beach walk beside the golf course into town</li>
<li>A walk around the harbour including great cliff views out to the Firth of Forth</li>
<li>A visit to the seabird centre where, amongst other things, I learned that gannets inhabit the Bass rock and that a gathering of gannets is called a <em>gannetry</em>!</li>
<li>Pretty good lil’ shops! I particularly enjoyed the Steampunk coffee shop which also houses the Orange Moon record store.</li>
<li>Enjoyed a pint at The Ship Inn and The Auld Hoose. It turns out that my friend Kris’s dad (who I knew pretty well) was a regular at the latter.</li>
<li>A nice <em>frutti de mare</em> pasta dinner at Bella Italia</li>
</ul>
<p>Next time I visit (hopefully with Clair and Rudy) I should go in summer so I can catch The Lobster Shack open! I’d also like to visit nearby Tantallon Castle.</p>
Getting started with Utopia Figma Plugins (Utopia Blog)2022-11-27T20:30:55Zhttps://fuzzylogic.me/posts/2022-11-27-getting-started-with-utopia-figma-plugins-utopia-blog/<p>Here’s another tool from the Utopia creators to assist with breakpoint-free fluid responsive design.</p>
<blockquote>
<p>Until now, the tooling for Utopia has been predominantly developer-focused, but we know that's only half the story. To start to address this, we've created a pair of Figma plugins to help designers set out Utopian project foundations.</p>
</blockquote>
<p>I also really like the idea of having three sets of type styles at both defined viewport sizes.</p>
<blockquote>
<p>We typically use a <em>Strong</em> style for headings and other text that we want to visually punctuate our designs. The <em>Prose</em> style is useful for longer-form text which might benefit from a larger, more relaxed line height. The <em>Default</em> style is a catch-all for other snippets of text in our designs, like a standlone link, a short piece of explainer text, or perhaps an image caption. The number and variety of styles required will vary depending on your design's purpose and style but these three serve as a reasonable starting point.</p>
</blockquote>
How to set up your Technics 1200 turntable (by Longbox Media on YouTube)2022-11-27T00:41:53Zhttps://fuzzylogic.me/posts/2022-11-27-how-to-set-up-your-technics-1200-turntable-by-longbox-media-on-youtube/<p>The best SL-1200/10 set-up video I’ve seen.</p>
<p>I especially like the section on testing for channel imbalance by playing a mono record (such as <a href="https://www.discogs.com/release/15752593-Nat-Birchall-meets-Al-Breadwinner-Upright-Living">Nat Birchall's Upright Living LP</a> and comparing the output meter for any differences between left and right, then untightening the relevant tonearm screws in order to make adjustments.</p>
A Long Time Coming - on the AbsoluteLee podcast2022-11-24T15:16:15Zhttps://fuzzylogic.me/posts/2022-11-24-a-long-time-coming-on-the-absolutelee-podcast/<blockquote>
<p>At the height of my playing career, David Baddiel wore blackface and put a pineapple on his head to mock me on national television every Friday night. While the chants have remained ever present, and David’s name has become synonymous with mine, it’s taken 25 years for us to finally meet face-to-face. In this episode, I talk with David about the impact his racist sketches had on me, my family and the wider community, and why allyship needs to become a bigger part of football.</p>
</blockquote>
<p>While watching David Baddiel's excellent <a href="https://www.channel4.com/programmes/david-baddiel-jews-dont-count">Jews Don't Count</a> documentary on Channel Four I was intrigued by the section in which he spoke to Jason Lee, leading me to seek out this podcast episode.</p>
<p>In the nineties at the height of “lads’ culture”, Baddiel and Frank Skinner essentially bullied and abused footballer Lee, mocking his appearance in particular.</p>
<p>This conversation, difficult as it sounded, is fascinating. It throws up so many moral ambiguities, such as whether or not Baddiel is a fit person to publicly campaign against racism, and related questions around acceptance, rehabilitation and moving on.</p>
<p>It also made me question my own prejudices and behaviours, past and present.</p>
<p>Most of all I was impressed by Jason Lee. His past treatment has meant that he and his family have had a lot to endure, but he speaks with such dignity, positivity and resolve.</p>
The anatomy of visually-hidden - TPGi2022-11-24T10:59:58Zhttps://fuzzylogic.me/posts/2022-11-24-the-anatomy-of-visuallyhidden-tpgi/<blockquote>
<p>This article is not about when or why you would use visually-hidden content. There’s a number of excellent articles that discuss these questions in detail, notably Scott O’Hara’s Inclusively Hidden. But most of them don’t go into much detail about the specific CSS involved — why do we use this particular pattern, with these specific properties? So today I’m going to dissect it, looking at each of the properties in turn, why it’s there, and why it isn’t something else.</p>
</blockquote>
<p>Relevant to <a href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/">How to hide elements on a web page</a>.</p>
<p>I also liked this nugget:</p>
<blockquote>
<p>it’s often called <code>.sr-only</code> (screen reader only, but that’s not a good name, because visually-hidden content is not just for screen readers).</p>
</blockquote>
Electronic Roots 01: The Story Of Axis, with Jeff Mills by OpenLab Radio (on SoundCloud)2022-11-21T16:30:06Zhttps://fuzzylogic.me/posts/2022-11-21-electronic-roots-01-the-story-of-axis-with-jeff-mills-by-openlab-radio-on-soundcloud/<p>Loved this thoughtful and insightful interview with Jeff Mills by <a href="https://twitter.com/mgoldenbarnes">Marcus Barnes</a>.</p>
<p>Among the highlights were Jeff’s thoughts on whether his music could viably still be described as “Detroit” given how long he’s lived away from the motor city, and also his reflections on the impact on his peer group of the 1980 film <a href="https://www.imdb.com/title/tt0080365/">American Gigolo</a>.</p>
Backhand topspin attack - Amateur vs Pro (Tom Lodziak on YouTube)2022-11-21T10:03:21Zhttps://fuzzylogic.me/posts/backhand-topspin-attack-amateur-vs-pro-tom-lodziak-on-youtube/<p>Here’s a lovely slow-mo comparison of Liam Pitchford’s backhand technique versus that of an amateur.</p>
<p>The main things I take from it are:</p>
<ul>
<li>his posture – really low with weight forward</li>
<li>how far in front of his body he strikes the ball – it’s way in front of his head and even in front of his non-playing hand, with impact at the back edge of the table</li>
<li>the bat angle at the start (forehand side facing ceiling like you’re holding a frying pan)</li>
<li>as he prepares, the bat’s left edge tilts up a bit and he gets slightly lower</li>
<li>elbow moves forward (helping him rotate wrist back) but only as far as to create a virtual parallel horizontal line with the table’s back edge. This is the perfect stopping point for wrist pivoting (whereas I’ve let the elbow go further forward which is unnatural)</li>
<li>uses wrist to bring bat tip way back to point back at his belly button – I think this greater “travel distance” might be crucial versus an amateur’s version of a wristy backhand</li>
<li>then there’s a little forearm forward movement and a <em>lot</em> of wrist rotation to get the bat to the impact point</li>
<li>stays low and on follow-through the bat only gets as high as his chin</li>
</ul>
Should I use the HTML title attribute?2022-11-16T10:43:06Zhttps://fuzzylogic.me/posts/should-i-use-the-html-title-attribute/<p>People have used the HTML title attribute to achieve a native “tooltip” effect for many years. However accessibility experts have recommended that we should avoid this practice, and here I summarise my research on the topic.</p>
<p>Renowned accessibility solutions provider <a href="https://www.tpgi.com/using-the-html-title-attribute/">The Paciello Group recommend the title attribute should almost always be avoided.</a> It causes problems for lots of different usage contexts (keyboard, touch device, screen readers). The only place where I can see that it is still helpful is on <code>iframe</code>. It <em>was</em> beneficial on form inputs in cases where a visible text label would be redundant and we want to provide our control with a programmatically associated label, however we now have <code>aria</code> attributes which do a better job.</p>
<p>So on anything other than <code>iframe</code> the <code>title</code> attribute is undesirable. To back this up, at work my team recently received the following accessibility feedback from <a href="https://tetralogical.com/">Tetralogical</a> when they reviewed one of our <code>table</code>s.</p>
<blockquote>
<p>The Edit and Delete links use the <code>title</code> attribute to provide additional context for each link. The <code>title</code> attribute can be unreliable (for example, in testing VoiceOver announces the title in French). Provide additional context using the <code>aria-describedby</code> attribute to reference the name or reference value of the item.</p>
</blockquote>
Forthcoming DJ gig on Radio Buena Vida 19/11/222022-11-13T15:26:49Zhttps://fuzzylogic.me/posts/forthcoming-dj-gig-on-radio-buena-vida-19-11-222/<p>I’ve been stockpiling good records for a while and it’s time they got an airing. I’ll be playing a few on <a href="https://buenavida.co.uk/">Radio Buena Vida</a>, Saturday 19/11 at 4–5pm. Tune in or even come hang out in the café, if you’re in the hood.</p>
<iframe title="Terry by Nahash" style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=2825939476/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/track=3333430384/transparent=true/" seamless=""><a href="http://firecrackerrecordings.bandcamp.com/album/firec027lp-the-sorrow-of-derdriu">Terry by Nahash</a></iframe>
The “how web requests work” interview question2022-11-08T09:12:33Zhttps://fuzzylogic.me/posts/interview-question-answer/<p>There’s a classic web developer interview question that goes something like this:</p>
<p>What happens when you type in “<a href="http://bbc.co.uk/">bbc.co.uk</a>” into a browser? Describe the journey that results in you seeing a page.</p>
<p>You could answer it like this:</p>
<p>Your browser sends an HTTP request which gets routed through a local modem/router then gets sent to a nameserver. That nameserver routes the request to the correct IP address, which will resolve to some sort of web server. That server will serve up either some static files, or run some backend code in order to generate a resource (probably an html page). When the HTML page is returned, your browser will parse it, which will likely generate more requests, and the cycle will repeat.</p>
<p>To do:</p>
<ul>
<li>add something about HTTPS</li>
<li>add more about the front-end aspects: DOM, CSSOM, Accessibility tree, render blocking resources etc</li>
</ul>
<h2 id="references%3A" tabindex="-1">References: <a class="direct-link" href="https://fuzzylogic.me/posts/interview-question-answer/#references%3A" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://benmccormick.org/2017/07/24/my-favorite-interview-question/">My favorite interview question</a>, by Ben McCormick</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work">How browsers work</a>, on MDN</li>
</ul>
Nordhealth’s Design System2022-11-06T11:20:24Zhttps://fuzzylogic.me/posts/nordhealth-s-design-system/<p>There’s so much to admire in Nord Health’s Design System and specifically its reference website.</p>
<p>I love the way it looks and is organised.</p>
<p>There’s a fantastic, practical <a href="https://nordhealth.design/accessibility-checklist/">accessibility checklist</a>.</p>
<p>They document their <a href="https://nordhealth.design/naming/">naming conventions</a> and the rationale behind them.</p>
<p>They were a trailblazer in <a href="https://nordhealth.design/web-components/">adopting web components</a> and I love the docs explaining why.</p>
<blockquote>
<p>We’ve chosen to use Web Components because there is a strong requirement for Nord to be used in many different contexts and with varying technologies — from static HTML pages to server-rendered apps, through to single page applications authored with frameworks such as <a href="https://reactjs.org/">React</a> and <a href="https://vuejs.org/">Vue</a>. Web Components work great for Nord, because they:</p>
<ul>
<li>Are tech-agnostic instead of tech-specific</li>
<li>Future proof our system with Web Standards</li>
<li>Allow us to use any framework or no framework at all</li>
<li>Provide great encapsulation for styles and functionality</li>
</ul>
</blockquote>
<p>Lastly <a href="https://nordhealth.design/components/">their components</a> look great and show a really high-level of front-end and accessibility literacy.</p>
Full disclosure2022-11-05T10:25:28Zhttps://fuzzylogic.me/posts/full-disclosure/<p>Whether I’m thinking about inclusive hiding, hamburger menus or web components one UI pattern I keep revisiting is the <em>disclosure widget</em>. Perhaps it’s because you can use this small pattern to bring together so many other wider aspects of good web development. So for future reference, here’s a braindump of my knowledge and resources on the subject.</p>
<p>A disclosure widget is for collapsing and expanding something. You might alternately describe that as hiding and showing something. The reason we collapse content is to save space. The thinking goes that users have a finite amount of screen estate (and attention) so we might want to reduce the space taken up by secondary content, or finer details, or repeated content so as to push the page’s key messages to the fore and save the user some scrolling. With a disclosure widget we collapse detailed content into a smaller snippet that acts as a button the user can activate to expand the full details (and collapse them again).</p>
<p>Adrian Roselli’s article <a href="https://adrianroselli.com/2020/05/disclosure-widgets.html">Disclosure Widgets</a> is a great primer on the available native and custom ARIA options, how to implement them and where each might be appropriate. Adrian’s article helpfully offers that a disclosure widget (the custom ARIA flavour) can be used as a base in order to achieve some other common UI requirements so long as you’re aware there are extra considerations and handle those carefully. Examples include:</p>
<ul>
<li>link and disclosure widget navigation</li>
<li>table with expando rows</li>
<li>accordion</li>
<li>hamburger navigation</li>
<li>highly custom <code>select</code> alternatives when <code>listbox</code> is innapropriate because it needs to include items that do not have the <code>option</code> role</li>
<li>a toggle-tip</li>
</ul>
<p>Something Adrian addresses (and I’ve previously written about) is the question around <a href="https://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/">for which collapse/expand use cases we can safely use the <em>native</em> <code>details</code> element</a>. There’s a lot to mention but since I’d prefer to present a simple heuristic let’s go meta here and use a <code>details</code>:</p>
<details>
<summary>Use <code>details</code> for basic narrative content and panels but otherwise use a DIY disclosure</summary>
<p>It’s either a bad idea or at the very least “challenging” to use a native `details` for:</p>
<ul>
<li>a hamburger menu</li>
<li>an accordion</li>
</ul>
<p>In terms of styling terms it’s tricky to use a `details` for:
</p><ul>
<li>a custom appearance</li>
<li>animation</li>
</ul>
<p>The above styling issues are perhaps not insurmountable. It depends on what level of customisation you need.</p>
<p>Note to self: add more detail and links to this section when I get the chance.</p>
</details>
<p>I’ve also noticed that <a href="https://codepen.io/aardrian/pen/dyowpJj?editors=0100">Adrian has a handy pen combining code for numerous disclosure widget variations</a>.</p>
<p>Heydon Pickering’s <a href="https://inclusive-components.design/collapsible-sections/">Collapsible sections</a> on Inclusive Components is excellent, and includes consideration of progressive enhancement and an excellent web component version. It’s also oriented toward <em>multiple</em> adjacent sections (an accordion although it doesn’t use that term) and includes fantastic advice regarding:</p>
<ul>
<li>appropriate markup including screen reader considerations</li>
<li>how best to programmatically switch <em>state</em> (such as open/closed) within a web component</li>
<li>how to make that state accessible via an HTML attribute on the web component (e.g. <code><toggle-section open=true></code>)</li>
<li>how that attribute is then accessible outside the component, for example to a button and script that collapses and expands all sections simultaneously</li>
</ul>
<p>There’s my <a href="https://codepen.io/fuzzylogicx/pen/YzQjyoj">DIY Disclosure widget</a> demo on Codepen. I first created it to use as an example in a talk on <a href="https://fuzzylogic.me/posts/my-talk-hiding-elements-on-the-web-for-freeagent-s-tech-blog/">Hiding elements on the web</a>, but since then its implementation has taken a few twists and turns. In its latest incarnation I’ve taken some inspiration from the way Manuel Matuzovic’s <a href="https://fuzzylogic.me/posts/2022-09-12-building-the-main-navigation-for-a-website-on-webdev/">navigation tutorial</a> uses a <code>template</code> in the markup to prepare the “hamburger toggle” button.</p>
<p>I’ve also been reflecting on how the <code>hidden</code> attribute’s boolean nature is ideal for a toggle button in theory – it’s semantic and therefore programattically conveys state – but how hiding with CSS can be more flexible, chiefly because <code>hidden</code> (like CSS’s <code>display</code>) is not animatible. If you hide with CSS, you could opt to use <code>visibility: hidden</code> (perhaps augmented with <code>position</code> so to avoid taking up space while hidden) which similarly hides from everyone in terms of accessibilty.</p>
<p>As it happens, <a href="https://fuzzylogic.me/posts/my-first-web-component-a-disclosure-widget/">the first web component I created was a disclosure widget</a>. It could definitely be improved by some tweaks and additions along the lines of Heydon Pickering’s web component mentioned above. I’ll try to do that soon.</p>
<h2 id="troubleshooting" tabindex="-1">Troubleshooting <a class="direct-link" href="https://fuzzylogic.me/posts/full-disclosure/#troubleshooting" aria-hidden="true">#</a></h2>
<p>For some disclosure widget use cases (such as a custom link menu often called a <em>Dropdown</em>) there are a few events that typically should collapse the expanded widget. One is the escape key. Another is when the user moves focus outside the widget. One possible scenario is that the user might activate the trigger button, assess the expanded options and subsequently decide none are suitable and move elsewhere. The act of clicking/tapping elsewhere should collapse the widget. However there’s a challenge. In order for the widget to be able to fire <code>unfocus</code> so that an event listener can act upon that, it would have to be focused in the first place. And in Safari – unlike other browsers – <a href="https://zellwk.com/blog/inconsistent-button-behavior/">buttons do not automatically receive focus when activated</a>. (I think Firefox used to be the same but was updated.) The workaround is to set focus manually via <code>focus()</code> in your click event listener for the trigger button.</p>
Choosing a date - we want to know your use cases (a discussion re. gov.uk design system)2022-11-02T09:59:26Zhttps://fuzzylogic.me/posts/2022-11-02-choosing-a-date-we-want-to-know-your-use-cases-a-discussion-re-govuk-design-system/<blockquote>
<p>We want to find out if adding a 'date picker' component to the Design System is a good idea.</p>
</blockquote>
<blockquote>
<p>We're currently looking for: examples of date pickers in services: screenshots, prototypes, links to live services; use cases: explanations of why a 'date picker' was used in a service instead of a 'date input', or something else; research: how well 'date pickers' tested with users to complete different tasks.</p>
</blockquote>
<p>This discussion thread will be really helpful for everyone attempting to create an accessible Date Picker.</p>
How to build an accesssible autocomplete2022-10-30T13:03:26Zhttps://fuzzylogic.me/posts/how-to-build-an-accesssible-autocomplete/<p>At work there are plans afoot to reconcile various differing <em>Autocomplete</em> implementations into a single, reusable component. So far there’s been a written audit presenting all instances and how they differ in functional and technical respects. There’s also been design work to identify visual commonalities and avoid future inconsistencies. I’d now like to add another perspective: an investigation into which HTML materials and (if necessary) ARIA supplements are appropriate to ensure we build something accessible and resilient.</p>
<p>My experience is that to achieve the right result, HTML semantics and related concerns can’t just follow and bend to spec and visual design goals, but rather must <em>influence</em> the setting of those goals.</p>
<p>I’ll flesh out my findings in due course, but for now here are the key resources I’ve identified and plan to dig deep into.</p>
<p><a href="https://adrianroselli.com/2020/03/stop-using-drop-down.html">Adrian Roselli’s article Stop Using ‘Drop-down’</a>. To summarise the options of interest:</p>
<ul>
<li><em>ARIA Listbox</em> lets you create a DIY thing that has the same roles and semantics as a <code><select></code> but where you have greater stylistic control. There are different ways to implement a Listbox.</li>
<li><code>Datalist</code> is the native HTML version of a <a href="https://en.wikipedia.org/wiki/Combo_box">combo box</a>. A combo box is essentially a <code><select></code> with a text field. <code>Datalist</code> is announced by screen readers in different ways but as far as I can gather these are quirky rather than terrible. I found <a href="https://twitter.com/IMAC2/status/1383384601192656897">a nice Twitter thread on DataList</a> which not only shows off its function but also includes <a href="https://twitter.com/patrick_h_lauke/status/1383511763417649152">a promising accessibility-related comment</a> from Patrick H Lauke of Tetralogical. The drawback, because <code>Datalist</code> is native HTML, is that its options are not stylelable.</li>
<li><em>ARIA Combobox</em> is a pattern that combines ARIA <code>combobox</code>, <code>textbox</code> and <code>listbox</code> roles, and the benefit it brings is to allow a level of custom design that you couldn’t achieve with <code>Datalist</code>.</li>
<li><code>Autocomplete</code> (not to be confused with the HTML <code>autocomplete</code> <em>attribute</em>) describes a control which provides users with suggestions that may not be available in the DOM already… for example when you fetch options via Ajax in reponse to what the user types.</li>
</ul>
<p>With regard to Autocomplete, Adrian points to <a href="https://adamsilver.io/blog/building-an-accessible-autocomplete-control/">Adam Silver’s <em>Building an accessible autocomplete control</em></a>.</p>
<p>And for advice on whether or not to go with a native select or a custom control, and how best to implement listbox and combobox if that’s your choice, Adrian points to the following resources from Sarah Higley:</p>
<ul>
<li><a href="https://www.24a11y.com/2019/select-your-poison-part-2/#select-poison-recommendations"><code><select></code> your poison part 2</a> (see the <em>Roll your own</em> section at bottom)</li>
<li><a href="https://codepen.io/smhigley/pen/gObMVzv">Recommended Combobox Patterns</a> pen</li>
</ul>
<p>I also see that <a href="http://gov.uk/">GOV.UK</a> have marked a possible <em>Autocomplete</em> component as one of their <a href="https://design-system.service.gov.uk/community/upcoming-components-patterns/">next priorities</a> to review. Their <a href="https://github.com/alphagov/govuk-design-system/discussions/2374">Autocomplete discussion thread</a> includes examples and research and will be really helpful.</p>
Using schema.org to describe your content2022-10-30T11:25:56Zhttps://fuzzylogic.me/posts/providing-additional-semantics-using-schema.org/<p>I’ve been using <a href="https://schema.org/">schema.org</a> for a few years now, but haven’t yet logged any notes and usage advice. <a href="http://schema.org/">Schema.org</a> gives websites a practical, structured data approach for communicating the meaning of their content in finer detail than they could with native HTML alone. Google etc can then parse this and use it in their interfaces to offer users a richer view of your data.</p>
<p><a href="http://schema.org/">Schema.org</a> lets you pick from different types of <em>properties</em> for describing your content, such as book, person, place or event. Alternatively a more generic article you might use <em>BlogPosting</em>.</p>
<p><a href="http://schema.org/">Schema.org</a> is still current and celebrated its ten year anniversary in 2021.</p>
<p>One bit of troubleshooting advice worth mentioning is to validate your page using <a href="https://validator.schema.org/">validator.schema.org</a>. Thanks to <a href="https://liamnugent.me/">Liam</a> who recently pointed out a schema issue on my site, which reminded me I need to use the validator any time I make changes to the relevant markup.</p>
The organisation of work versus the job itself2022-10-26T07:55:36Zhttps://fuzzylogic.me/posts/the-organisation-of-work-versus-the-job-itself/<p>Here’s a half-formed thought (the sort of thing personal websites that nobody else reads are perfect for). As a web developer, something I’ve noticed when interviewing candidates and hearing how they do things, or when I myself am being assessed in expectations reviews is that our industry seems obsessed with discussing <em>the organisation of work</em>. You know – PR review protocol, agile ceremonies, organising a Trello board, automation, linters. All of which is really important, of course. But the amount of airtime that gets leaves me frustrated. What about the <em>actual job</em>?</p>
<p>Are responsive strategy, web typography, layout, interactive JS components, animation (to name but a few very high-level topics) not interesting, complex and impactful enough as to warrant a higher percentage of the conversation? I want an insight into other folks’ knowledge of and opinions on how best to build things, and feel it gets relegated behind organisational topics.</p>
<p>Or do people just see the nitty-gritty stuff as the domain of enthusiasts on Twitter and personal blogs, or as “implementation details” that are secondary to the organisation of something – anything – that will “get the job done”?</p>
<p>As I say, a half-formed thought and probably just reveals my leanings! But writing it helps me gather my thoughts even if I eventually decide I’m in the wrong.</p>
Let's talk about web components (by Brad Frost)2022-10-23T20:09:22Zhttps://fuzzylogic.me/posts/2022-10-23-lets-talk-about-web-components-or-brad-frost/<p>Brad breaks down the good, bad and ugly of web components but also makes a compelling argument that we should get behind this technology.</p>
<blockquote>
<p>I come from the Zeldman school of web standards, am a strong proponent of progressive enhancement, care deeply about accessibility, and want to do my part to make sure that the web lives up to its ideals. And I bet you feel similar. It’s in that spirit that I want to see web components succeed. Because web components are a part of the web!</p>
</blockquote>
<p>I’m with you, Brad. I just need to find practical ways to make them work.</p>
WebC2022-10-23T16:28:08Zhttps://fuzzylogic.me/posts/webc/<p>WebC, the latest addition to the <a href="https://www.11ty.dev/">Eleventy</a> suite of technologies, is focused on making <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components">Web Components</a> easier to use. I have to admit, it took me a while to work out the idea behind this one, but I see it now and it looks interesting.</p>
<p>Here are a few of the selling points for WebC, as I see them.</p>
<p>With WebC, web components are the consumer developer’s authoring interface. So for example you might add a badge component into your page with <code><my-badge text='Lorem ipsum'></my-badge></code>.</p>
<p>Using web components is great – especially for Design Systems – because unlike with proprietary component frameworks, components are not coupled to a single technology stack but rather are platform and stack-agnostic, meaning they could be reused across products.</p>
<p>From the component creator perspective: whereas normally web components frustratingly require writing accompanying JavaScript and depending on JavaScript availability even for “JavaScript-free” components, with WebC this is not the case. You can create “HTML-only” components and rely on them to be rendered to screen. This is because WebC takes your <code>.webc</code> component file and compiles it to the simplest output HTML required.</p>
<p>WebC is progressive enhancement friendly. As mentioned above, your no-JS HTML foundation will render. But going further, you can also colocate your foundational baseline beside the scripts and CSS that enhance it within the same file.</p>
<p>This ability to write components within a single file (rather than separate template and script files) is pretty nice in general.</p>
<p>There are lots of other goodies too such as the ability to scope your styles and JavaScript to your component, and to set styles and JS to be aggregated in such a way that your layout file can optionally load only the styles and scripts required for the components in use on the current page.</p>
<p>Useful resources:</p>
<ul>
<li><a href="https://www.11ty.dev/docs/languages/webc/">WebC docs</a></li>
<li><a href="https://www.youtube.com/watch?v=X-Bpjrkz-V8"><em>Crash course</em> video tutorial</a></li>
<li><a href="https://www.youtube.com/watch?v=p0wDUK0Z5Nw">Progressively enhanced interactive components video tutorial</a></li>
</ul>
The ARIA presentation role2022-10-23T09:25:21Zhttps://fuzzylogic.me/posts/the-aria-presentation-role/<p>I’ve never properly understood when you would need to use the ARIA <code>presentation</code> role. This is perhaps in part because it is often used inappropriately, for example in situations where <code>aria-hidden</code> would be more appropriate. However I think the penny has finally dropped.</p>
<p>It’s fairly nuanced stuff so I’ll forgive myself this time!</p>
<p>You might use <code>role=presentation</code> in JavaScript which progressively enhances a basic JS-independent HTML foundation into a more advanced JS-dependent experience. In such cases you might want to reuse the baseline HTML but remove semantics which are no longer appropriate.</p>
<p>As an example, Inclusive Components <a href="https://inclusive-components.design/tabbed-interfaces/">Tabbed Interfaces</a> starts with a Table of Contents marked up as an unordered list of links. However in enhanced mode the links take on a new role as tabs in a <code>tablist</code> so <code>role=presentation</code> is applied to their containing <code><li></code> elements so that the tab list is announced appropriately and not as a <em>plain</em> list.</p>
Thoughts on HTML over the wire solutions2022-10-22T09:16:06Zhttps://fuzzylogic.me/posts/thoughts-on-html-over-the-wire-solutions/<p><a href="https://twitter.com/mxbck/status/1581595524180094977">Max Böck just tweeted his excitement about htmx</a>:</p>
<blockquote>
<p>htmx (and similar "HTML over the wire" approaches) could someday replace Javascript SPAs. Cool to see a real-world case study on that, and with promising results</p>
</blockquote>
<p>There’s similar excitement at my place of work (and among the Rails community in general) about <a href="https://turbo.hotwired.dev/">Turbo</a>. It promises:</p>
<blockquote>
<p>the speed of an SPA without having to write any JS</p>
</blockquote>
<p>These new approaches are attractive because they let us create user interfaces that update the current page <em>sans reload</em> – usually communicating with the server to get swap-in content or update the database – but by writing HTML rather than JavaScript. Developers have long wished for HTML alone to handle common interactive patterns so a set of simple, declarative conventions really appeals. Writing less JavaScript feels good for performance and lightening maintenance burden. Furthermore the Single Page App (SPA) approach via JS frameworks like React and Vue is heavier and more complicated than most situations call for.</p>
<p>However I have some concerns.</p>
<p>I’m concerned about the “no javascript” language being used, for example in articles titled <a href="https://evilmartians.com/chronicles/hotwire-reactive-rails-with-no-javascript">Hotwire: reactive Rails with no JavaScript</a>. Let’s be clear about what Turbo and htmx are in simple material terms. As Reddit user nnuri puts it in <a href="https://www.reddit.com/r/rails/comments/tx8lj7/does_hotwire_have_an_a11y_commitment/">do Hotwire and htmx have a commitment to accessibility?</a> the approach is based on:</p>
<blockquote>
<p>a JavaScript library in the client's browser that manipulates the DOM.</p>
</blockquote>
<p>Your UI that uses htmx or Turbo is dependent on that JS library. And JS is the most brittle part of the stack. So you need to think about resilience and access. The <a href="https://htmx.org/docs/#progressive_enhancement">htmx docs has a section on progressive enhancement</a> but I’m not convinced it’s part of the design.</p>
<p>Secondly if you have client-side JS that changes content and state, that brings added accessibility responsibilities. When the content or state of a page is changed, you need to convey this programatically. We normally need to handle this in JavaScript. Do these solutions cover the requirements of accessible JS components, or even let you customise them to do add the necessary state changes yourself? For example <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">when replacing HTML you need to add aria-live</a> (see also <a href="https://tink.uk/accessible-forms-with-aria-live-regions/">Léonie Watson on accessible forms with ARIA live regions</a>).</p>
<p>Another concern relates to user expectations. Just because you <em>can</em> do something doesn’t mean you should. For example, links should not be used to do the job of a <code>button</code>. If you do, they need <code>role=button</code> however this is inadvisable because you then need to <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role#description">recreate (and will likely miss) the other features of a button</a>, and will also likely confuse people due to mismatches between perceived affordance and actual functionality. Additionally, as Jeremy Keith has written, <a href="https://adactio.com/journal/17768">links should not delete things</a>.</p>
<p>In general I feel the message of the new <em>HTML over the wire</em> solutions is very weighted toward <em>developer experience</em> but doesn’t make <em>user experience</em> considerations and implications clear. Due to <a href="https://github.com/bigskysoftware/htmx/issues/731">unanswered questions regarding accessibility</a> I worry that firstly they’re not natively mature in their understanding and approach on that front, and secondly that their framing of benefits is likely to make accessibility ignored due to engineers thinking that they can totally rely on the library.</p>
<p>I’d be really pleased if my concerns could be allayed because in general I like the approach.</p>
<h2 id="update-30%2F1%2F%2F22" tabindex="-1">Update 30/1//22 <a class="direct-link" href="https://fuzzylogic.me/posts/thoughts-on-html-over-the-wire-solutions/#update-30%2F1%2F%2F22" aria-hidden="true">#</a></h2>
<p>I decided to revisit a book I read back in 2007 – <a href="https://bulletproofajax.com/">Jeremy Keith’s <em>Bulletproof Ajax</em></a>. I had forgotten this, but it actually contains a section titled “Ajax and accessibility”. It acknowledged that reconciling the two is challenging and despite listing ideas for mitigating issues, it admitted that the situation was not great. However since 2007 – specifically since around 2014 – WAI-ARIA has been a completed W3C recommendation and provides a means of making web pages more accessible, particularly when dealing with dynamic content.</p>
<p>I don’t often have cause to use more than a few go-to ARIA attributes, however here’s my understanding of how you might approach making Ajax-driven content changes accessible by using ARIA.</p>
<p>To do: write this section.</p>
<p>References:</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">ARIA Live Regions on MDN</a></li>
</ul>
Accessibility drives aesthetics by Alex Chen (on UX Collective)2022-10-19T19:43:26Zhttps://fuzzylogic.me/posts/2022-10-19-accessibility-drives-aesthetics-paying-homage-to-oxo-eames-govuk-or-by-alex-chen-on-ux-collective/<p>This article is a couple of years old but just popped up on my radar again. UX Designer Alex Chen asserts that arguments which pit accessibility against aesthetics create a dangerous false equivalence… and I agree.</p>
<blockquote>
<p>The article claims that if we are “too accessible” we will meet the needs of the minority but end up hurting those of the majority. This creates a false equivalence between having legitimate access needs and having a preference for a certain aesthetic.</p>
</blockquote>
<p>Alex goes on to praise examples where accessibility is used to drive aesthetics – such as the Eames leg splint and <a href="http://gov.uk/">GOV.UK</a>’s design system – as opposed to considering the two ideals opposites or that one needs sacrificed for the other.</p>
inline-block versus flexbox for horizontal arrangements2022-10-17T13:31:09Zhttps://fuzzylogic.me/posts/inline-block-versus-flexbox-for-horizontal-arrangements/<p>Something I’ve found interesting while reviewing recent code test submissions (within job applications) at work is that more developers than I’d expect still use <code>display: inline-block</code> when they need to lay out multiple elements horizontally such as the items in a navigation menu. It’s interesting because Flexbox – which has now been around for almost 10 years – gives you a modern, purpose-built solution to that.</p>
<p>Of course, there is no <em>crime</em> in taking the <code>inline-block</code> approach. It’s an option. And I did take a moment just to challenge my assumptions. But having given it a little thought, I am pretty convinced that Flexbox is the better approach and so I think their choice is worth a query.</p>
<p>Here’s why I think Flexbox is much better:</p>
<ol>
<li>Modern CSS layout is <em>purpose-built</em> for constructing multi-element layouts. Older methods were lacking, quirky and slightly hacky. Using (and knowing to use) purpose-built tools is generally a good thing for reliability, predictability and scalability.</li>
<li>Modern CSS layout provides more <em>control</em>, because it’s fundamentally different. You get a parent context (the flex container or grid) that lets you style the <em>context</em> (with <code>gap</code>, for example). We didn’t have this before.</li>
<li>Styling a context rather than individual items plays better with modern component-oriented organisation and ideas. It‘s good to keep components <a href="https://mxstbr.com/thoughts/margin/">encapsulated and context-agnostic</a>, <a href="https://every-layout.dev/">handing off layout to separate, fit-for-purpose tools</a>.</li>
<li>Flexbox is built for <em>responsiveness</em>, i.e. built for the modern era. <code>inline-block</code> was not.</li>
<li>the default <code>align-items:stretch</code> means that items laid out in a row are automatically full parent-height which is often desirable for larger touch targets and achieving hover styles.</li>
<li><code>inline-block</code> retains some of the properties of <code>inline</code> that are undesirable for this type of use-case. Who can be bothered with whitespace in the code appearing on the screen, or having to work with <code>vertical-align</code> when you don’t need to.</li>
</ol>
<p>I also don’t see any reason to <em>not</em> use Flexbox. It’s conventional (see for example navigation menus on <a href="https://www.bbc.co.uk/">BBC</a>, <a href="https://tetralogical.com/">Tetralogical</a>), recommended by CSS experts (Rachel Andrew, Jen Simmons etc), performant and well-supported by browsers. You are not going “fancy”, “cutting edge” or “overkill” by using Flexbox. For the “horizontal menu” use case, it’s simply a more suitable choice than the older alternatives.</p>
<p>Related: Chris Coyier’s article <a href="https://css-tricks.com/when-do-you-use-inline-block/">When do you use inline block</a> is an excellent investigation into whether any necessary uses for <code>inline-block</code> remain. I reserve the right to change my mind on this, but aside from the “apply <code>transform</code> to an inline element” use case I can’t really see any that have not now been superseded.</p>
Should I use a button or a link?2022-10-10T13:41:12Zhttps://fuzzylogic.me/posts/should-i-use-a-button-or-a-link/<p>I’ve written previously about the <a href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/">important differences between buttons and links</a>. While reviewing some “component refresh” design mocks at work yesterday I noticed the designs were a bit unclear in this regard so I sent the designers a little decision-tree, which I’m noting here for future reference.</p>
<p>It’s important both for our users and for us as practitioners to distinguish between links (the <code><a></code> element) and the <code><button></code> element. The reason I push this is because they’re fundamentally different functionally, which has important usability implications. Users expect to use mouse, keyboard, browser back-button and assistive tech differently for links than they do for <code><button></code>s. And if they can’t visually distinguish one from the other, they’ll try things they expect to work then get confused when they don’t work.</p>
<p>I think this is an area where <em>design</em> and <em>materials</em> can’t be considered separately and need a joined-up approach.</p>
<p>Here’s a flow I hope is helpful.</p>
<p>Ask: does it…</p>
<ol>
<li><em>take the user to another page</em>? Then it’ll be a link – the <code><a></code> (anchor) element.</li>
<li><em>cause something to change on the current page</em>, or <em>submit a form</em>? Then it’ll be a button – i.e. the <code><button></code> element.</li>
</ol>
<p>If it’s a link (<code><a></code>):</p>
<ul>
<li>it should be underlined so people know it’s a link</li>
<li>it should have a hover state, for example stay underlined but change colour</li>
<li>in cases where it’s a CTA you might <em>choose</em> to design it to look button-like and remove some standard link affordances. Just be aware you’re only “calling” it a button. In real user-experienced terms, it’s still a link.</li>
<li>it does not natively have a disabled state. We shouldn’t be disabling links.</li>
</ul>
<p>If it’s a button (<code><button></code>):</p>
<ul>
<li>it should look like a button, i.e. like a pill or rectangle</li>
<li>It should <em>not look like a link</em> – that’d confuse users into thinking it takes them to another page.</li>
<li>So it shouldn’t be underlined by default or on hover. It should have some other hover state.</li>
</ul>
<h2 id="testing-the-decision-tree" tabindex="-1">Testing the decision tree <a class="direct-link" href="https://fuzzylogic.me/posts/should-i-use-a-button-or-a-link/#testing-the-decision-tree" aria-hidden="true">#</a></h2>
<p>Let’s take the example of a control for launching a modal dialogue.</p>
<p>The obvious choice is a button, because the control causes something to change on the current page. In this case it causes a dialogue to appear on the current page.</p>
<p>Some might argue that it could be a link. This is usually influenced by the fact that dialogues are often (perhaps inadvisably) used as a kind of “fake page”. And to get someone to a “page” we use a link, right? Advocates of the link option might also have progressive enhancement in mind. If they present a link either to a named fragment further down the page or to a separate page, that offers a resilient baseline experience regardless of whether or not JavaScript is available. The idea is that they also have JavaScript to enhance the link when the user’s environment supports it, perhaps adding <code>role=button</code>.</p>
<p>However a <code>button</code> is the more accessible and user-friendly approach for launching the modal.</p>
<ul>
<li><a href="https://stackoverflow.com/questions/38594369/is-it-more-accessible-to-use-a-button-or-a-to-open-close-a-modal">Adrian Roselli on stackoverflow</a></li>
<li><a href="https://twitter.com/aardrian/status/1322160454723129345">Adrian Roselli conversation with Jeremy Keith</a></li>
<li><a href="https://twitter.com/aardrian/status/1321947480112680960">Other Adrian Roselli musings on Jeremy’s post</a></li>
<li>Chris Ferdinandi on <a href="https://gomakethings.com/progressively-enhancing-a-link-into-a-button-with-vanilla-javascript/">a progressive enhancement approach which replaces a link with a button</a></li>
</ul>
Better accessible names | hidde.blog2022-10-02T00:03:28Zhttps://fuzzylogic.me/posts/2022-10-02-better-accessible-names-or-hiddeblog/<p>Accessible names are used by assistive technologies to refer to elements on a web page. Hidde tells us how to word them so that they are more useful.</p>
<blockquote>
<p>Because of how we use accessible names, we want to keep them functional and avoid naming controls after what they look like. Ideally, you do this in the imperative form, that makes it easiest to quickly grasp what a thing is going to do.</p>
</blockquote>
<p>My summary of Hidde’s top tips is:</p>
<ul>
<li>Name after function rather than form (“Open navigation” over “Hamburger”)</li>
<li>Put the most unique part first as this makes it more easy to distinguish between elements (so “Midnight Marauders - Album” rather than “Album - Midnight Marauders”)</li>
<li>Be concise – keep a name to the most important 1-3 words</li>
<li>No roles as part of the name (for example don’t include the word ‘button’ or <code>nav</code>. The browser already handles this part so it’d be redundant and annoying)</li>
<li>Start names with a capital letter and don't end with a full stop, because a name is not a sentence</li>
<li>Avoid ARIA if you can just use good element text content</li>
</ul>
Using the :has pseudo-class for real2022-09-28T14:13:39Zhttps://fuzzylogic.me/posts/using-the-has-pseudo-class-for-real/<p>By day I’m currently working on our Design System’s <em>Table</em> component. In order to achieve a design spec where the table has no bottom-border I needed to set:</p>
<ol>
<li>all cells in the final row of the <code><tfoot></code> to have no bottom-border; but also</li>
<li>if there is no <code><tfoot></code> then set all cells in the final row of the <code><tbody></code> to have no bottom-border.</li>
</ol>
<p>Modern CSS’s support for writing selectors which traverse the DOM <em>up, down and sideways</em> is pretty amazing here.</p>
<p>I’ve gone with:</p>
<pre><code>tfoot > :last-child td,
tbody:not(:has(+ tfoot)) > :last-child td {
border-bottom-width: 0;
}
</code></pre>
<p><em>(Some BEM stuff renamed for brevity but that’s the gist of it)</em></p>
<p>In the past we’ve had to bloat the backend layer with complex and awkward logic that adds “convenience classes” like <code>.fe-Table-bodyLastRow</code> but <a href="https://shoptalkshow.com/520/#t=30:35">as Eric Meyer has been saying</a> <code>:has()</code> in particular is going to remove the need for those convenience classes.</p>
<p>Hat-tip to Jhey Tompkins for <a href="https://fuzzylogic.me/posts/2022-08-08-has-the-family-selector-chrome-developers-blog/">his excellent recent article on :has</a> which was a great help.</p>
How to Fix Common iOS Accessibility Issues | Deque2022-09-24T17:20:33Zhttps://fuzzylogic.me/posts/2022-09-24-how-to-fix-common-ios-accessibility-issues-or-deque/<p>Although I don’t work on native apps, I’ve recently been wondering about how accessibility considerations for them compare to those for websites. So this is a timely and useful reference.</p>
<blockquote>
<p>iOS provides a lot of accessibility behavior for free, so it’s a great start to making a mobile application accessible. Unfortunately, accessibility is more complicated than the iOS behavior can address, and using only default behavior can actually cause the app to have additional issues.</p>
</blockquote>
Tabs: truth, fiction and practical measures2022-09-22T09:34:23Zhttps://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/<p>My colleague Anda and I just had a good conversation about tabs, and specifically the company’s tabs component. I’ve mentioned before that our tabs are unconventional and potentially confusing, and Anda was interested to hear more.</p>
<h2 id="what%E2%80%99s-the-purpose-of-a-tabbed-interface%3F" tabindex="-1">What’s the purpose of a tabbed interface? <a class="direct-link" href="https://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/#what%E2%80%99s-the-purpose-of-a-tabbed-interface%3F" aria-hidden="true">#</a></h2>
<p>A tabbed interface is a space-saving tool for collapsing parallel content into panels, with one panel visible at a time but all accessible on-demand. While switching between tab panels the user is kept within the same wider context i.e. the same page, rather than being moved around.</p>
<h2 id="conventional-tabbed-interfaces" tabindex="-1">Conventional tabbed interfaces <a class="direct-link" href="https://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/#conventional-tabbed-interfaces" aria-hidden="true">#</a></h2>
<p>Here are some great examples of <em>tabs</em> components.</p>
<ul>
<li><a href="https://inclusive-components.design/tabbed-interfaces/">Inclusive Components – Tabbed Interfaces</a></li>
<li><a href="https://design-system.service.gov.uk/components/tabs/">Tabs component in GOV.UK Design System</a></li>
<li><a href="https://adrianroselli.com/2013/02/aria-tabs.html">ARIA Tabs by Adrian Roselli</a></li>
</ul>
<p>Tabs are a device intended to improve content density. They should deliver a <em>same-page experience</em>. Activating a tab reveals its corresponding tab panel. Ideally the approach employs progressive enhancement, starting as a basic Table of Contents. There’s quite a lot of advanced semantics, state and interactivity under the hood.</p>
<h2 id="faux-tabs" tabindex="-1">Faux tabs <a class="direct-link" href="https://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/#faux-tabs" aria-hidden="true">#</a></h2>
<p>But in our Design System at work, ours are currently just the “tabs” with no tab panels, and each “tab” generally points to <em>another page</em> rather than somewhere on the same page. In other words it’s a navigation menu made to look like a tabbed interface.</p>
<p>I’m not happy with this from an affordance point of view. Naming and presenting something as one thing but then having it function <em>differently</em> leads to usability problems and communication breakdowns. As the Inclusive Components Tabbed Interfaces page says:</p>
<blockquote>
<p>making the set of links in site navigation appear like a set of tabs is deceptive: A user should expect the keyboard behaviors of a tabbed interface, as well as focus remaining on a tab in the current page. A link pointing to a different page will load that page and move focus to its document (body) element.</p>
</blockquote>
<h2 id="confused-language-causes-problems" tabindex="-1">Confused language causes problems <a class="direct-link" href="https://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/#confused-language-causes-problems" aria-hidden="true">#</a></h2>
<p>One real-life problem with our tabs is that they have been engineered as if they are conventional tabs, however since the actual use case is often <em>navigation</em> the semantics are inappropriate.</p>
<p>We currently give each “tab” <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role">the ARIA <code>tab</code> role</a>, defined as follows:</p>
<blockquote>
<p>The ARIA <code>tab</code> role indicates an interactive element inside a <code>tablist</code> that, when activated, displays its associated <code>tabpanel</code>.</p>
</blockquote>
<p>But <em>our tabs</em> have no corresponding <code>tabpanel</code>; they don’t use JavaScript for a single-page experience balancing semantics, interactivity and state <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role#required_javascript_features">as is conventional</a>. <strong>They’re just navigation links.</strong> And this mismatch of tabs-oriented ARIA within a non-tabs use case will do more harm than good. It’s an accessibility fail.</p>
<h2 id="a-stop-gap-solution" tabindex="-1">A stop-gap solution <a class="direct-link" href="https://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/#a-stop-gap-solution" aria-hidden="true">#</a></h2>
<p>If content for one or more <code>tabpanel</code> is provided, apply the complicated ARIA attributes for proper tabs. If not, don’t. This means we allow component consumers to either create i) a real tabbed interface, or ii) “a nav menu that looks like tabs” (but without any inappropriate ARIA attributes). I don’t agree with the latter as a design approach, but that’s a conversation for another day!</p>
<h2 id="tabs-in-the-future" tabindex="-1">Tabs in the future <a class="direct-link" href="https://fuzzylogic.me/posts/tabs-truth-fiction-and-practical-measures/#tabs-in-the-future" aria-hidden="true">#</a></h2>
<p>Some clever people involved with Open UI are using web components to explore how a useful <code>tabs</code> element could work if it were an HTML element. Check out <a href="https://github.com/tabvengers/spicy-sections.">the Tabvengers’ spicy-sections component</a>. Again, this is based on the conventional expectation of tabs as a same-page experience for arranging content, rather than as a navigation menu. And I think it’d make sense to stay on the same path as the rest of the web.</p>
Editable table cells2022-09-22T09:21:18Zhttps://fuzzylogic.me/posts/editable-table-cells/<p>Yesterday the Design System team received a tentative enquiry regarding making table cells editable. I’m not yet sure whether or not this is a good idea – experience and spidey sense tell me it’s not – but regardless I decided to start exploring so as to base my answer on facts and avoid being overly cautious.</p>
<p>In my mind’s eye, there are two ways to achieve this:</p>
<ol>
<li>on clicking the cell, the cell content is presented in an (editable) form input; or</li>
<li>apply the <code>contenteditable</code> attribute</li>
</ol>
<p>In both cases you get into slightly gnarlier territory when you start considering the need for a submit button and how to position it.</p>
<p>I don’t have anything further to add at the moment other than to say that if I had to spike this out, I’d probably start by following Scott O’Hara’s article <a href="https://www.scottohara.me/blog/2014/05/08/contenteditable.html">Using JavaScript & contenteditable</a>.</p>
<p>I’d probably also tweet Scott and ask if he can say anything more on his closing statement which was:</p>
<blockquote>
<p>I have more thoughts on the accessibility of contenteditable elements, but that will also have to be a topic for another day…</p>
</blockquote>
<p>Update 27-09-22: I’ve also remembered that (if I were to pursue Option 1: input within cell) Adrian Roselli has an article on <a href="https://adrianroselli.com/2019/05/uniquely-labeling-fields-in-a-table.html">Accessibly including inputs in tables</a>.</p>
Building the main navigation for a website (on web.dev)2022-09-12T11:38:34Zhttps://fuzzylogic.me/posts/2022-09-12-building-the-main-navigation-for-a-website-on-webdev/<blockquote>
<p>learn about semantic HTML, accessibility, and how using ARIA attributes can sometimes do more harm than good.</p>
</blockquote>
<p>Alongside all the sound accessibility and hiding-related advice, I also found Manuel’s approach to progressive enhancement interesting. Rather than i) include a hamburger <code>button</code> directly in the DOM and set its initial state to <code>hidden</code>; or ii) create the <code>button</code> element with JavaScript, he instead nests the <code>button</code> in a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template">template</a> element then clones that element with JavaScript. He later <a href="https://twitter.com/mmatuzo/status/1568149800209498113">tweeted his rationale for this approach</a>:</p>
<blockquote>
<p>If JS doesn't work, the markup inside the template won't be rendered on screen and it's more convenient to prepare the markup upfront instead of using document.createElement().</p>
</blockquote>
<p>The ability to prepare complex, JS-dependent component markup upfront in declarative HTML rather than recreating it in JavaScript is a compelling argument for his approach. Especially so if you don’t work in JS framework-based systems therefore your components are not written in JavaScript.</p>
Brilliant first day at We Out Here 20222022-08-27T07:16:03Zhttps://fuzzylogic.me/posts/brilliant-first-day-at-we-out-here-2022/<p>Had such a good day yesterday <a href="https://twitter.com/weoutherefest?s=21&t=U7_g4kzt2lqS6k_83zUQkw">@weoutherefest</a> with Tom, Jason and Craig. In the afternoon we checked Enny, Sally Rodgers (A Man Called Adam) and Aletha. We then stopped for a short break to sample the food and drink (Char Sui Vermicelli from the NAM stall and a break from beer for a cracking coffee). Our nighttime choices were Bake, Charlie Dark, Pearson Sound and Alex Nut.</p>
<p>The absolute highlight was Charlie Dark in the forest. Amazing woodland setting and a killer set! Charlie has such great energy both on the decks and on the mic. He played a mix of house, techno, disco and broken biznizz – right up my street! Great mixing too (aided by his old-school lollipop headphone).</p>
<p>Time for Round Two!</p>
Use CSS :has to set root-level styles based on a button’s state2022-08-25T13:56:10Zhttps://fuzzylogic.me/posts/2022-08-25-use-css-has-to-set-rootlevel-styles-based-on-a-button-state/<p>Great tip here from Jhey. He advises using a <code>button</code> with ARIA and a little JavaScript for your dark-mode toggle. And to apply the dark styles, use a CSS selector which targets the <code>:root</code> parent of the button when in “pressed” state and sets a root-level custom property to “on”.</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">:root:has([aria-pressed=true])</span> <span class="token punctuation">{</span><br /> <span class="token property">--dark</span><span class="token punctuation">:</span>1<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Seriously clever stuff!</p>
<p>And aside from the CSS, I really like the way Jhey advocates using a <code>button</code> rather than a form element such as a checkbox for this kind of interface, much <a href="https://fuzzylogic.me/posts/2022-07-15-perceived-affordances-and-the-functionality-mismatch-by-leonie-watson/">like Léonie did recently</a>.</p>
Experimenting with CSS cascade layers2022-08-21T15:00:31Zhttps://fuzzylogic.me/posts/trying-out-css-cascade-layers/<p>Back in June I attended CSS Day in Amsterdam. One of my favourite talks was <a href="https://www.youtube.com/watch?v=zEPXyqj7pEA">The CSS Cascade – A Deep Dive</a> by Bramus van Damme. Bramus covered everything we wanted to know about the cascade but were afraid to ask! And that included an introduction to CSS <em>Cascade Layers</em> – the latest game-changing CSS feature.</p>
<p>I previously <a href="https://fuzzylogic.me/posts/getting-started-with-css-cascade-layers-by-stephanie-eckles/">enjoyed Stephanie Eckles’s article <em>Getting Started with CSS Cascade Layers</em></a> so my interest was already piqued. However seeing Bramus’s talk in person really helped bring home the practical benefits of CSS layers.</p>
<p>For example, currently if we have the selectors <code>ul[class]</code> defined early in the “reset” section of our styles and <code>.nav</code> defined later in a “components” section, the former selector wins due to its higher specificity. That’s not what we want – we want our component styles to override our global styles. This has previously led people to hack around the problem by adding extra specificity to the latter selector, or by <a href="https://css-tricks.com/using-the-specificity-of-where-as-a-css-reset/">wrapping <code>:where()</code> around the former</a> to decrease its specificity, neither of which are desirable. With layers we can do:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@layer</span> reset<span class="token punctuation">,</span> components<span class="token punctuation">;</span></span><br /> <br /><span class="token atrule"><span class="token rule">@layer</span> reset</span> <span class="token punctuation">{</span><br /> <span class="token selector">ul[class]</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* set margin to 0 here */</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /> <br /><span class="token atrule"><span class="token rule">@layer</span> components</span> <span class="token punctuation">{</span><br /> <span class="token selector">.nav</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* give .nav ul custom margins */</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>And <code>.nav</code> gets that higher specificity that we want.</p>
<p>I also like that layers align well with an <a href="https://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528">ITCSS</a> approach.</p>
<h2 id="taking-layers-for-a-spin" tabindex="-1">Taking layers for a spin <a class="direct-link" href="https://fuzzylogic.me/posts/trying-out-css-cascade-layers/#taking-layers-for-a-spin" aria-hidden="true">#</a></h2>
<p>Cascade Layers are relatively newly-supported in browsers but pretty all-or-nothing in CSS terms to the extent that using them in a progressively-enhanced approach isn’t really an option. So I wouldn’t yet advocate using Layers on an important production website. However there’s nothing to stop me test-driving them on my personal site. Users on old browsers still get the essential content (although very few styles) and for this site, that’s good enough. So I’ve taken the plunge.</p>
<p>And it’s working really well already! Recently while rewriting some CSS I found that if the top of my styles featured a reset which disabled margins on <code>h2</code> but I also wanted an <code>h2</code> to take on margins when used within a <a href="https://piccalil.li/quick-tip/flow-utility/">low-specificity flow utility</a>, the reset style was winning and that was frustrating. But when I moved my reset styles into a <code>reset</code> layer and my layout styles into a <code>layouts</code> layer with the layer order set as <code>reset, layouts</code> then the layout styles win! Really cool.</p>
We use too many damn modals (modalz modalz modalz dot com)2022-08-09T20:03:21Zhttps://fuzzylogic.me/posts/we-use-too-many-damn-modals-modalzmodalzmodalz.com/<p>At our fortnightly Accessibility Forum at work, we just had a great discussion about modal dialogues. We started by discussing whether focus should be completely trapped within the modal or if the user should at least have access to the browser toolbar (we decided on the former). We then moved onto a general discussion on the pros and cons of modals, which led me to share MODALZ MODALZ MODALZ with the team.</p>
<p>Adrian Egger’s website presents some interesting suggestions, which I’ll summarise below:</p>
<p>Have you considered using the following alternatives to modals?</p>
<ul>
<li>Non-modal dialogs (e.g. toasts): for non-critical interactions that don’t block the user, use these rather than modals</li>
<li>New page: lead the user to a different page to isolate the interaction without losing access to functionality such as navigation.</li>
<li>Go inline: present your content inline to be less disruptive.</li>
<li>Expanding elements: Use expanding elements such as accordions, toolbars, tooltips, or sliding sidebars (or other modeless elements).</li>
<li>“Undo” patterns: instead of confirmation modals, consider using inline “Undo” option to speed up the user’s interactions.</li>
</ul>
<p>When all else fails here’s how to get modals right:</p>
<p><em>Do:</em></p>
<ul>
<li>Make it easy to close: make it simple to get rid of ‐ by escape key, clicking outside the modal window, and a clearly labelled close button.</li>
<li>Single purpose: limit the interaction to one, straightforward task.</li>
<li>Keep it short: be brief and concise in your content</li>
<li>Accessibility: this is fairly self-explanatory — if you can’t make it accessible, don’t use a modal.</li>
</ul>
<p><em>Do not:</em></p>
<ul>
<li>Modal inception: avoid opening a modal from a modal.</li>
<li>Fullscreen modals: you might as well navigate to a new page.</li>
<li>Multi-step modals: never create a multi-step modal. That way madness lies.</li>
<li>Self-spawning modals: never present modals unless prompted by the user.</li>
<li>Marketing modals: seriously, nobody wants that sh*t — especially not your newsletter.</li>
</ul>
<p>Modals are so hard to do well and present so many possible issues that I think before diving into designing/building one, it’s worth questioning if a modal is really appropriate for your use case.</p>
Putting a full stop on truncation2022-08-09T15:37:54Zhttps://fuzzylogic.me/posts/putting-a-full-stop-on-truncation/<p>At work we’ve recently been shown a couple of design proposals where truncation was presented as a solution to the perceived problem of long and unwieldy content, for example a long description in a table cell. However following good discussions, as a wider team we’re now leaning towards <em>avoiding</em> truncation as an approach. Truncation <a href="https://www.tpgi.com/the-ballad-of-text-overflow/">can present accessibility issues</a> and as Karen McGrane says <a href="https://freeagent.slack.com/archives/C37K79GCA/p1656058527349639?thread_ts=1656058159.790969&cid=C37K79GCA">truncation is not a good content strategy</a>. I reckon we should just let long content wrap, and design for that to look OK.</p>
<p>And when natural wrapping doesn’t cut it – like when you’re tackling very long words in confined spaces – reach for <code>overflow-wrap: break-word</code> as suggested in Ahmad Shadeed’s excellent <a href="https://ishadeed.com/article/css-short-long-content/">Handling Short And Long Content In CSS</a>.</p>
These 3 Pro Tips Saved My Backhand (from Table Tennis Daily on YouTube)2022-08-08T19:16:52Zhttps://fuzzylogic.me/posts/2022-08-08-these-3-pro-tips-saved-my-backhand-from-table-tennis-daily-on-youtube/<blockquote>
<p>In this video we go over the 3 pro tips from Liam Pitchford that helped transform Dan’s backhand!</p>
</blockquote>
<p>My backhand is kinda shaky at the moment and I struggle with correct elbow and wrist position so this tutorial video is timely and helpful.</p>
:has(): the family selector (Chrome developers blog)2022-08-08T19:13:35Zhttps://fuzzylogic.me/posts/2022-08-08-has-the-family-selector-chrome-developers-blog/<blockquote>
<p>The :has() CSS pseudo-class represents an element if any of the selectors passed as parameters match at least one element. But, it's more than a "parent" selector. That's a nice way to market it. The not so appealing way might be the "conditional environment" selector. But that doesn't have quite the same ring to it. How about the “family” selector?</p>
</blockquote>
<p>The CSS :has() pseudo-class is a game-changer and can do more than act as a parent selector, as Jhey illustrates.</p>
Inclusive user research: recruiting participants (by Ela Gorla on Tetralogical’s blog)2022-08-08T08:25:21Zhttps://fuzzylogic.me/posts/inclusive-user-research-recruiting-participants-by-ela-gorla-on-tetralogical-s-blog/<p>Tetralogical are doing a great series of articles on <em>running inclusive research</em>. Their latest is about recruiting participants and covers whether you should recruit people with disabilities as part of your testing and if so who, and how many, and how to recruit them.</p>
<p>Previous articles addressed moderating usability testing sessions with people with disabilities, and analysing findings from inclusive user research.</p>
Herbie Hancock in Edinburgh2022-08-07T22:00:56Zhttps://fuzzylogic.me/posts/herbie-hancock-at-edinburgh-playhouse/<p>Just had a memorable experience with Jason and Tom catching Herbie Hancock at the Edinburgh Festival. At 82 years old he still has amazing energy and capped his performance with a tour of the stage playing his keytar followed by a scissor jump!</p>
<p>Herbie’s piano playing was mesmerising – the solos really took me to another place and if this is how he plays in his eighties I can only imagine how good his gigs were in his prime. I also loved his warm anecdotes, including one about his friend Wayne Shorter just before treating us to a rendition of <a href="https://www.youtube.com/watch?v=3XvJFW0DHbU">Footprints</a>.</p>
<p>Other highlights included <a href="https://www.youtube.com/watch?v=8B1oIXGX0Io">Cantaloupe Island</a>, the mindbending <a href="https://www.youtube.com/watch?v=nP4CJfSN27E">Actual Proof</a> and hearing guitarist Lionel Louke coax sounds from a guitar that you wouldn’t think possible.</p>
Post-COVID holiday in Provence, July 20222022-07-29T17:30:00Zhttps://fuzzylogic.me/posts/holiday-to-provence-july-2022/<p>Like most folks we didn’t holiday abroad during 2020 and 2021, when COVID was at its height. Trips abroad are a luxury and privilege so this was no hardship. However I’ll admit that once restrictions were lifted and things felt safer, we were pretty excited to head for some sun and good food, and set our sights on a first trip together to the south of France.</p>
<h2 id="the-location" tabindex="-1">The location <a class="direct-link" href="https://fuzzylogic.me/posts/holiday-to-provence-july-2022/#the-location" aria-hidden="true">#</a></h2>
<p>We spent seven nights at <a href="https://en.desirdeprovence.com/">Désir de Provence</a>, hosted by owners Sylvie and Igor.</p>
<h2 id="dining-out" tabindex="-1">Dining out <a class="direct-link" href="https://fuzzylogic.me/posts/holiday-to-provence-july-2022/#dining-out" aria-hidden="true">#</a></h2>
<p>La Bastide Bleue restaurant, Séguret.</p>
<p>Hotel Montmirail in Vacqueyras.</p>
<p>Beautiful local wine at <a href="https://domaine-mathiflo.com/">Domaine Mathiflo</a> in Suzette (right in the heart of the countryside).</p>
<p>Les Ramparts in Venasque – incredible nighttime view over the mountains</p>
<p><a href="https://www.tripadvisor.com/Restaurant_Review-g608811-d23724147-Reviews-Monsieur_Tu-L_Isle_sur_la_Sorgue_Vaucluse_Provence_Alpes_Cote_d_Azur.html">Monsieur Tu</a> at L’isle sur la Sorgue, where we had a lovely meal of fish and wine by the canal.</p>
<p>Chez Serge in Carpentras.</p>
<h2 id="other-highlights" tabindex="-1">Other highlights <a class="direct-link" href="https://fuzzylogic.me/posts/holiday-to-provence-july-2022/#other-highlights" aria-hidden="true">#</a></h2>
<p>Antiques market at Carpentras.</p>
<p>A day walking around the towns of Gigigondas, Seguret and Vaison La Romagne.</p>
<p>St Remy de Provence on a Wednesday morning for a fantastic market.</p>
<p><a href="https://www.carrieres-lumieres.com/en/node/994">Carrieres Lumieres</a> (caves featuring art installations) which was amazing.</p>
<p>Aix en Provence. <a href="https://www.fondationvasarely.org/en/">Vasarely Foundation</a> for Kinetic art. Lovely shops and vibe.</p>
<p><a href="https://www.chateaudubarroux.fr/en/">Chateau du Barroux</a> was a stunning hilltop location with a castle, cobbled streets, a chapel and incredible panoramic views of the surrounding region including Mont Ventoux.</p>
<p>L’isle sur la sorgue – a lovely town which had an antiques market that blew Clair’s mind!</p>
<h2 id="if-we-had-more-time" tabindex="-1">If we had more time <a class="direct-link" href="https://fuzzylogic.me/posts/holiday-to-provence-july-2022/#if-we-had-more-time" aria-hidden="true">#</a></h2>
<p>Hopefully on a future stay in the area we can visit Gord, Russelet (“the Colorado of Provence”), and Nimmes.</p>
<!--
Arrive after delays and Europcar racket
Best hosts!
night dinner (booked by Sylvie) – La Bastide Bleue restaurant, Séguret. Beautiful outdoor garden/courtyard setting, lovely food. We learned “squid” either that night or the next. Practiced a little French as they didn’t speak much English which was refreshing!
Beaut setting, and light and countryside
Saumon, beef, chocolat, assiete de fromage
Next morning, Sun
Breakfast
Carpentras antique market. Loved it! Spidey sense was tingling and sure enough there were second-hand record stalls.
Then quiet day of chilling and planning.
Dinner: Hotel Montmirail in Vacqueyras (?) Lovely!
Monday
Gigigondas cut aboot
2 other towns cut aboot.
- Seguret
- Vaison La Romagne
Art shop with Brazillian guy’s cool art. Website for Cesar Henao’s art: Infinitisation (dot something). Shop was called nartex or similar
Brasserie universal: Tuna steak!!!
https://www.fondationvasarely.org/en/
Kinetic art
Aix en Provence.
- Bought sunglasses, Persol. Assistant was great – completely straightforward, no messing! Exactly what I needed.
- we ate at Bistrot Mairie (I think). Simple but great!
- T-shirts at Lafaurie
(Which night?) Les Ramparts in Venasque – incredible nighttime view over the mountains. Drive back a bit hairy!
Day we had wine above the countryside https://domaine-mathiflo.com/
Did we go to St Remy de Provence? in morning. 45m drive. Wed is market day.
Yes! It was the day I bought the Specials LP! Lovely market town. Market was amazing. Hard to park there. Lucky to get a restaurant.
THen went to
https://www.carrieres-lumieres.com/en/node/994 which was amazing. Venice rennaisance followed by French “Blue” guy (amazing)
Last day
- L’isle sur la sorgue
- lovely!
- Monsieur Tu https://www.tripadvisor.com/Restaurant_Review-g608811-d23724147-Reviews-Monsieur_Tu-L_Isle_sur_la_Sorgue_Vaucluse_Provence_Alpes_Cote_d_Azur.html Meal by canal, for fish and wine
- antiques market that blew Clair’s head off
- L’isle sur la sorgue
Last night – Chez Serge in Carpentras.
-->
Custom multi-checkbox and multi-radio controls2022-07-27T07:14:19Zhttps://fuzzylogic.me/posts/custom-multi-checkbox-and-multi-radio-controls/<p>Our Design System team has recently received “new component requests” for some custom filtering controls. These <em>look like</em> custom-styled <code><select></code>s however their “options” appear more like checkboxes and radio buttons. I think the inspiration was <a href="https://carbondesignsystem.com/components/dropdown/usage">Carbon Design System’s Dropdown component</a> and the idea is to bring consistency to filtering controls in forms. Although it’s not yet time to fully explore this and make a yay/nay decision on the request, I’ve been doing some initial thinking.</p>
<p>(Note: this post is kinda a journey and work-in-progress. I’ll return to complete it and tidy up. For now it serves as a handy log of my research.)</p>
<p>When this was first mooted without guide designs, I assumed we’d be making a custom select. Filament Group have previously shown how to style one of those, although that only affects the “trigger” part. CSS can’t yet style the options. That then led me to check in on the progress of <a href="https://css-tricks.com/the-selectmenu-element/">Open UI’s selectmenu element</a> which <em>does</em> support styling the options however it appears that it’s far from road-ready.</p>
<p>However then I saw the designs and realised that while the outside looks like a select, the options look like a group of checkboxes or (kinda) like radio buttons, rather than typical <code><select></code> options. And of course the checkboxes and radio buttons themselves are custom-styled.</p>
<p>This led me to reading the following resources.</p>
<ul>
<li><a href="https://adrianroselli.com/2022/05/under-engineered-multi-selects.html">Under-engineered multi-selects</a></li>
<li><a href="https://adrianroselli.com/2021/03/under-engineered-select-menus.html">Under-engineered select menus</a></li>
<li><a href="https://adrianroselli.com/2017/05/under-engineered-custom-radio-buttons-and-checkboxen.html">Under-engineered custom radio buttons and checkboxen</a></li>
<li><a href="https://www.sarasoueidan.com/blog/inclusively-hiding-and-styling-checkboxes-and-radio-buttons/#styling-the-svg-accessibly">Inclusively Hiding & Styling Checkboxes and Radio Buttons</a></li>
</ul>
<p>Léonie Watson’s post <a href="https://tink.uk/perceived-affordances-and-the-functionality-mismatch/">Perceived affordances and the functionality mismatch</a> is also looming large in the back of my mind.</p>
Simple input[type=range] styling, by Ana Tudor2022-07-24T11:05:35Zhttps://fuzzylogic.me/posts/2022-07-24-simple-inputtyperange-styling-by-ana-tudor/<p>Ana demonstrates how to achieve a range slider effect accessibly, using web standards and without needing to reach for libraries.</p>
<p>As <a href="https://twitter.com/anatudor/status/1549284325765554176">Ana’s tweet explains</a>, this offers a number of features and benefits:</p>
<ul>
<li>can drag thumb with JS disabled</li>
<li>receives focus</li>
<li>keyboard navigation</li>
<li>clicking track moves thumb there and changes slider value</li>
<li>seen as slider in Accessibility panel</li>
<li>no library needed, so less code in total</li>
</ul>
Thoughts on The 15-Minute City (the book and the concept)2022-07-20T21:30:35Zhttps://fuzzylogic.me/posts/thoughts-on-the-15-minute-city-the-book-and-the-concept/<p>I really enjoyed <a href="https://uk.bookshop.org/books/the-15-minute-city-global-change-through-local-living/9781910022474">The 15 Minute City</a> by Natalie Whittle.</p>
<p>It presents the idea of modern cities in which residents can reach everything they need – shopping, work, school, green space, transport, exercise, culture etc – within 15 minutes on foot or by bike.</p>
<p>This idea is already working (or making good progress) in cities like Amsterdam and Paris.</p>
<p>And during periods of restriction during the Covid-19 pandemic it’s a way of life that people around the world have been forced to try.</p>
<p>There are numerous potential benefits of the idea – for example for physical and mental health, the environment, gaining more family and social time from less commuting, boosting neighbourhood economies through shopping local and so on.</p>
<p>On the other hand the 15-minute idea arguably favours the middle-class over the working-class, leads to diminished interpersonal skills, and ignores the important role of cities (such as London) in performing a wider, globally-connected role.</p>
<p>I enjoyed the thoughtful exploration of what are the important factors that give somewhere <a href="https://www.sciencedirect.com/topics/earth-and-planetary-sciences/sense-of-place#:~:text=Sense%20of%20place%20refers%20to,of%20particular%20localities%20and%20regions.">a sense of place</a>. And I loved the chapter on Glasgow – Natalie’s home of the last 3 years and mine for much longer. It considers how past planning decisions in relation to new towns and the M8 motorway have become problematic for the city. It also looks at exciting modern projects such as the bridge to better connect the Sighthill estate on the outskirts to the city centre, and initiatives to revitalise the Clyde riverside.</p>
<p>Since reading this book I’m noticing more and more these matters being “in the air”. Just recently The Guardian’s <em>Big Idea</em> feature asked <a href="https://www.theguardian.com/books/2022/jul/11/the-big-idea-should-cars-be-banned-from-cities">Should cars be banned from cities?</a> If that gave one perspective on traffic in cities, I recently spoke to a taxi driver who offered another. Taxi drivers are being made to change their cars to hybrid models soon, but feel that the combination of increased outlays and lack of necessary technology and infrastructure make the move prohibitive. It was a reminder that we have to consider the potential effects on lots of different people when planning change.</p>
Perceived affordances and the functionality mismatch (by Léonie Watson)2022-07-15T11:29:59Zhttps://fuzzylogic.me/posts/2022-07-15-perceived-affordances-and-the-functionality-mismatch-by-leonie-watson/<p>Léonie tackles the prickly subject of “element re-purposing” in web development. This post follows a <a href="https://twitter.com/LeaVerou/status/1545712667515654144">fantastic Twitter exchange started by Lea Verou</a> regarding whether the common visual design request for “adjacent but mututally exclusive buttons” should be built as radio buttons or using <code><button></code> elements.</p>
<blockquote>
<p>Using one element or set of elements (usually because of their functionality) and styling them to look like something else is a common pattern […but…] it creates a mismatch between the actions people expect they can take and the ones they actually can.</p>
</blockquote>
<p>Relatedly, <a href="https://twitter.com/LeaVerou">Lea</a> has also gathered her post-discussion thoughts and decisions into a blog post <a href="https://lea.verou.me/2022/07/button-group/">What is the best way to mark up an exclusive button group?</a> <em>and</em> shared a new <a href="https://github.com/LeaVerou/nudeforms/tree/main/button-group"><code>button-group</code> web component</a>!</p>
<p>Meanwhile, Léonie already has a <a href="https://github.com/LJWatson/website-tink-eleventy/search?q=theme-toggle">theme-toggle web component</a> on her personal website which demonstrates the use of buttons and <code>aria-pressed</code>.</p>
<p>Thank you so much, Lea and Léonie.</p>
<p><a href="https://twitter.com/LeonieWatson/status/1547651790115520521">(via @LeonieWatson)</a></p>
<h2 id="update-july-19%2F7%2F22" tabindex="-1">Update July 19/7/22 <a class="direct-link" href="https://fuzzylogic.me/posts/2022-07-15-perceived-affordances-and-the-functionality-mismatch-by-leonie-watson/#update-july-19%2F7%2F22" aria-hidden="true">#</a></h2>
<p>I just had a twitter conversation with Adrian Roselli where I suggested that the reasons for developers considering radio inputs over buttons for Lea’s use case might be more nuanced than simply misunderstanding HTML. I’m not sure we agreed on that one in the end, however Adrian shared <a href="https://twitter.com/aardrian/status/1549365053580890112">some helpful heuristics when choosing betweeen JS-powered buttons and forms</a>:</p>
<blockquote>
<p>A checkbox, radio button, select menu are meant to gather information. The submit button sends the form (whether get, post, or an AJAX call). A button (non-submit) causes a change on the page, such as toggling a control, showing or hiding something, etc. Different context/use.</p>
</blockquote>
<blockquote>
<p>I think it would help to think of form fields as for <em>forms</em>. Forms that users intentionally submit (no matter if processed client- or server-side). Forms that gather info. Buttons that have states (expanded, pressed, etc) are for manipulation of the current view.</p>
</blockquote>
<p>Takeaways:</p>
<ul>
<li>Pick the HTML solution that is generally intended for your use case.</li>
<li>Use a form if you’re gathering information but if you’re not, don’t. There will be exceptions like “filter forms” but that’s an edge case and most forms are not like that.</li>
<li>Forms are ideally things that users intentionally submit, via a submit button. This helps rule out “clever forms” as an option.</li>
<li>Use a button to cause a change on, or manipulate, the current page.</li>
</ul>
My new syntax for modern, responsive blog images2022-07-14T10:07:16Zhttps://fuzzylogic.me/posts/my-new-syntax-for-responsive-and-modern-blog-images/<p>I’ve started trialling different HTML and technologies for the “simple” responsive images (i.e. not art-directed per breakpoint) used in blog articles on this site. I’m continuing to lean on Cloudinary as my free image host, CDN and format-conversion service. But at the HTML level I’ve moved from a complicated <code><img srcset></code> based approach which included many resized versions of the same image. I now use a simpler <code><picture></code> and <code><source></code> based pattern that keeps the number of images and breakpoints low, leaning instead into the performance gains offered by the newer image formats <code>avif</code> and <code>webp</code>.</p>
<p>My new approach is based on advice in Jake Archibald’s brilliant article <a href="https://jakearchibald.com/2021/serving-sharp-images-to-high-density-screens/">Halve the size of images by optimising for high density displays</a>. Jake explains that the majority of your traffic likely consists of users with high density screens so when we can combine optimising for that and making performance gains in a progressively enhanced way, we should!</p>
<p>Jake offers a “lazy but generally good enough” approach:</p>
<blockquote>
<p>Here's the technique I use for most images on this blog: I take the maximum size the image can be displayed in CSS pixels, and I multiply that by two, and I encode it at a lower quality, as it'll always be displayed at a 2x density or greater. Yep. That's it. For 'large' images in blog posts like this, they're at their biggest when the viewport is 799px wide, where they take up the full viewport width. So I encode the image 1,598 pixels wide.</p>
</blockquote>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>picture</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/avif<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>red-panda.avif<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/webp<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>red-panda.webp<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>red-panda.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1598<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1026<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>A red panda<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>picture</span><span class="token punctuation">></span></span></code></pre>
</figure>
<blockquote>
<p>So, if you want your images to be as sharp as possible, you need to target images at the user's device pixels, rather than their CSS pixels. To encode a 2x image, I throw it into Squoosh.app, and zoom it out until it's the size it'll be displayed on a page. Then I just drag the quality slider as low as it'll go before it starts looking bad.</p>
</blockquote>
<p>Taking Jake’s guidance and tweaking it for my Cloudinary-based context, my recent post <a href="https://fuzzylogic.me/posts/april-2022-mixtape/">April 2022 mixtape</a> included its image like so:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figure</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>picture</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/avif<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://res.cloudinary.com/…/f_avif,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/webp<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://res.cloudinary.com/…/f_webp,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>u-full-parent-width<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://res.cloudinary.com/…/f_jpg,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1292<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1292<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Side A of the 7-inch vinyl release of Mato’s “Summer Madness<span class="token punctuation">"</span></span> <span class="token attr-name">loading</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>lazy<span class="token punctuation">"</span></span> <span class="token attr-name">decoding</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>async<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>picture</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figcaption</span><span class="token punctuation">></span></span>Mato’s “Summer Madness”, as featured on the mix<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figcaption</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figure</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>And my process was as follows:</p>
<ol>
<li>Take a photo (for me, that’ll be on my phone). Without doing anything special it’ll already be wide enough.</li>
<li>Apple use the HEIC format. <a href="https://discussions.apple.com/thread/253906990">To get around that</a>, do: Share, Copy, open Files > <em>HEIC to JPG</em>, paste and it’ll save as JPG.</li>
<li>Drop it into <a href="https://squoosh.app/">Squoosh</a> and do the following:</li>
</ol>
<ul>
<li>rotate it if necessary</li>
<li>resize it to 1300 wide (in my current layout <code>1292</code> is twice as wide (2 × 646) as the image would need to go, and I just round up to 1300)</li>
<li>reduce its quality a bit (stopping before it gets noticeably bad)</li>
</ul>
<ol>
<li>Encode that as a <code>mozjpg</code> which gave the best size reduction and as far as I can tell, is a safe approach to use.</li>
<li>Upload to my Cloudinary account then copy its new Cloudinary URL.</li>
<li>Prepare the image HTML per the above snippet. The first <code>source</code> <a href="https://cloudinary.com/blog/how_to_adopt_avif_for_images_with_cloudinary#how_do_i_do_that_">tells Cloudinary to use format <code>avif</code></a>, while for the second source it’s <code>webp</code>, and for the fallback <code>img</code> it’s <code>jpg</code>.</li>
<li>Check the rendered image in a browser to confirm that the modern formats are being used.</li>
</ol>
<p>I’ll DRY-up that HTML into an 11ty shortcode in due course.</p>
<p>I’ve no doubt that I’ll be getting some of this wrong – this stuff gets pretty complicated! For example I note my image file size is still quite large so I wonder if I should be manually creating the <code>avif</code> and <code>webp</code> versions in Squoosh myself to ensure getting the savings that make this approach worthwhile, rather than handing the conversion off to Cloudinary. (However this would mean having to host more images…)</p>
<p>In the meantime however, I’m happy that this approach has simplified the mental overhead of handling modern, responsive blog images, and optimising it can be a work in progress.</p>
<h2 id="additional-references" tabindex="-1">Additional references <a class="direct-link" href="https://fuzzylogic.me/posts/my-new-syntax-for-responsive-and-modern-blog-images/#additional-references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://caniuse.com/avif">Browser support for avif on caiuse.com</a></li>
<li><a href="https://twitter.com/jaffathecake/status/1540697894683942912">Twitter thread on forthcoming Safari support for avif</a>, and related info</li>
</ul>
Avoiding img layout shifts: aspect-ratio vs width & height attributes (on Jake Archibald's blog)2022-07-13T19:44:49Zhttps://fuzzylogic.me/posts/2022-07-13-avoiding-img-layout-shifts-aspectratio-vs-width-and-height-attributes-on-jake-archibalds-blog/<p>Recently I’ve noticed some developers recommending using the CSS <code>aspect-ratio</code> property directly on images. <a href="https://fuzzylogic.me/posts/2021-02-02-a-first-look-at-aspectratio-on-csstricks/">My understanding of <code>aspect-ratio</code></a> was that it’s not so much intended for elements like <code>img</code> which already have an intrinsic aspect ratio, but rather for the likes of <code>div</code> which do not. Furthermore, when the goal is to prevent the layout shift that can occur after an image loads we should supply our images with <code>width</code> and <code>height</code> HTML attributes rather than using CSS.</p>
<p>In this timely post, Jake helpfully explains how <code>width</code> and <code>height</code> attributes are used by CSS as <em>presentation hints</em> to automatically set an <code>aspect-ratio</code> that will also, in cases where the attributes were set wrongly, fall back to the image’s intrinsic aspect ratio. Therefore, concentrating on HTML alone is ideal for our <em>content</em> images. My previous approach seems sound but I now know a little more about <em>why</em>.</p>
<blockquote>
<p>If I'm adding an image to an article on my blog, that's content. I want the reserved space to be the aspect ratio of the content. If I get the width and height attributes wrong, I'd rather the correct values were used from the content image. Therefore, width and height attributes feel like the best fit. This means I can just author content, I don't need to dip into inline styles.</p>
</blockquote>
<blockquote>
<p>If it's a design requirement that the layout of an image is a particular aspect ratio, enforcing that with aspect-ratio in CSS can be appropriate. For example, a hero image that must be 16 / 9 – if the image isn't quite 16 / 9 I don't want it messing up my design, I want the design to take priority. Although, if the image isn't actually that aspect ratio, it'll either end up stretched (object-fit: fill), letter-boxed (object-fit: contain), or cropped (object-fit: cover). None of which are ideal.</p>
</blockquote>
A local’s guide to… (on The Guardian)2022-07-13T11:57:14Zhttps://fuzzylogic.me/posts/a-local-s-guide-to-on-the-guardian/<p>For a while now I’ve been enjoying this series of bite-sized travel guides from The Guardian, which puts the spotlight on a European town or city and hands over to a switched-on local to share food, shopping, cultural and green space highlights.</p>
<p>Some are more suited to my tastes and budget than others, but overall they’ve been good. And not just for far-flung places – on a recent day-trip east I checked out a number of the stops on <a href="https://www.theguardian.com/travel/2021/dec/19/locals-guide-to-edinburgh-bookshops-restaurants-parks-cocktail-bars">their Edinburgh guide</a> and it gave me a great basis for further exploration.</p>
Sites which don’t work without JavaScript enabled still benefit from progressive enhancement2022-07-05T17:20:01Zhttps://fuzzylogic.me/posts/progressive-enhancement-javascript-disabled-vs-unavailable/<p>At work I and our team just had an interesting realisation about a recent conversation. We had been discussing progressive enhancement for custom toggles and a colleague mentioned that the web app in question breaks at a fundamental level if the user has disabled JavaScript, displaying a message telling them to change their settings in order to continue. He used this to suggest that any efforts to provide a no-JavaScript experience would be pointless. And this fairly absolute (and on-the-surface, sensible) statement caught me off-guard and sent me and the others down a blind alley.</p>
<p>I remember replying “yes, but even still we should try to improve the code by introducing good practices” and that feeling a little box-ticky.</p>
<p>However in retrospect I realise that we had temporarily made the mistake of conflating “JavaScript enabled” with “JavaScript <em>available</em>” – which are separate possibilities.</p>
<p>When considering resilience around JavaScript, we can consider the “factors required for JavaScript to work” as layers:</p>
<ol>
<li>is JavaScript enabled in the user’s browser?</li>
<li>is the JavaScript getting through firewalls? (it recently didn’t for one of our customers on the NHS’s network)</li>
<li>has the JavaScript finished loading?</li>
<li>does the user’s browser support the JavaScript features the developers have used (i.e. does the browser “cut the mustard”?)</li>
<li>is the JavaScript error-free? It’s easy for some malformed JSON to creep in and break it…</li>
</ol>
<p>And the point my colleague made relates to Layer 1 only. And that layer – JavaScript being disabled by the user – is actually the least likely explanation for a JavaScript-dependent feature not working.</p>
<p>So it's really important to remember that when we build things with progressive enhancement we are not just addressing Layer 1, but Layers 2—5 too (as well as other layers I’ve probably forgotten!)</p>
Safari is getting Web Push! (on the Webventures blog)2022-07-05T07:22:48Zhttps://fuzzylogic.me/posts/safari-is-getting-web-push-on-the-webventures-blog/<p>Roderick E.J.H. Gadellaa, author of the Webventures blog writes that at their June 2022 Worldwide Developers Conference (WWDC) Apple announced that it will bring Web Push (web-based push notifications) to Safari, including iOS Safari.</p>
<blockquote>
<p>MacOS is going to get it first and iOS will receive it in a later iOS 16.x update, sometime in 2023.</p>
</blockquote>
<p>This could be a big deal, because…</p>
<blockquote>
<p>The lack of the web being able to do push notifications on iOS is probably the biggest reason why web developers see a potential project end up being built as a native app instead of a web app</p>
</blockquote>
<p>…and…</p>
<blockquote>
<p>Web Push on iOS will change the “we need to build a native app” decision.</p>
</blockquote>
<p>I don’t like the idea that native mobile apps are superior to mobile web experiences, nor the notion that by having a native app you can ignore your small-screen web experience. PWAs and native apps can co-exist in harmony and address different use cases. But also web APIs are becoming more powerful all the time, and this announcement by Apple provides fuel for the argument that “you might not need a native app for that!”</p>
Reading The New Breed: How to think about robots by Kate Darling2022-07-03T09:52:09Zhttps://fuzzylogic.me/posts/2022-07-24-reading-the-new-breed-how-to-think-about-robots-by-kate-darling/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9780241352991">The New Breed: How to think about robots</a>, by Kate Darling.</p>
How we think about browsers, on GitHub’s blog2022-06-30T09:50:00Zhttps://fuzzylogic.me/posts/how-we-think-about-browsers-on-github-s-blog/<p>Keith Cirkel of Github has written about how they think about browsers and it’s interesting. In summary Github achieve:</p>
<ul>
<li>improved performance;</li>
<li>exploiting new native technologies; and</li>
<li>universal user access/inclusion</li>
</ul>
<p>…via a progressive enhancement strategy that ensures a basic experience for all but delivers an enhanced experience to most. Their tooling gets a bit deep/exotic in places but I think the basic premise is:</p>
<ol>
<li>decide on what our basic experience is, then use native HTML combined with a bare minimum of other stuff to help old browsers deliver that; and</li>
<li>exploit new JS features in our enhanced experience (the one most people will get) to make it super lean and fast</li>
</ol>
<p>Pretty cool.</p>
Using accessibility literacy to counter accessibility ignorance, by Devon Persing2022-06-29T09:32:18Zhttps://fuzzylogic.me/posts/using-accessibility-literacy-to-counter-accessibility-ignorance-by-devon-persing/<p>The idea of accessibility literacy (having the right vocabulary, knowing the trustworthy info sources etc) makes sense.</p>
<p>The section on <em>Accessibility ignorance and ableism</em> presents some home truths about organisational attitudes to accessibility that need addressed.</p>
<blockquote>
<p>Accessibility ignorance actually goes beyond just a lack of accessibility literacy. Accessibility ignorance is a facet of ableism, since it causes people to make decisions that actively harm disabled people.</p>
<ul>
<li>Accessibility ignorance isn't usually malicious.</li>
<li>It's assuming that accessibility is taken care of because your organization has an accessibility specialist on staff, or has accessibility "baked in" to a design system.</li>
<li>It's providing accessibility training for only teams that build products and not people that work in support, legal, operations, leadership, or other parts of the organization.</li>
<li>It's expecting accessibility work to happen without impacting schedules and roadmaps that didn't originally take accessibility work into account.</li>
<li>It's assuming disabled people don't use your product.</li>
<li>It's not hiring disabled people.</li>
<li>It's hiring disabled people but only to do accessibility work.</li>
<li>…</li>
</ul>
</blockquote>
<p>The article wraps up with some great advice on cultivating accessibility literacy, and the senior buy-in needed to support it.</p>
Getting Started With CSS Cascade Layers, by Stephanie Eckles2022-06-06T07:50:59Zhttps://fuzzylogic.me/posts/getting-started-with-css-cascade-layers-by-stephanie-eckles/<p>Yesterday I read <a href="https://aneventapart.com/news/post/looking-ahead-june-2022">Eric Meyer discussing CSS Cascade Layers</a> and commenting that the speed at which it had transitioned from first public working draft to shipping as a full public release in every major desktop and mobile browser had made his head spin. Amazing stuff and an indicator of the turbo-boosted pace at which modern CSS is now evolving.</p>
<p>It also made me want to properly read up on Cascade Layers, because I knew some of the theory but now wanted to consider using it in practice. I’m no great fan of “cascade-taming” CSS frameworks like BEM and SUIT (although I acknowledge why we have them) so I’m interested to know if Cascade Layers can replace them. Stephanie Eckles’ article is an excellent primer.</p>
<p>I liked the idea of a specifying a stack like this:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@layer</span> reset<span class="token punctuation">,</span> base<span class="token punctuation">,</span> theme<span class="token punctuation">,</span> components<span class="token punctuation">,</span> utilities<span class="token punctuation">;</span></span></code></pre>
</figure>
<p>You can then write styles into any of those layers at <em>any point</em> in a stylesheet, safe in the knowledge that the original stack definition sets the order of priority rather than the sequence in which we wrote specific styles.</p>
<p>Stephanie also addresses the question of whether we should write every <em>component</em> as a layer, which is something I’ve been considering. She advises that <em>you could</em>… but it’s probably not going to achieve the scoping effect that you want.</p>
<blockquote>
<p>layers are not intended to solve scoping or encapsulation of styles. For that, keep an eye on another spec also being authored by Miriam Suzanne for actual <a href="https://css.oddbird.net/scope/explainer/">native CSS scoping</a>.</p>
</blockquote>
<p>Lastly, Stephanie tackles how ready Cascade Layers are to use right now. At the time she wrote the article – January 2022 – the feature wasn’t widely supported, so wasn’t an option. Additionally Cascade Layers can’t really be used as a progressive enhancement because its nature is so all-encompassing and because testing for feature support using <code>@supports</code> isn’t an option.</p>
<p><em>However</em> like Eric Meyer mentions, a few months is a long time in CSS support! And as I write in June 2022 the browser support picture is currently <a href="https://caniuse.com/?search=cascade%20layers">looking quite healthy</a>. However given that the first browsers to add support were only released a few months ago in February or March of this year, I think we might need to wait a bit longer – maybe til the percentage of users on non-supporting browsers is negligible – before using this on larger, higher-traffic sites.</p>
<p>Nothing to stop us experimenting on our smaller and intranet-based sites, though!</p>
Refactoring a modal dialogue in 20222022-06-01T13:39:34Zhttps://fuzzylogic.me/posts/refactoring-a-modal-dialogue-in-2022/<p>My team will soon be refactoring our modal dialogue component. Ours has a few deficiencies, needs better developer experience and documentation, is not built to our Design System component standards, and could use a resilience boost from some progressive enhancement.</p>
<p>For a long time the best – meaning accessible, framework-agnostic, feature-packed – modal implementations were <em>custom</em>. Specifically:</p>
<ul>
<li><a href="https://a11y-dialog.netlify.app/">Kitty Giraudel’s a11y-dialog</a>; and</li>
<li><a href="https://scottaohara.github.io/accessible_modal_window/">Scott O’Hara’s Vanilla Modal Dialog</a></li>
</ul>
<p>However with recent browser advances (especially from Safari), there’s an argument that the time has now come that we no longer need custom solutions and can go native. So we might reach for <a href="https://twitter.com/Una/status/1508926326392164353">the native <code><dialog></code> HTML element</a>.</p>
<p>However first I think we’d need to make an informed decision regarding our satisfaction with support, based on the updated advice in Scott O’Hara’s article <a href="https://www.scottohara.me/blog/2019/03/05/open-dialog.html">Having an Open Dialog</a>.</p>
<p>Additionally we should <em>definitely</em> be keeping one eye on proposals around <a href="https://twitter.com/jh3yy/status/1529909208098947072">the exciting new <code>togglepopup</code> and <code>popup</code> attributes</a> which promise the holy grail of entirely HTML-powered modal dialogues with no JavaScript dependency.</p>
Does the HTML details element solve progressively-enhanced disclosures?2022-05-29T08:54:32Zhttps://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/<p>The HTML <code>details</code> element continues to gain fans and get developers’ juices flowing. <a href="https://twitter.com/scottjehl/status/1524746181271863296">Scott Jehl recently tweeted:</a></p>
<blockquote>
<p>I love the details/summary HTML elements. So versatile. My favorite part is being able to show a collapsed state from the start without worrying about potential operability issues if JavaScript fails to run (since its behavior doesn't need it).</p>
</blockquote>
<p>Scott goes on to describe how creating disclosure widgets (controls that hide and show stuff) with resilience in mind is so much more difficult when not using <code><details></code> since it can require complex progressive enhancement techniques. At the very least these involve making content available by default in case JavaScript fails, then hiding it when the disclosure widget script loads successfully, ideally without a jarring flash of content in between.</p>
<p>Like Scott says, the <code><details></code> element is different because you can have the content collapsed (hidden) by default without worrying about JavaScript and workarounds since the hidden content can be toggled open natively. That‘s a real superpower… and also makes you wonder: how many different places and different ways might we use this super-element?</p>
<h2 id="github%E2%80%99s-use-of-details" tabindex="-1">GitHub’s use of details <a class="direct-link" href="https://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/#github%E2%80%99s-use-of-details" aria-hidden="true">#</a></h2>
<p>Back in 2019, GitHub caused a flutter by <a href="https://twitter.com/muanchiou/status/1091331877636661249">going all-in on <code><details></code></a> to make various interesting UI elements interactive without JS. <a href="https://twitter.com/muanchiou">Muan</a> has co-created a number of components for Github where <code><details></code> is used to, for example, open menus. They also <a href="https://github.com/muan/details-on-details">shared notes from a talk on this subject</a>. And <a href="https://css-tricks.com/using-details-for-menus-and-dialogs-is-an-interesting-idea/">Chris Coyier for one was impressed and intrigued</a>.</p>
<h2 id="zach-leatherman%E2%80%99s-details-utils" tabindex="-1">Zach Leatherman’s details-utils <a class="direct-link" href="https://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/#zach-leatherman%E2%80%99s-details-utils" aria-hidden="true">#</a></h2>
<p>I’ve <a href="https://fuzzylogic.me/posts/web-components-as-progressive-enhancement-by-cloud-four/">previously noted</a> Zach Leatherman’s <a href="https://www.zachleat.com/web/details-utils/">details-utils</a> – a great example of using a web component to enhance an existing HTML element, in this case <code><details></code>. The enhancements include:</p>
<ul>
<li>animated open/close</li>
<li>a quantum aspect ideal for responsive design – closed by default on narrow screens, open by default on wide</li>
<li>and more</li>
</ul>
<p>And Zach has already used it on the navigation menus on <a href="https://jamstack.org/">jamstack.org</a> and <a href="https://www.netlify.com/">netlify.com</a>, amongst other use cases.</p>
<h2 id="notes-of-caution" tabindex="-1">Notes of caution <a class="direct-link" href="https://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/#notes-of-caution" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.matuzo.at/blog/2023/details-find-in-page/">The details element and in-page search</a> by Manuel Matuzovic</li>
<li><a href="https://cloudfour.com/thinks/a-details-element-as-a-burger-menu-is-not-accessible/">A details element as a burger menu is not accessible</a> on Cloud Four’s blog</li>
<li><a href="https://www.scottohara.me//blog/2022/09/12/details-summary.html">The details and summary elements, again</a> by Scott O’Hara</li>
<li><a href="https://adrianroselli.com/2020/05/disclosure-widgets.html">Disclosure widgets by Adrian Roselli</a></li>
<li><a href="https://adrianroselli.com/2019/04/details-summary-are-not-insert-control-here.html">Details and summary are not…</a></li>
<li><a href="https://adrianroselli.com/2019/04/details-summary-are-not-insert-control-here.html#comment-208747">Details content showing up in find (Ctrl+F)</a></li>
</ul>
<h2 id="alternative-approaches" tabindex="-1">Alternative approaches <a class="direct-link" href="https://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/#alternative-approaches" aria-hidden="true">#</a></h2>
<p>Using a custom disclosure widget put together with JavaScript and ARIA is not the end of the world. In fact I recently tried my hand at a <a href="https://fuzzylogic.me/posts/my-first-web-component-a-disclosure-widget/">disclosure widget web component</a> and early impressions are that the combination of fast, async ES modules plus native DOM discovery (which you get with web components) might alleviate the “flicker of content” issue I mentioned at the start.</p>
<h2 id="summing-up" tabindex="-1">Summing up <a class="direct-link" href="https://fuzzylogic.me/posts/does-the-html-details-element-solve-progressively-enhanced-disclosures/#summing-up" aria-hidden="true">#</a></h2>
<p>I’d been cautious about using <code>details</code> for more than cases matching its intended usage but had started thinking the time was right to take it further – possibly using Zach’s web component. However based on the findings shared in the above <em>Notes of caution</em> section I’ve decided to stay safe to keep the user experience predictable and accessible. The behaviour when the user does an in-page search, and the current browser inconsistencies in announcing the <code>summary</code> as an expand/collapse button tell me that a custom JS and ARIA disclosure widget is better for the custom UI cases.</p>
Min-Max clamp calculator, by 9elements2022-05-28T20:37:13Zhttps://fuzzylogic.me/posts/min-max-clamp-calculator-by-9elements/<p>Here’s a handy tool from the smart folks at 9elements for making a value – such as a font-size, or margin – <em>fluidly responsive</em>. In their words the tool…</p>
<blockquote>
<p>calculates the CSS clamp formula to interpolate between two values in a given viewport range.</p>
</blockquote>
<p>It’s inspired by <a href="https://utopia.fyi/">Utopia</a> but is for situations when you only need a single clamp formula rather than one for each interval in a type or spacing scale.</p>
<p>Beyond that, the website for this tool just looks great and is choc-full of tricks. It uses some snazzy CSS, includes <a href="https://www.zachleat.com/web/details-utils/">Zach Leatherman’s details-utils web component</a> for animated disclosures and is <a href="https://github.com/9elements/min-max-calculator">made with</a> Astro, Svelte and PostCSS.</p>
A better birthday input, by Vitaly Friedman2022-05-27T19:11:33Zhttps://fuzzylogic.me/posts/a-better-birthday-input-by-vitaly-friedman/<p>I recently signed up to Vitaly from Smashing Mag’s <em>Smart Interface Design Patterns</em> newsletter. This latest edition regarding “date of birth” inputs was interesting, and well timed as my work colleagues and I are about to revisit our form patterns. It’s a nice explainer on why we should approach UI for dates the user <em>knows</em> differently from UI for dates the user will <em>choose</em>.</p>
<p>Vitaly recommends that when asking the user for a very specific date that they already know without needing to consult a calendar, drop-downs and calendar look-ups are unnecessary. And avoiding them is probably ideal, because <code><input type=date></code> and <code><select></code> based interfaces have some usability and accessibility kinks, as do many date-picker libraries.</p>
<p>It’s better to rely on three simple, adjacent <em>text input</em> fields with a label above each field. See <a href="https://design-system.service.gov.uk/components/date-input/">GOV.UK’s Date input component</a> for a great example.</p>
<p>Date pickers should only be required when you’re asking for a date that the user will <em>choose</em> (say, booking a holiday or appointment) rather than one they’ll <em>know</em>. Vitaly doesn’t recommend a date picker, but I reckon the <a href="https://github.com/duetds/date-picker">date-picker web component</a> from the clever folks behind the Duet Design System could be a good option.</p>
<p>Oh, and this also reminds me that I need to get the finger out and pick up a copy of Adam Silver’s <a href="https://formdesignpatterns.com/">Form Design Patterns</a>.</p>
Interactive type tutorial, from Erik Kennedy2022-05-25T11:11:15Zhttps://fuzzylogic.me/posts/interactive-type-tutorial-from-erik-kennedy/<p>Here’s a handy interactive tool for learning “the logic of great typography” from Erik Kennedy, the man behind the <em>Learn UI Design</em> course.</p>
Tables and pseudo-tables: lessons and tactics2022-05-21T13:55:51Zhttps://fuzzylogic.me/posts/tables-and-pseudo-tables-lessons-and-tactics/<p>At work I have to think about complex HTML tables a lot. The challenge with doing tables well is that 99% of online table tutorials use fairly simple examples… whereas in reality design and product teams often want to squeeze in lots more. It’s really hard to balance those needs against accessibility, systemisation, styling and responsiveness.</p>
<p>Heads up: I’ve published this post early while it’s still a work in progress because it’s better for me to have it available for reference than languishing in drafts and forgotten. Apologies if you read it in a temporarily rough state.</p>
<p>Following a lot of work on tables I’ve recently gained additional insight into the possibilities and constraints, thanks to an accessibility review by <a href="https://tetralogical.com/">Tetralogical</a> and some great articles by <a href="https://adrianroselli.com/">Adrian Roselli</a>.</p>
<p>Here are my new rules of thumb.</p>
<h2 id="avoid-complex-recreations-of-tables-with-alternate-elements" tabindex="-1">Avoid complex recreations of tables with alternate elements <a class="direct-link" href="https://fuzzylogic.me/posts/tables-and-pseudo-tables-lessons-and-tactics/#avoid-complex-recreations-of-tables-with-alternate-elements" aria-hidden="true">#</a></h2>
<p>In addition to developing a component wrapping the HTML <code>table</code> element to handle simple data tables, I recently created an alternate component for “tables with bells and whistles”. It used a combination of the HTML <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl">description list</a> element plus CSS Grid plus some <code>display: contents</code> in lieu of the currently poorly supported subgrid. This approach allowed recreating a table-like appearance but facilitating much more responsive layout flexibility, amongst other benefits.</p>
<p>Unfortunately this resulted in an accessibiliy fail around using the description list in this way. Popular combinations of browsers and assistive technologies do not support description lists sufficiently to convey the intended crucial relationships between the faux table headers and faux table cells.</p>
<p>Note: I think <a href="https://tetralogical.com/blog/2022/04/29/lists/">it’s OK to use the description list element</a> in general – just not for such an unconventional and complex use case.</p>
<h2 id="aria-grid-role%3A-an-alternative-in-theory-(if-not-in-practice)" tabindex="-1">ARIA Grid role: an alternative in theory (if not in practice) <a class="direct-link" href="https://fuzzylogic.me/posts/tables-and-pseudo-tables-lessons-and-tactics/#aria-grid-role%3A-an-alternative-in-theory-(if-not-in-practice)" aria-hidden="true">#</a></h2>
<p>I noted that Github handle their “repository directory indexes” using the <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/grid_role">ARIA grid role</a>. Their HTML is like this (I’ve abbreviated it a touch):</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>grid<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>files<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sr-only<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>row<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>columnheader<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Type<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>columnheader<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Name<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>columnheader<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>d-none d-md-block<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Latest commit message<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>columnheader<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Commit time<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- interesting 'fake' row here --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>row<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rowheader<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>nofollow<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Go to parent directory<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css">…</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>.<span class="token entity named-entity" title=" ">&hairsp;</span>.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>gridcell<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>gridcell<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- first real row --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>row<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Box-row Box-row--focus-gray py-2 d-flex position-relative js-navigation-item navigation-focus<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>gridcell<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">…</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rowheader<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>my-file-name.md<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>gridcell<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>The commit message<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>gridcell<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>time-ago</span> <span class="token attr-name">datetime</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>2021-06-17T16:45:42Z<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>11 months ago<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>time-ago</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- more rows go here --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>I like the idea of looking at alternatives to tables but don’t think I’d take this approach right now. Where there are lots of focusable elements it turns those multiple tab-stops into <em>one</em> (the grid is a single <em>widget</em>) which is perhaps useful for some cases, but I’ve yet to encounter them. It’d also require you to do manual focus management within the widget.</p>
<p>It’s an interesting approach though, and one I’ll keep in the back of my mind.</p>
<h2 id="you-can-achieve-%E2%80%9Cbells-and-whistles%E2%80%9D-within-a-table-accessibly" tabindex="-1">You can achieve “bells and whistles” within a table accessibly <a class="direct-link" href="https://fuzzylogic.me/posts/tables-and-pseudo-tables-lessons-and-tactics/#you-can-achieve-%E2%80%9Cbells-and-whistles%E2%80%9D-within-a-table-accessibly" aria-hidden="true">#</a></h2>
<p>Here are some handy techniques – done accesibly – courtesy of Adrian Roselli:</p>
<ul>
<li><a href="https://adrianroselli.com/2019/05/uniquely-labeling-fields-in-a-table.html">Accessibly including inputs in tables</a></li>
<li><a href="https://adrianroselli.com/2020/11/under-engineered-responsive-tables.html">Under-engineered responsive tables</a></li>
<li><a href="https://adrianroselli.com/2017/11/a-responsive-accessible-table.html">Responsive accessible tables</a> – this more complex approach employs JavaScript to i) apply appropriate ARIA roles to existing table HTML, and ii) create clever alternate labelling using pseudo elements. It uses CSS to change the <code>display</code> of the table and its children to create a small-screen-friendly layout. The JS-applied roles serve to maintain the necessary semantics that would otherwise be lost when applying the radical CSS changes.</li>
<li><a href="https://codepen.io/pixelchar/pen/rNaKLM">Charlie Cathcart’s responsive table</a> is similar to the above although perhaps less comprehensive. However it might have other interesting aspects.</li>
<li><a href="https://adrianroselli.com/2016/02/keyboard-and-overflow.html">Clip long, overflowing content</a></li>
<li><a href="https://adrianroselli.com/2019/09/table-with-expando-rows.html">Expandable rows</a></li>
<li><a href="https://adrianroselli.com/2020/01/fixed-table-headers.html">Fixed headers</a></li>
</ul>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/tables-and-pseudo-tables-lessons-and-tactics/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://sarahmhigley.com/writing/grids-part1/">Grids pt1: To grid or not to grid</a> by Sarah Higley</li>
<li><a href="https://adrianroselli.com/2020/07/aria-grid-as-an-anti-pattern.html">ARIA Grid as an anti-pattern</a> by Adrian Roselli</li>
</ul>
Layering elements with Grid rather than positioning2022-05-15T11:42:39Zhttps://fuzzylogic.me/posts/using-css-grid-instead-of-absolute-positioning/<p>A while back I bookmarked Michelle Barker’s <a href="https://fuzzylogic.me/posts/2021-01-06-a-utility-class-for-covering-elements-on-css-in-real-life/">CSS Grid based overlay technique</a> which neatly allows layering one element atop another using CSS Grid rather than absolute positioning. Now, Stephanie Eckles has taken the idea a step further with her <a href="https://smolcss.dev/#smol-stack-layout">Smol Stack Layout</a> which offers a more flexible markup structure, some intuitive grid area naming and a neat <code>aspect-ratio</code> API.</p>
<p>Stephanie’s component is feature-packed and opinionated to the extent that it took me a while to understand all the moving parts. So for simplicity I’ve created a pared-back version on CodePen: see <a href="https://codepen.io/fuzzylogicx/pen/XWZNqqo">Layering utility with CSS Grid</a>.</p>
<p>While Michelle’s utility kept the markup really simple with the container doubling-up as the first visual “layer in the cake”, I think for flexibility and robustness I prefer Stephanie’s approach where the container only serves to set the aspect ratio, with the <em>layers</em> represented by two or more child elements.</p>
<h2 id="layering-text-upon-images" tabindex="-1">Layering text upon images <a class="direct-link" href="https://fuzzylogic.me/posts/using-css-grid-instead-of-absolute-positioning/#layering-text-upon-images" aria-hidden="true">#</a></h2>
<p>In <a href="https://smolcss.dev/#smol-background-picture">Smol background picture</a>, Stephanie goes further, leaning on her layering utility to cleverly layer text upon images. This is a modern alternative to the type of effect we previously achieved with background images. It uses a content image marked up using <code><picture></code> to progressively enhance the format (heavier-weight <code>jpg</code> for old browsers, lightweight <code>webp</code> for new browsers) and is styled with <code>object-fit: cover</code> in order to perfectly span its container.</p>
<p>This modern approach is great because often from an accessibility perspective our background images should really be <em>content</em>, described properly with <code>alt</code>, to provide equivalent visual and non-visual experiences. Furthermore using a content image tends to be better for performance with there now being so many new image techniques and attributes at our disposal when compared to background images. Lastly, handling the image as content makes it more flexible for styling.</p>
<h2 id="using-grid-for-a-%E2%80%9Chero%E2%80%9D-banner" tabindex="-1">Using Grid for a “Hero” Banner <a class="direct-link" href="https://fuzzylogic.me/posts/using-css-grid-instead-of-absolute-positioning/#using-grid-for-a-%E2%80%9Chero%E2%80%9D-banner" aria-hidden="true">#</a></h2>
<p>Another noteworthy member of this family of techniques from Stephanie is her <a href="https://moderncss.dev/3-popular-website-heroes-created-with-css-grid-layout/">Hero with CSS Grid</a>. Here she uses the same idea of a single grid-template-area with child <em>content</em> and <em>image</em> stacked up in layers, alongside some nifty use of grid positioning properties to align elements within that. This one is very flexible, very responsive, and super-useful.</p>
<h2 id="summing-up" tabindex="-1">Summing up <a class="direct-link" href="https://fuzzylogic.me/posts/using-css-grid-instead-of-absolute-positioning/#summing-up" aria-hidden="true">#</a></h2>
<p>I really like this move away from absolute positioning because it always felt brittle. It doesn’t play well with responsive layouts, and isn’t resilient to cases where adjacent elements could overlap. Furthermore you often see absolute positioning used in conjunction with pseudo elements and while I’ve occasionally taken this approach (and appreciate the creativity behind these techniques) I’ll admit I find it much easier to read and maintain CSS that relates to actual structural elements rather than “magical” CSS elements. I much prefer these simple, modern and fit-for-purpose CSS Grid based approaches.</p>
Improved focus indicators for keyboard navigation (on GitHub’s blog)2022-04-29T08:38:48Zhttps://fuzzylogic.me/posts/improved-focus-indicators-for-keyboard-navigation-on-github-s-blog/<p>GitHub have recently done some good work on improving keyboard navigation for (and general usability of) their focusable elements such as links, buttons and form controls by improving focus indication. And then they wrote a short-but-sweet article about it, then <a href="https://twitter.com/KatieLangerman/status/1519397715859312640">tweeted to share that</a> and their work is getting lots of positive recognition from all the right people. Nice job all round, GitHub!</p>
<p>Incidentally, that article they wrote really is <em>very</em> short. Maybe they’ll add to it later. The animated gif they include is very descriptive, mind you. And I noticed that they added the following <code>alt</code> text to it:</p>
<blockquote>
<p>Animated gif of a customer using their keyboard to navigate a pull request, interactive UI elements receive a blue focus outline to show current location on the page. Key presses are shown in the bottom center of the image.</p>
</blockquote>
<p>That feels like a good non-visual alternative description to me.</p>
Web components as progressive enhancement, by Cloud Four2022-04-25T09:29:43Zhttps://fuzzylogic.me/posts/web-components-as-progressive-enhancement-by-cloud-four/<blockquote>
<p><em>By enhancing native HTML instead of replacing it, we can provide a solid baseline experience, and add progressive enhancement as the cherry on top.</em></p>
</blockquote>
<p>Great article by Paul Herbert of Oregon’s Cloud Four. Using a web component to enhance an existing HTML element such as <code><textarea></code> (rather than always creating a custom element from scratch) feels very lean, resilient and maintainable.</p>
<p>Off the top of my head I could see this being a nice approach for other custom form controls.</p>
<p><a href="https://www.zachleat.com/web/details-utils/">Zach Leatherman also took this approach with the <code><details></code> element</a> in quite exciting ways and is using it in production on Netlify’s marketing websites. I’m a bit cautious of jumping on that one just yet, though, because it’s plays more fast-and-loose with the intended purpose of the element and in so doing probably might present some accessibility issues. Still really interesting though.</p>
<p><a href="https://adactio.com/links/19001">Thanks to @adactio for sharing.</a></p>
A front-end developer’s job2022-04-24T09:14:53Zhttps://fuzzylogic.me/posts/a-front-end-developer-s-job/<p>Recently I’ve been reflecting on what we front-end developers do in the modern era. Working on a design system in 2022, I feel now more than ever that my job represents a convergence of a range of interesting disciplines, goals, skills and experiences. These include UX knowledge and usability testing, a degree of design savvy, systems and atomic thinking, accessibility knowledge and strong skills with the core web standards. That’s my understanding of front-end development.</p>
<p>Yet not long ago a colleague recalled the time a teammate teased him that front-end developers “put the froth on the cappuccino”. While this gave us all a laugh, I imagine it also reflects one common misunderstanding and undervaluing of our role.</p>
<p>Meanwhile there’s another image of front-end development that’s very engineering rather than user experience oriented. This focuses on JavaScript and tooling and arose in the era of NPM and JavaScript frameworks. In this definition, front-end developers spend their time wrangling JavaScript, configuring build tools and manipulating API data.</p>
<p>I’m conscious of <a href="https://css-tricks.com/the-great-divide/">the great divide</a> and while my career has straddled that divide, I’ll freely admit that at heart I’m <a href="https://bradfrost.com/blog/post/front-of-the-front-end-and-back-of-the-front-end-web-development/">a front of the front-ender</a>.</p>
<p>Here’s a description of a “Design System engineer” that I recently compiled during while my team were recruiting for a software engineer:</p>
<ul>
<li>Very strong knowledge and understanding of the core web standards: HTML, CSS and JavaScript</li>
<li>Strong appreciation of the need for appropriate HTML semantics to achieve resilience and accessibility</li>
<li>Understands component-based architecture and delivery including concepts like atomic design, composition, variants and versioning</li>
<li>Advanced understanding of web accessibility including how to create accessible interactive components</li>
<li>Excellent attention to detail in implementing designs in code</li>
<li>Strong appreciation of responsive / multi-device considerations</li>
<li>Comfortable in modern CSS including BEM-like methodologies, ITCSS architecture, and modern approaches such as Flexbox, CSS Grid, custom properties</li>
<li>Some experience in testing JavaScript and/or server-side components<br />
- Comfortable with Git</li>
<li>Committed to constantly learning and improving technical knowledge and skills</li>
</ul>
<p>Something else I remember noting down was that:</p>
<blockquote>
<p>User interfaces should be user-centric, purpose-driven, appropriate, accessible and consistent (not arbitrary).</p>
</blockquote>
<p>I guess my point there was that good front-end developers build user interfaces in a very considered manner.</p>
<h2 id="areas-of-interest" tabindex="-1">Areas of interest <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#areas-of-interest" aria-hidden="true">#</a></h2>
<p>Here are some of the key areas I find myself thinking about or working on regularly.</p>
<h3 id="accessibility" tabindex="-1">Accessibility <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#accessibility" aria-hidden="true">#</a></h3>
<p>I list this first not due to alphabetical order, but because it’s arguably the cornerstone of our job. That’s for two reasons. Firstly, because the web was designed to be accessible to all therefore it’s incumbent on us to uphold that. (Of course it’s not just <em>our</em> job, however we tend to be both the primary evangelists and last line of defence). Secondly, so many other aspects of front-end development can only be done well when you start from an accessible foundation. This is something that becomes clearer and clearer the longer you do this job.</p>
<h3 id="resilience" tabindex="-1">Resilience <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#resilience" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h3 id="performance" tabindex="-1">Performance <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#performance" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h3 id="ux" tabindex="-1">UX <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#ux" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h3 id="documentation" tabindex="-1">Documentation <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#documentation" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h3 id="adaptability" tabindex="-1">Adaptability <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#adaptability" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h3 id="design-system-considerations" tabindex="-1">Design System considerations <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#design-system-considerations" aria-hidden="true">#</a></h3>
<ul>
<li>Componentization</li>
<li>Creating component APIs</li>
<li>Composition</li>
<li>Documentation</li>
</ul>
<h3 id="scalability" tabindex="-1">Scalability <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#scalability" aria-hidden="true">#</a></h3>
<p>At scale, you can’t just write <em>new code</em> for everything. You have to focus on creating reusable things.</p>
<h3 id="maintainability-and-sustainability" tabindex="-1">Maintainability and sustainability <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#maintainability-and-sustainability" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h3 id="integration-into-the-company%E2%80%99s-language-framework" tabindex="-1">Integration into the company’s language framework <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#integration-into-the-company%E2%80%99s-language-framework" aria-hidden="true">#</a></h3>
<p>This can be challenging. I might add more about this later.</p>
<h3 id="adding-interactivity" tabindex="-1">Adding interactivity <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#adding-interactivity" aria-hidden="true">#</a></h3>
<p>I might add more about this later.</p>
<h2 id="adherence-to-designs%2C-and-making-things-look-good." tabindex="-1">Adherence to designs, and making things look good. <a class="direct-link" href="https://fuzzylogic.me/posts/a-front-end-developer-s-job/#adherence-to-designs%2C-and-making-things-look-good." aria-hidden="true">#</a></h2>
<p>I might add more about this later.</p>
April 2022 mixtape2022-04-18T14:18:08Zhttps://fuzzylogic.me/posts/april-2022-mixtape/<p>I put together a fairly spacey and mellow selection of laidback electronic sounds with a little nod to summer.</p>
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_avif,q_55,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/f_webp,q_55,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/fuzzylogic/image/upload/f_jpg,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg" width="1292" height="1292" alt="Side A of the 7-inch vinyl release of Mato’s “Summer Madness" loading="lazy" decoding="async" />
</picture>
<figcaption>Mato’s “Summer Madness”, as featured on the mix</figcaption>
</figure>
<p><a href="https://drive.google.com/uc?export=download&id=1xdHzCc-GyrRr40Yp-dUp6yYTXkCSOpvf">Download my April 2022 mixtape.</a></p>
<p>Here’s the tracklist:</p>
<ul>
<li>Nale Sinephro - Space 1</li>
<li>Culross Close - To Belong</li>
<li>Other Lands - Matter (Reshaped)</li>
<li>Mato – Summer Madness</li>
<li>Desmond Chambers – Haly Gully</li>
<li>Tom Churchill – Cast adrift</li>
<li>Bright & Findlay — Slow Dance</li>
<li>Quiet Force — Listen To The Music (Apiento & Tepper Mix)</li>
<li>Fuga Ronto – Columbo De Domingo</li>
<li>dreamcastmoe — l foot right</li>
<li>Lord of the isles — Novwo</li>
<li>Kofi B - Mmobrowa (Hagan Edit)</li>
<li>State of grace — That’s when we’ll be free</li>
</ul>
<p>This was a nice opportunity to get back into the rhythm of programming music of varying styles and tempos. Kit-wise, I used two Technics 1210s, a Pioneer XDJ-700, an Isonoe 420 mixer and an Eventide Timefactor delay.</p>
I’ve started reading The 15 Minute City, by Natalie Whittle.2022-04-14T10:00:00Zhttps://fuzzylogic.me/posts/i-ve-started-reading-the-15-minute-city-by-natalie-whittle/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781910022474">The 15 Minute City</a>, by Natalie Whittle.</p>
Improving alternative text for images2022-03-10T09:23:55Zhttps://fuzzylogic.me/posts/improving-alternative-text-for-images/<p>Some colleagues at work have recently been asking interesting questions about “good/appropriate alternative text for images”. I definitely reckon it’s a topic worth revisiting because it feels like the landscape has changed a bit on this front over the years.</p>
<p>I think the web design industry has traditionally been:</p>
<ol>
<li>lacking knowledge of how to write good alternative text.</li>
<li>too quick to decide which images are “purely decorative”, or accurately described by a matter-of-fact short label when maybe they actually should convey their inherent tone and emotion to all users rather than only those with no visual impairments.</li>
</ol>
<p>But as inclusion-centric practioners we can probably do better. In his blog post <a href="https://jakearchibald.com/2021/great-alt-text/">Writing great alt text</a> Jake Archibald breaks down the considerations. I reckon it’d be useful for us to dissect this post and try to boil it down to some practical rules-of-thumb for our teams.</p>
<p>But also, I’ve just noticed a couple of interesting developments at the big players. Firstly, <a href="https://twitter.com/TwitterA11y/status/1501603777006260226">Twitter have upped their image <code>alt</code> game</a> and are encouraging their users to try doing so, too.</p>
<p>And hot on the heels of Twitter’s announcement, I now see in Slack an <em>Edit file details</em> option for adding image descriptions. It’s great that Twitter and Slack are doing this… and also serves as a reminder that tools such as Slack and Twitter are consumed on the web and so accessible best practices apply when you’re writing content on them, too!</p>
SVG: collected tips2022-03-09T17:08:12Zhttps://fuzzylogic.me/posts/svg-collected-tips/<p>SVG is an amazing technology which I regularly use for icons and occasionally for logos and illustrations. I’ve also dipped my toe into animated SVG. But if I’m honest I still find some SVG concepts confusing so I’ve gathered some useful tips here for future reference. Note: this is a living document which I’ll expand over time.</p>
<h2 id="table-of-contents" tabindex="-1">Table of contents <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#table-of-contents" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#introduction-to-svg">Introduction to SVG</a></li>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#canvas-viewport-and-viewbox">Canvas, viewport and viewbox</a></li>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#arranging-elements-on-a-grid">Arranging elements on a grid</a></li>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#inline-svg-for-icons">Inline SVG for icons</a></li>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#choose-an-svg-embedding-technique-that-suits-the-task">Choose an SVG embedding technique that suits the task</a></li>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#choose-the-best-performing-format">Choose the best-performing format</a></li>
<li><a href="https://fuzzylogic.me/posts/svg-collected-tips/#exporting-and-optimising-svg-in-design-tools">Exporting and optimising SVG in design tools</a></li>
</ul>
<h2 id="introduction-to-svg" tabindex="-1">Introduction to SVG <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#introduction-to-svg" aria-hidden="true">#</a></h2>
<p>It’s an image format (like jpg and png) but also an XML-based markup language. So it’s a bit like HTML in that you can “compose a whole from a bunch of parts” – but it is focused on graphics. As a web graphics technology it has many benefits, for example:</p>
<ul>
<li>scalable,</li>
<li>manipulable by CSS and JS,</li>
<li>has a small file-size if well-optimised, and</li>
<li>can be made accessible.</li>
<li>It’s built for drawing in a way HTML and CSS are not.</li>
<li>It can guide users, reduce their cognitive load, and provide personality and moments of fun.</li>
</ul>
<p>Here’s a classic example: <a href="https://codepen.io/dsenneff/pen/2c3e5bc86b372d5424b00edaf4990173">Log-in Avatar</a></p>
<h2 id="canvas%2C-viewport-and-viewbox" tabindex="-1">Canvas, viewport and viewBox <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#canvas%2C-viewport-and-viewbox" aria-hidden="true">#</a></h2>
<p>Let’s break down the key elements of the SVG coordinate system.</p>
<h3 id="canvas" tabindex="-1">Canvas <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#canvas" aria-hidden="true">#</a></h3>
<p>The canvas is the area where the SVG content is drawn. It’s infinite in both dimensions therefore the SVG can be any size.</p>
<h3 id="viewport" tabindex="-1">Viewport <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#viewport" aria-hidden="true">#</a></h3>
<p>Although the canvas is infinite, the SVG is rendered on the screen relative to a finite region known as the viewport. Areas of the SVG that lie beyond the boundaries of the viewport are not visible. This is similar to a browser viewport. On a long page you don’t see all the content; just a portion of it.</p>
<p>Specify the viewport size by giving your <code><svg></code> element a width and height, e.g.:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>600<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>400<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- svg content --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>We <em>could</em> specify units (such as <code>em</code> or <code>px</code>) but don’t need to. Unitless values are regarded as being set in <em>user space</em> using <em>user units</em> which effectively equate to pixels so our example above renders a 600px by 400px viewport.</p>
<p>The width of the viewport can also be set in CSS. Setting <code>width:100%</code> makes the SVG viewport fluid in a given container.</p>
<h3 id="viewbox" tabindex="-1">Viewbox <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#viewbox" aria-hidden="true">#</a></h3>
<p>The <em>viewport coordinate system</em> starts at the top left (0, 0) corner of the SVG viewport. The <em>user coordinate system</em> is by default identical to that of the viewport, starting in the same place and with equal dimensions and units, however it can be modified using the <code>viewBox</code> attribute.</p>
<p><code>viewBox</code> takes a value in the format: <code>x y width height</code>. The first two values set the upper-left corner of the viewbox and the second two its dimensions.</p>
<p>You can set the aspect ratio of the viewbox to the same as for the SVG viewport, or differently.</p>
<p>You might (optionally) use the <code>viewBox</code> attribute to <em>transform</em> the SVG graphic by scaling or translating it, or to <em>crop</em> it.</p>
<p>Specifying a smaller viewbox than viewport results in cropping the graphic to those dimensions and then zooming it in i.e. scaling it up so that it fills the entire viewport area.</p>
<h2 id="arranging-elements-on-a-grid" tabindex="-1">Arranging elements on a grid <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#arranging-elements-on-a-grid" aria-hidden="true">#</a></h2>
<p><a href="https://www.cassie.codes/posts/swipey-image-grids/">Cassie Evans recommends</a> that when planning an arrangement of elements it’s nice to start with a simple grid using nice round numbers such as 100×100 – per the following <code><svg></code> – making it easy to then plot elements on top. You might even start by sketching with paper and pencil.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">viewBox</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0 0 100 100<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- svg content, perhaps <rect>s --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span></code></pre>
</figure>
<figure>
<img style="margin-inline: auto;" src="https://res.cloudinary.com/fuzzylogic/image/upload/v1652611257/wepik-2022415-113410_zouman.jpg" />
<figcaption>100×100 grid sketched on <a href="https://www.freepik.com/photos/square-paper">Kues’ graph paper photo</a></figcaption>
</figure>
<h2 id="inline-svg-for-icons" tabindex="-1">Inline SVG for icons <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#inline-svg-for-icons" aria-hidden="true">#</a></h2>
<p>Having tried various icon systems including using <code><symbol></code> and <code><use></code>, Chris Coyier advocates that it’s perhaps simpler and better to <a href="https://css-tricks.com/pretty-good-svg-icon-system/">just include the icons inline</a>. Perhaps use the appropriate <code>include</code> technique for your stack to keep the code maintainable.</p>
<h2 id="choose-an-svg-embedding-technique-that-suits-the-task" tabindex="-1">Choose an SVG embedding technique that suits the task <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#choose-an-svg-embedding-technique-that-suits-the-task" aria-hidden="true">#</a></h2>
<p>There are a variety of flavours and uses of SVG, including:</p>
<ul>
<li>icons</li>
<li>infographics</li>
<li>illustrations</li>
<li>SVG that include text</li>
<li>SVG that include animation.</li>
</ul>
<p>As Sara Souidean covers in her talk “A Smashing Case Study”, your choice of SVG embedding technique depends on the nature of the project and the specific use case.</p>
<p>To do: summarise Sara’s technique for SVG with illustration and accessible text.</p>
<h2 id="choose-the-best-performing-format" tabindex="-1">Choose the best-performing format <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#choose-the-best-performing-format" aria-hidden="true">#</a></h2>
<p>When you’re tasked with coding an illustration-based image, it’s tempying to automatically see that as a job for SVG. However keep in mind that for some images the SVG file size will be massive and PNG will perform much better, so compare the two options.</p>
<h2 id="exporting-and-optimising-svg-in-design-tools" tabindex="-1">Exporting and optimising SVG in design tools <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#exporting-and-optimising-svg-in-design-tools" aria-hidden="true">#</a></h2>
<p>To export an SVG in Figma, right-click it (or select it on the left hand side) then select “copy as SVG”. There’s also an “export as SVG” option on the right.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/svg-collected-tips/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.sarasoueidan.com/blog/svg-coordinate-systems/">Understanding SVG Coordinate Systems</a> by Sara Soueidan</li>
<li><a href="https://www.cassie.codes/posts/swipey-image-grids/">Swipey image grids</a> by Cassie Evans</li>
<li><a href="https://css-tricks.com/pretty-good-svg-icon-system/">A pretty good icon system</a> by Chris Coyier</li>
<li><a href="https://vimeo.com/214427831">A Smashing Case Study</a> recorded presentation by Sara Souidean</li>
</ul>
Web Components with Declarative Shadow DOM via Lit and Eleventy2022-03-08T11:02:35Zhttps://fuzzylogic.me/posts/web-components-with-declarative-shadow-dom-via-lit-and-eleventy/<p>Here’s a new development in the Web Components story, and one that may have positive implications for resilience, performance and progressive enhancement.</p>
<p><a href="https://web.dev/declarative-shadow-dom/">Declarative Shadow DOM</a> is a new way to implement and use Shadow DOM directly in HTML rather than by constructing a shadow root in JavaScript.</p>
<p>But some people including Chris Coyier and Brad Frost) reckon that writing that looks horrible. <a href="https://bradfrost.com/blog/link/eleventy-lit/">Brad said</a>:</p>
<blockquote>
<p>Declarative Shadow DOM always looked gross to me and I felt it almost defeats the purpose of web components.</p>
</blockquote>
<p>And <a href="https://css-tricks.com/newsletter/290-designing-context-menus-css-presentations-and-complaining-about-web-browsers/">Chris added</a>:</p>
<blockquote>
<p>the server-side rendering story for Web Components, Declarative Shadow DOM, doesn’t feel very nice to me if you have to do it manually.</p>
</blockquote>
<p>However Lit, a library which makes working with Web Components easier, are now <a href="https://lit.dev/blog/2022-02-07-eleventy/">providing ways to make this easier when Lit is used with Eleventy</a>.</p>
<p><a href="https://bradfrost.com/blog/link/eleventy-lit/">Brad likes this:</a></p>
<blockquote>
<p>With tools like this (especially this <a href="https://github.com/lit/lit/tree/main/packages/labs/ssr">@lit-labs/ssr</a> project), we can have our cake and eat it too: use web components in a dev-friendly way, and then have the machines do the heavy lifting to convert that into a grosser-yet-progressive-enhancement-enabled syntax that ships to the user.</p>
</blockquote>
<p><a href="https://css-tricks.com/newsletter/290-designing-context-menus-css-presentations-and-complaining-about-web-browsers/">As does Chris:</a></p>
<blockquote>
<p>using JavaScript frameworks in an entirely-client-side rendered way isn’t nearly as good for anything (users, SEO, performance, accessibility, etc) as server-side rendering (the effects of hydration are still debatable, but I view as largely worth it) … [but] the server-side rendering story for Web Components, Declarative Shadow DOM, doesn’t feel very nice to me if you have to do it manually. So… don’t do it manually! Let Eleventy do it!</p>
</blockquote>
<p>As an additional footnote, perhaps we can make frameworks other than Eleventy (such as Rails) create server-rendered custom elements with Declarative Shadow DOM in a similar way. One to explore.</p>
Minimum Viable Web Component (by Zach Leatherman)2022-02-15T21:03:21Zhttps://fuzzylogic.me/posts/minimum-viable-web-component-by-zach-leatherman/<p><a href="https://twitter.com/zachleat/status/1282807913501859841">Zach tweeted</a> last year to share a codepen which illustrates the very simple boilerplate needed for a minimum viable web component. Note: his example is so simple that in this case the JavaScript isn’t actually needed for the custom element to work, however the provided JS is a starting point for when you do actually intend to add JS-driven features.</p>
<p>The HTML:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>foo-component</span><span class="token punctuation">></span></span>Hello, world<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>foo-component</span><span class="token punctuation">></span></span></code></pre>
<p>The CSS:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">foo-component</span> <span class="token punctuation">{</span><br /> <span class="token property">font-size</span><span class="token punctuation">:</span> 4em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The JS:</p>
<pre class="language-js"><code class="language-js">customElements<span class="token punctuation">.</span><span class="token function">define</span><span class="token punctuation">(</span><span class="token string">"foo-component"</span><span class="token punctuation">,</span> <span class="token keyword">class</span> <span class="token class-name">extends</span> HTMLElement <span class="token punctuation">{</span><br /> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Add your custom functionality.</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</figure>I’ve started, so I’ll panic: what it’s really like to go on Mastermind (on The Guardian)2022-02-15T21:03:21Zhttps://fuzzylogic.me/posts/i-ve-started-so-i-ll-panic-what-it-s-really-like-to-go-on-mastermind-on-the-guardian/<p>When Mastermind comes on TV, Clair and I always enjoy competing against each other to see who’s most intelligent / least stupid and always jokingly say we’d fancy our chances in real life (although we <em>really</em> wouldn’t). So I enjoyed Sirin Kale’s amusing memoir on what it’s really like to get in the famous black chair!</p>
<blockquote>
<p>It is spotlit, well worn, imposing. Its leather has been burnished by the arses of minds far greater than mine, minds capable of retaining all manner of trivia while staying cool under pressure and not panic-sweating profusely via their bum cheeks on to the seat; cellulite-free grey matter, crammed full of general knowledge like a suitcase you have to sit on to close. My mind, by comparison, is a duffel bag containing a single pair of socks.</p>
</blockquote>
GOV.UK visitor stats for January 20222022-02-09T07:56:47Zhttps://fuzzylogic.me/posts/gov.uk-visitor-stats-for-january-2022/<p>Thanks once again to Matt Hobbs and <a href="http://gov.uk/">GOV.UK</a> for sharing their website visitor stats publicly so that we can learn from them. As ever, lots of juicy detail in Matt’s thread.</p>
<blockquote>
<p><a href="https://t.co/CcU3PLPTpj">GOV.UK</a> stats for January (1-31):</p>
<p>- Chrome - 45.08%</p>
<p>- Safari - 36.82%</p>
<p>- Edge - 7.38%</p>
<p>- Samsung Internet - 7.08%</p>
<p>- Firefox - 1.35%</p>
<p>- Android Webview - 0.72%</p>
<p>- Safari (in-app) - 0.61%</p>
<p>- Internet Explorer - 0.5%</p>
<p>100% = 187,969,863</p>
<p><a href="https://twitter.com/hashtag/browserstats?src=hashtag_click">#browserstats</a></p>
</blockquote>
<p>—Matt Hobbs, <a href="https://twitter.com/TheRealNooshu">@TheRealNooshu</a></p>
<p>In particular, their “usage by device type” stats see mobile at ~67%, Desktop at ~30.5%, Tablet at ~2.5%.</p>
<p>In terms of comparative traffic, according to <a href="https://www.similarweb.com/top-websites/united-kingdom/">Simliar Web’s Top 10 most visited UK websites list</a> they’re hovering around #10.</p>
Skip to Content: Online Accessibility Insights from Léonie Watson2022-02-07T08:36:27Zhttps://fuzzylogic.me/posts/skip-to-content-online-accessibility-insights-from-leonie-watson/<p>Here’s a lovely, short (13 min) interview from an accessibility expert with a really positive outlook—highly recommended.</p>
<blockquote>
<p>Q: What’s just one thing that every single person can do in the progression toward an accessible internet?</p>
<p>A: When you’re talking to colleagues, peers… promote the notion that accessibility is just part of what we do because we’re good at our job. It’s not extraordinary, it’s not unusual, it’s not something you can drop because you’re pushing for launch.</p>
</blockquote>
Division and construction in design systems2022-02-03T08:57:00Zhttps://fuzzylogic.me/posts/division-and-construction-in-design-systems/<p>Over the last couple of days I’ve been watching <a href="https://www.youtube.com/watch?v=jR0Gefa4lpg">an interview with Brad Frost on Storybook’s channel</a>. I’m still only halfway through but it’s great so far.</p>
<p>One part I’m loving is, from about 25 mins in, when Brad talks abut how <a href="https://bradfrost.com/blog/post/atomic-web-design/">Atomic Design</a> <em>crucially</em> includes the notion of not only “breaking interfaces down” (like every DS does) but also “building them back up”. It’s not just the atoms and molecules that are important, but also combining them into (in Atomic Design parlance) organisms and templates, too. For example when using Storybook as an internal workshop (in my team our equivalent is <a href="https://github.com/allmarkedup/lookbook">LookBook</a>), he makes a point of it not just including components but also templates, so that:</p>
<blockquote>
<p>we can internally test with a high degree of confidence before handing over to our user-consumers that when our components are <em>assembled together,</em> they work”.</p>
</blockquote>
<p>I like the idea of our workshop containing not just components but also multicomponent arrangements, or even full page templates. It’d mean less need to go arrange this stuff in the consuming application all the time. Brad’s chat also chimes with some recent thoughts I’ve been having about <em>Patterns</em> and also<br />
<a href="https://twitter.com/heydonworks/status/1483127049657143297">a tweet from Heydon Pickering regarding a catalogue vs a system</a>.</p>
<p>Essentially, I think that in component libraries, notions of hierarchy and composition are really important. Simply having “a catalogue of components” (including lots that are common to all Design Systems) might not hugely separate your library from Bootstrap or Material. However it’s our ability to combine our custom legos into specific higher order arrangements, and our care for making sure they combine together harmoniously that creates our own special sauce.</p>
My talk, “Hiding elements on the web” for FreeAgent’s tech blog2022-01-19T13:08:38Zhttps://fuzzylogic.me/posts/my-talk-hiding-elements-on-the-web-for-freeagent-s-tech-blog/<p>I recorded a talk on “Hiding elements on the web” for <a href="https://twitter.com/freeagent">@freeagent</a>’s tech blog. It’s a tricky <a href="https://twitter.com/hashtag/FrontEnd?src=hashtag_click">#FrontEnd</a> & <a href="https://twitter.com/hashtag/a11y?src=hashtag_click">#a11y</a> topic so I try to cover some good practices and responsible choices. Hope it helps someone. (Also it’s my first video. Lots of room to improve!)</p>
<iframe title="Hiding elements on the web, a talk by Laurence Hughes of FreeAgent’s Design System team" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/AZ6uw4KCOQA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
What open-source design systems are built with web components?2022-01-19T09:33:15Zhttps://fuzzylogic.me/posts/what-open-source-design-systems-are-built-with-web-components/<p>Alex Page, a Design System engineer at Spotify, has just asked:</p>
<blockquote>
<p>What open-source design systems are built with web components? Anyone exploring this space? Curious to learn what is working and what is challenging. <a href="https://twitter.com/hashtag/designsystems?src=hashtag_click">#designsystems</a> <a href="https://twitter.com/hashtag/webcomponents?src=hashtag_click">#webcomponents</a></p>
</blockquote>
<p>And there are lots of interesting examples in the replies.</p>
<p>I plan to read up on some of the stories behind these systems.</p>
<p>I really like Web Components but given that I don’t take a “JavaScript all the things” approach to development and design system components, I’ve been reluctant to consider that web components should be used for <em>every component</em> in a system. They would certainly offer a lovely, HTML-based interface for component consumers and offer interoperability benefits such as Figma integration. But if we shift all the business logic that we currently manage on the server to client-side JavaScript then:</p>
<ul>
<li>the user pays the price of downloading that additional code;</li>
<li>you’re writing client-side JavaScript even for those of your components that aren’t interactive; and</li>
<li>you’re making <em>everything</em> a custom element (which as Jim Neilsen has previously written <a href="https://blog.jim-nielsen.com/2021/custom-elements-without-js/">brings HTML semantics and accessibility challenges</a>).</li>
</ul>
<p>However maybe we can keep the JavaScript for our Web Component-based components really lightweight? I don’t know. For now I’m interested to just watch and learn.</p>
My first Web Component: a disclosure widget2022-01-18T16:05:04Zhttps://fuzzylogic.me/posts/my-first-web-component-a-disclosure-widget/<p>After a couple of years of reading about web components (and a lot of head-scratching), I’ve finally got around to properly creating one… or at least a rough first draft!</p>
<p><a href="https://codepen.io/fuzzylogicx/pen/MWERKQo/?editors=1010">Check out disclosure-widget on codepen.</a></p>
<p>See also <a href="https://codepen.io/fuzzylogicx/pen/MWERbPZ">my pen which imports and consumes the component.</a></p>
<p>Caveats and to-dos:</p>
<ul>
<li>I haven’t yet tried writing tests for a web component</li>
<li>I should find out how to refer to the custom element name in JavaScript without repeating it</li>
<li>I should look into whether <code>observedAttributes</code> and <code>attributeChangedCallback</code> are more appropriate than the more typical event listeners I used</li>
</ul>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/my-first-web-component-a-disclosure-widget/#references" aria-hidden="true">#</a></h2>
<p>I found Eric Bidelman’s article <a href="https://developers.google.com/web/fundamentals/web-components/customelements">Custom Elements v1: Reusable Web Components</a> pretty handy. In particular it taught me how to create a <code><template></code> including a <code><slot></code> to automatically ringfence the Light DOM content, and then to attach that template to the Shadow DOM to achieve my enhanced component.</p>
Saving CSS changes in DevTools without leaving the browser2022-01-15T10:56:35Zhttps://fuzzylogic.me/posts/saving-css-changes-in-devtools-without-leaving-the-browser/<p><a href="https://twitter.com/scottjehl/status/1478919359070445568">Scott Jehl recently tweeted:</a></p>
<blockquote>
<p>Browser devtools have made redesigning a site such a pleasure. I love writing and adjusting a CSS file right in the sources panel and seeing design changes happen as I type, and saving it back to the file. (…) Designing against live HTML allows happy accidents and discoveries to happen that I wouldn't think of in an unconstrained design mockup</p>
</blockquote>
<p>I feel very late to the party here. I tend to tinker in the DevTools Element Styles panel rather than save changes. So, inspired by Scott, I’ve just tried this out on my personal website. Here’s what I did.</p>
<ol>
<li>started up my 11ty-based site locally which launches a <code>localhost</code> URL for viewing it in the browser;</li>
<li>opened Chrome’s DevTools at <em>Sources;</em></li>
<li>checked the box “Enable local overrides” then followed the prompts to allow access to the folder containing my SCSS files;</li>
<li>opened an SCSS file in the Sources tab for editing side-by-side with my site in the browser;</li>
<li>made a change, hit <kbd>Cmd-S</kbd> to save and marvelled at the fact that this updated that file, as confirmed by a quick <code>git status</code> check.</li>
<li>switched to the <em>Elements</em> panel, opened its <em>Styles</em> subpanel, made an element style change there too, then confirmed that this alternative approach also saves changes to a file.</li>
</ol>
<p>This is a <em>really</em> interesting and efficient way of working in the browser and I can see me using it.</p>
<p>There are also a couple of challenges which I’ll probably want to consider. Right now when I make a change to a Sass file, the browser takes a while to reflect that change, which diminishes the benefit of this approach. My site is set up such that Eleventy watches for changes to the sass folder as a trigger for rebuilding the static site. This is because for optimal performance I’m purging the compiled and combined CSS and inlining that into the <code><head></code> of every file… which unfortunately means that when the CSS is changed, every file needs rebuilt. So I need to wait for Eleventy to do its build thing until the page I’m viewing shows my CSS change.</p>
<p>To allow my SCSS changes to be built and reflected faster I might consider no longer inlining CSS, or only inlining a small amount of critical stuff… or maybe (as best of all worlds) only do the inlining for production builds but not in development. Yeah, I like that latter idea. Food for thought!</p>
Partnering with Google on web.dev (on adactio.com)2022-01-14T09:02:28Zhttps://fuzzylogic.me/posts/partnering-with-google-on-web.dev-on-adactio.com/<p>At work in our Design System team, we’ve been doing a lot of content and documentation writing for a new reference website. So it was really timely to read Jeremy Keith of Clearleft’s new post on the process of writing <a href="https://web.dev/learn/design/">Learn Responsive Design</a> for Google’s <a href="http://web.dev/">web.dev</a> resource. The course is great, very digestible and I highly recommend it to all. But I also love this new post’s insight into how Google provided assistance, provided a <a href="https://web.dev/handbook/">Content handbook</a> as “house style” for writing on web.dev and managed the process from docs and spreadsheets to Github. I’m sure there will be things my team can learn from that Content Handbook as we go forward with our technical writing.</p>
Theming to optimise for user colour scheme preference2022-01-01T19:39:48Zhttps://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/<p>“Dark mode” has been a buzz-phrase in web development since around 2019. It refers to the ability provided by modern operating systems to set the user interface’s appearance to either light or dark. Web browsers and technologies support this by allowing developers to detect whether or not the OS provides such settings, and if so which mode the user prefers. Developers can create alternate light and dark <em>themes</em> for their websites and switch between these intelligently (responsively?) to fit with the user’s system preference.</p>
<p>I’ve been meaning to do some work on this front for a while and finally got around to it. (You might even be reading this post with your computer’s dark colour scheme enabled and seeing the fruits of my labour.) Here’s how I set things up and the lessons I learned along the way.</p>
<h2 id="switching-your-computer%E2%80%99s-appearance" tabindex="-1">Switching your computer’s appearance <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#switching-your-computer%E2%80%99s-appearance" aria-hidden="true">#</a></h2>
<p>On a Mac:</p>
<p><kbd class="block">System Preferences > General > Appearance</kbd></p>
<p>On Windows:</p>
<p><kbd class="block">Colors > Choose your color</kbd></p>
<p>On iOS:</p>
<p><kbd class="block">Settings > Display & Brightness > Appearance</kbd></p>
<p>On Android:</p>
<p><kbd class="block">Settings > Dark Theme</kbd></p>
<h2 id="emulating-this-in-browser-devtools" tabindex="-1">Emulating this in browser DevTools <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#emulating-this-in-browser-devtools" aria-hidden="true">#</a></h2>
<p>In Chromium-based browsers you can open DevTools, then open the <code>Rendering</code> tool (which might be hidden behind <em>More Tools</em>). In the <em>Emulate CSS media feature prefers-color-scheme</em> dropdown, select <em>prefers-color-scheme: dark</em> or <em>prefers-color-scheme: light</em>.</p>
<h2 id="the-theme-color-html-meta-tag" tabindex="-1">The theme-color HTML meta tag <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#the-theme-color-html-meta-tag" aria-hidden="true">#</a></h2>
<p>You can use the <code>theme-color</code> HTML meta tag to indicate to the browser a colour it can use to customise the display of the page and surrounding elements such as the address bar. The reason we have a meta tag solution to this rather than leaving it to CSS is <em>performance</em>; it allows the browser to make the relevant updates immediately.</p>
<p>In practice you might specify your “highlight colour”—<a href="https://clearleft.com/">Clearleft</a> currently use their signature green. Alternatively you could specify both your <em>light theme</em> and <em>dark theme</em> background colours, using the <code>media</code> attribute to associate each with the user colour scheme preference it is optimised for. This is the approach I chose.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- Set theme color to white when user prefers light mode --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>theme-color<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rgb(255,255,255)<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(prefers-color-scheme: light)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token comment"><!-- Set theme color to a custom black when user prefers dark mode --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>theme-color<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rgb(38,38,38)<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(prefers-color-scheme: dark)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
</figure>
<p><a href="https://caniuse.com/?search=meta%20theme-color">The theme-color meta tag has mixed support</a>. It works well in Safari and iOS Safari. Meanwhile Chrome only applies the colour on installed progressive web apps (PWAs).</p>
<p>This had me considering PWA matters again for the first time in a while. I previously definined a PWA “theme colour” for my website in my <code>manifest.manifest</code> file. However unlike in the <code>theme-color</code> meta tag approach, the manifest allows defining one theme colour only. While I don’t think there’d be any issue in having both the meta tag and manifest value in play simultaneously (my understanding is that the <a href="https://github.com/w3c/manifest/issues/975#issuecomment-859986496">HTML would take priority over the manifest</a>), I decided to keep things simple and removed <code>theme_color</code> from my manifest file for now.</p>
<p>Note: <a href="https://github.com/w3c/manifest/issues/975">the w3c manifest spec may support multiple theme colours in future.</a></p>
<h2 id="the-color-scheme-meta-tag" tabindex="-1">The color-scheme meta tag <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#the-color-scheme-meta-tag" aria-hidden="true">#</a></h2>
<p>The <code>color-scheme</code> meta tag is used to specify one or more color schemes/modes with which the page is compatible. Unlike <code>theme-color</code> you don’t provide an arbitrary colour value, but rather one of <code>light</code> or <code>dark</code> or both in combination. This tells the browser whether it can change default background, foreground and text colours to match the current system appearance. As Jim Nielsen notes in <a href="https://blog.jim-nielsen.com/2020/color-scheme-property/">Don’t forget the color-scheme property</a>, it gives the browser permission to automatically change standard form controls, scroll bars, and other named system colors.</p>
<p>I include this meta tag on each page (just after my <code>theme-color</code> meta tags). I indicate that my styles have been prepped to handle the browser applying either light or dark colour schemes and—via the order of values in the content attribute—that I prefer light.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color-scheme<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>light dark<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>Notes:</p>
<ol>
<li>I’ve also seen <code><meta name="supported-color-schemes"></code> however <a href="https://medium.com/dev-channel/what-does-dark-modes-supported-color-schemes-actually-do-69c2eacdfa1d">Thomas Steiner explained that this is an old syntax</a> and has since been standardised as <code><meta name="color-scheme"></code>;</li>
<li>There is also a <code>color-scheme</code> CSS property, which I’ll come to later. Once again though, having an HTML meta tag helps browsers to apply things <em>faster</em>;</li>
<li>although I’m currently intimating that I prefer <em>light</em>, in future I might update this to <em>dark</em> first (assuming I don’t hear of any reasons against it). The dark colour palette is really growing on me!</li>
</ol>
<h2 id="ensuring-colours-are-accessible" tabindex="-1">Ensuring colours are accessible <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#ensuring-colours-are-accessible" aria-hidden="true">#</a></h2>
<p>While working on a new dark colour palette and tweaking my light palette I made sure to check that colour contrast met accessibility requirements.</p>
<p>Useful tools on this front include:</p>
<ul>
<li>Activating Chrome’s element inspector (the “box with arrow at bottom-right” icon) enables hovering an element to check the contrast of text against background;</li>
<li>Erik Kennedy’s <a href="https://learnui.design/tools/accessible-color-generator.html">Accessible Color Generator</a> provides slightly modified colour alternatives when contrast is insufficient—really handy and I used this a couple of times;</li>
<li><a href="https://www.aremycolorsaccessible.com/">Are my colors accessible?</a> is another great “check contrast, digest results, then tweak” tool which provides more detailed information than the Chrome inspector, especially regarding the impact of small text on contrast.</li>
</ul>
<h2 id="design-tokens" tabindex="-1">Design Tokens <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#design-tokens" aria-hidden="true">#</a></h2>
<p>It quickly became clear that I’d need global colour settings that I could use across multiple technologies and multiple files. For example, I’d want to reuse the same custom background colour value in an HTML <code>theme-color</code> meta tag, in CSS, and perhaps also in a JSON-based manifest file.</p>
<p>I’d previously <a href="https://fuzzylogic.me/posts/manage-design-tokens-in-eleventy/">bookmarked Heydon Pickering’s article on design tokens in Eleventy</a> and now was the time to give it a spin.</p>
<p>I created <code>_data/tokens.json</code> in which I defined raw tokens such as <code>colorDark</code>, <code>colorDarker</code> and <code>colorLight</code>.</p>
<p>Then in my Nunjucks-based HTML templates I could access that token data to define meta tag values using <code>{{ tokens.colorLight }}</code>. These values would be interpolated to the real CSS colour values during build.</p>
<p>I also created a new Nunjucks file, <code>theme_css.njk</code>, adding <code>permalink: "css/theme.css"</code> in its frontmatter so that it’d generate a CSS file. This file maps my design tokens to custom properties set on the root element, something like this:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span><br /> <span class="token selector">--color-dark:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorDark <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-darker:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorDarker <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-light:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorLight <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-grey:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorGrey <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-highlight:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorHighlight <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-highlight-dark:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorHighlightDark <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-highlight-darker:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorHighlightDarker <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token selector">;<br /> --color-text:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> tokens.colorText <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<h2 id="custom-properties-ftw" tabindex="-1">Custom properties FTW <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#custom-properties-ftw" aria-hidden="true">#</a></h2>
<p>Using custom properties allowed me to do the hard work of preparing my light and dark themes <em>upfront</em> and removed the need to constantly duplicate values and write code forks throughout my CSS.</p>
<p>Having previously created a base layer of reusable custom property representations of my design tokens, I began creating more specific custom properties to serve different contexts.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span><br /> <span class="token property">--color-page-bg-light</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-light<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-page-bg-dark</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-dark<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-ink-dark</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-text<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-ink-light</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-light<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<h2 id="css-for-default-and-dark-mode-contexts" tabindex="-1">CSS for default and dark-mode contexts <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#css-for-default-and-dark-mode-contexts" aria-hidden="true">#</a></h2>
<p>Now to set my light-mode defaults and fork these when the user prefers dark-mode.</p>
<p>Here’s my CSS:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span><br /> <span class="token property">color-scheme</span><span class="token punctuation">:</span> light<span class="token punctuation">;</span><br /><br /> <span class="token property">--color-highlight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-highlight-darker<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-page-bg</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-page-bg-light<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-band</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-darker<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-ink</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-ink-dark<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-ink-offset</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-grey<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token property">color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">;</span><br /><br /> <span class="token property">--color-highlight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-highlight-dark<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-page-bg</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-page-bg-dark<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-band</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-darker<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-ink</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-ink-light<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">--color-ink-offset</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-grey<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><br /> <span class="token property">accent-color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-highlight<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">body</span> <span class="token punctuation">{</span><br /> <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-page-bg<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-ink<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Let’s break that down.</p>
<p>The <code>color-scheme</code> property allows us to specify one or more colour schemes/modes with which an element is compatible. I’m defining it on the root element i.e. for the whole page. My approach was to start by specifying support for a light colour scheme only, then define background and text colour custom properties with values optimised for light colour scheme.</p>
<p>Using <code>@media (prefers-color-scheme: dark) {…}</code> we can check the user’s colour scheme preference. When the user prefers dark, I change <code>color-scheme</code> to <code>dark</code> to let the browser do its “set sensible defaults” thing, and I update the custom property values to those optimised to blend with a dark appearance.</p>
<p>The reusable, theme-sensitive custom properties I’ve plumped for are:</p>
<ul>
<li>highlight colour: really just my brand colour, although lightened a touch in dark mode for better contrast;</li>
<li>page background colour;</li>
<li>“band” background colour: something I’d use as a band of alternative background colour to distinguish special sections like the header or footer;</li>
<li>ink colour: my default text colour;</li>
<li>“offset” ink colour: a grey for little bits of meta text like dates and categories.</li>
</ul>
<p>I’m sure I’ll evolve these over time.</p>
<p>Lastly, the <code>accent-colour</code> CSS property is used by some form controls e.g. radios and checkboxes. I set that to my highlight colour with the intention of creating a more branded experience.</p>
<h2 id="svg-considerations" tabindex="-1">SVG considerations <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#svg-considerations" aria-hidden="true">#</a></h2>
<p>My SVG-based logo didn’t look right in dark mode, however the fix was pretty simple. I applied BEM-style element classes to any problematic <code>path</code> elements of the SVG then wrote CSS for those. The CSS tests for <code>prefers-color-scheme: dark</code> and updates the path’s <code>fill</code> or <code>stroke</code> colour as necessary.</p>
<h2 id="what-about-leaving-everything-to-the-browser%3F" tabindex="-1">What about leaving everything to the browser? <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#what-about-leaving-everything-to-the-browser%3F" aria-hidden="true">#</a></h2>
<p>Having read Jim Nielsen’s brilliant article on <a href="https://blog.jim-nielsen.com/2021/css-system-colors/">CSS System Colors</a> I tried feeding the browser <code>color-scheme: light dark</code>, removing my arbitrary dark theme colours, and leaving the colour palette entirely up to the browser. Along the way I learned some interesting lessons on system colours—which we can also choose to use as valid CSS colours in our custom components—such as <code>Canvas</code> and <code>CanvasText</code>.</p>
<p>I love this idea in principle! However in practice:</p>
<ul>
<li>only Safari’s colour palette looks consistent with the rest of the Mac OS. The palette applied by Chrome doesn’t; it has its own, different “black”. So for the control you’ve given away, you don’t necessarily achieve that nice “consistency with the OS” reward in return;</li>
<li>as far as I know you can’t lighten or darken the system colours so it’s hard to create a multi-tone, complimentary palette, and also be confident in achieving sufficient colour contrast. That’s fine if you only need a single background colour for the entire page with no alternate bands of colour (like on <a href="https://blog.jim-nielsen.com/">Jim’s blog</a>) however I think that’s a little restrictive. (Maybe I’m getting too hung up on control here though, and introducing additional arbitrary colours would work fine alongside a variable “system black”);</li>
<li>Firefox and iOS Safari are a little problematic in their support for the technologies involved, leading to writing a few hacky workarounds.</li>
</ul>
<p>For the combined reasons above I’m sticking with manually defined colours for now (however I have <a href="https://github.com/fuzzylogicxx/fuzzylogic/pull/33">a pull request</a> I can revisit later if the mood takes).</p>
<h2 id="what-could-i-do-better%3F" tabindex="-1">What could I do better? <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#what-could-i-do-better%3F" aria-hidden="true">#</a></h2>
<p>With extra time, I might:</p>
<ul>
<li>think more deeply about dark theme design, perhaps following some of the tips regarding shadows, depth and colour contrast in CSS Tricks’ <a href="https://css-tricks.com/a-complete-guide-to-dark-mode-on-the-web/#design-considerations">A complete guide to dark mode on the web</a>;</li>
<li>consider providing a <a href="https://mxb.dev/blog/color-theme-switcher/">theme switcher control</a> to allow the user to choose the website theme they want regardless of the current OS appearance. (But I probably won’t; I’m not sure it’s necessary)</li>
</ul>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/theming-based-on-user-color-scheme-preference/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://web.dev/learn/design/">Theming</a>, from Jeremy Keith’s excellent <em>Learn Responsive Design</em></li>
<li><a href="https://heydonworks.com/article/design-tokens-in-eleventy/">Design Tokens in Eleventy</a> by Heydon Pickering</li>
<li><a href="https://blog.jim-nielsen.com/2021/css-system-colors/">CSS System Colors</a> by Jim Nielsen</li>
</ul>
Building a toast component (by Adam Argyle)2022-01-01T14:39:23Zhttps://fuzzylogic.me/posts/building-a-toast-component-by-adam-argyle/<p>Great tutorial (with accompanying video) from Adam Argyle which starts with a useful definition of what a <code>Toast</code> is and is not:</p>
<blockquote>
<p>Toasts are non-interactive, passive, and asynchronous short messages for users. Generally they are used as an interface feedback pattern for informing the user about the results of an action. Toasts are unlike notifications, alerts and prompts because they're not interactive; they're not meant to be dismissed or persist. Notifications are for more important information, synchronous messaging that requires interaction, or system level messages (as opposed to page level). Toasts are more passive than other notice strategies.</p>
</blockquote>
<p>There are some important distinctions between toasts and notifications in that definition: toasts are for less important information and are non-interactive. I remember in a previous work planning exercise regarding a toast component a few of us got temporarily bogged down in working out the best JavaScript templating solution for SVG icon-based “Dismiss” buttons… however we were probably barking up the wrong tree with the idea that toasts should be manually dismissable.</p>
<p>There are lots of interesting ideas and considerations in Adam’s tutorial, such as:</p>
<ul>
<li>using the <code><output></code> element for each toast</li>
<li>some crafty use of CSS Grid and logical properties for layout</li>
<li>combining <code>hsl</code> and percentages in custom properties to proportionately modify rather than redefine colours for dark mode</li>
<li>animation using <code>keyframes</code> and <code>animation</code></li>
<li>native JavaScript modules</li>
<li>inserting an element <em>before</em> the <code><body></code> element (TIL that this is a viable option)</li>
</ul>
<p>Thanks for this, <a href="https://fuzzylogic.me/posts/building-a-toast-component-by-adam-argyle/@argyleink">Adam</a>!</p>
<p>(via <a href="https://twitter.com/argyleink/status/1468620728052305924">Adam’s tweet</a>)</p>
<p>There’s some nice code in here but the demo page minifies and obfuscates everything. However the <a href="https://github.com/argyleink/gui-challenges/tree/main/toast">toast component source</a> is available on GitHub.</p>
<h2 id="related-links" tabindex="-1">Related links <a class="direct-link" href="https://fuzzylogic.me/posts/building-a-toast-component-by-adam-argyle/#related-links" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.scottohara.me/blog/2019/07/08/a-toast-to-a11y-toasts.html">A toast to accessible toasts</a> by Scott O’Hara</li>
</ul>
Web animation tips2021-12-22T22:42:48Zhttps://fuzzylogic.me/posts/web-animation-tips/<p>Warning: this entry is a work-in-progress and incomplete. That said, it's still a useful reference to me which is why I've published it. I’ll flesh it out soon!</p>
<p>There are lots of different strands of web development. You try your best to be good at all of them, but there’s only so much time in the day! Animation is an area where I know <em>a little</em> but would love to know more, and from a practical perspective I’d certainly benefit from having some road-ready solutions to common challenges. As ever I want to favour web standards over libraries where possible, and take an approach that’s lean, accessible, progressively-enhanced and performance-optimised.</p>
<p>Here’s my attempt to break down web animation into bite-sized chunks for ocassional users like myself.</p>
<h2 id="defining-animation" tabindex="-1">Defining animation <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#defining-animation" aria-hidden="true">#</a></h2>
<p>Animation lets us make something visually move between different states over a given period of time.</p>
<h2 id="benefits-of-animation" tabindex="-1">Benefits of animation <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#benefits-of-animation" aria-hidden="true">#</a></h2>
<p>Animation is a good way of providing visual feedback, teaching users how to use a part of the interface, or adding life to a website and making it feel more “real”.</p>
<h2 id="simple-animation-with-transition-properties" tabindex="-1">Simple animation with <code>transition</code> properties <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#simple-animation-with-transition-properties" aria-hidden="true">#</a></h2>
<p>CSS <code>transition</code> is great for simple animations triggered by an event.</p>
<p>We start by defining two different states for an element—for example <code>opacity:1</code> and <code>opacity:0</code>—and then <code>transition</code> between those states.</p>
<p>The first state would be in the element’s starting styles (either defined explicitly or existing implicitly based on property defaults) and the other in either its <code>:hover</code> or <code>:focus</code> styles or in a class applied by JavaScript following an event.</p>
<p>Without the <code>transition</code> the state change would still happen but would be instantaneous.</p>
<p>You’re not limited to only one property being animated and might, for example, transition between different <code>opacity</code> and <code>transform</code> states simultaneously.</p>
<p>Here’s an example “rise on hover” effect, adapted from Stephanie Eckles’s <a href="https://smolcss.dev/#smol-transitions">Smol CSS</a>.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>u-animate u-animate--rise<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>rise<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
</figure>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.u-animate > *</span> <span class="token punctuation">{</span><br /> <span class="token property">--transition-property</span><span class="token punctuation">:</span> transform<span class="token punctuation">;</span><br /> <span class="token property">--transition-duration</span><span class="token punctuation">:</span> 180ms<span class="token punctuation">;</span><br /> <span class="token property">transition</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--transition-property<span class="token punctuation">)</span> <span class="token function">var</span><span class="token punctuation">(</span>--transition-duration<span class="token punctuation">)</span> ease-in-out<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.u-animate--rise:hover > *</span> <span class="token punctuation">{</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translateY</span><span class="token punctuation">(</span>-25%<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Note that:</p>
<ol>
<li>using custom properties makes it really easy to transition a different property than <code>transform</code> without writing repetitious CSS.</li>
<li>we have a parent and child (<code><div></code> and <code><span></code> respectively in this example) allowing us to avoid the accidental flicker which can occur when the mouse is close to an animatable element’s border by having the child be the <em>effect</em> which animates when the <em>trigger</em> (the parent) is hovered.</li>
</ol>
<h2 id="complex-animations-with-animation-properties" tabindex="-1">Complex animations with <code>animation</code> properties <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#complex-animations-with-animation-properties" aria-hidden="true">#</a></h2>
<p>If an element needs to animate automatically (perhaps on page load or when added to the DOM), or is more complex than a simple A to B state change, then a CSS <code>animation</code> may be more appropriate than <code>transition</code>. Using this approach, animations can:</p>
<ul>
<li>run automatically (you don’t <em>need</em> an event to trigger a state change)</li>
<li>go from an initial state through multiple intermediate steps to a final state rather than just from state A to state B</li>
<li>run forwards, in reverse, or alternate directions</li>
<li>loop infinitely</li>
</ul>
<p>The required approach is:</p>
<ol>
<li>use <code>@keyframes</code> to define a reusable “template” set of animation states (or <em>frames</em>); then</li>
<li>apply <code>animation</code> properties to an element we want to animate, including one or more <code>@keyframes</code> to be used.</li>
</ol>
<p>Here’s how you do it:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@keyframes</span> flash</span> <span class="token punctuation">{</span><br /> <span class="token selector">0%</span> <span class="token punctuation">{</span> <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /> <span class="token selector">20%</span> <span class="token punctuation">{</span> <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /> <span class="token selector">80%</span> <span class="token punctuation">{</span> <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /> <span class="token selector">100%</span> <span class="token punctuation">{</span> <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.animate-me</span> <span class="token punctuation">{</span><br /> <span class="token property">animation</span><span class="token punctuation">:</span> flash 5s infinite<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Note that you can also opt to include just one state in your <code>@keyframes</code> rule, usually the initial state (written as either <code>from</code> or <code>0%</code>) or final state (written as either <code>to</code> or <code>100%</code>). You’d tend to do that for a two-state animation where the other “state” is in the element’s default styles, and you’d either be <em>starting</em> from the default styles (if your single <code>@keyframes</code> state is <code>to</code>) or finishing on them (if your single <code>@keyframes</code> state is <code>from</code>).</p>
<h2 id="should-i-use-transition-or-animation%3F" tabindex="-1">Should I use <code>transition</code> or <code>animation</code>? <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#should-i-use-transition-or-animation%3F" aria-hidden="true">#</a></h2>
<p>As far as I can tell there’s no major performance benefit of one over the other, so that’s not an issue.</p>
<p>When the animation will be triggered by pseudo-class-based events like <code>:hover</code> or <code>:focus</code> and is simple i.e. based on just two states, <code>transition</code> feels like the right choice.</p>
<p>Beyond that, the choice gets a bit less binary and seems to come down to developer preference. But here are a couple of notes that might help in making a decision.</p>
<p>For elements that need to “animate in” on page load such as an alert, or when newly added to the DOM such as items in a to-do list, an <code>animation</code> with <code>keyframes</code> feels the better choice. This is because <code>transition</code> requires the presence of two CSS rules, leading to dedicated JavaScript to grab the element and apply a class, whereas <code>animation</code> requires only one and can move between initial and final states automatically including inserting a delay before starting.</p>
<p>For animations that involve many frames; control over the number of iterations; or looping… use <code>@keyframes</code> and <code>animation</code>.</p>
<p>For utility classes and classes that get added by JS to <em>existing, visible</em> elements following an event, either approach could be used. Arguably <code>transition</code> is the slightly simpler and more elegant CSS to write if it covers your needs. Then again, you might want to reuse the animations applied by those classes for both existing, visible elements and new, animated-in elements, in which case you might feel that instead using <code>@keyframes</code> and <code>animation</code> covers more situations.</p>
<h2 id="performance" tabindex="-1">Performance <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#performance" aria-hidden="true">#</a></h2>
<p>A smooth animation should run at 60fps (frames per second). Animations that are too computationally expensive result in frames being dropped, i.e. a reduced fps rate, making the animation appear janky.</p>
<h3 id="cheap-and-slick-properties" tabindex="-1">Cheap and slick properties <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#cheap-and-slick-properties" aria-hidden="true">#</a></h3>
<p>The CSS properties <code>transform</code> and <code>opacity</code> are very cheap to animate. Also, browsers often optimise these types of animation using hardware acceleration. To hint to the browser that it should optimise an animation property (and to ensure it is handled by the GPU rather than passed from CPU to GPU causing a noticeable glitch) we should use the CSS <code>will-change</code> property.</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.my-element</span> <span class="token punctuation">{</span><br /> <span class="token property">will-change</span><span class="token punctuation">:</span> transform<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<h3 id="expensive-properties" tabindex="-1">Expensive properties <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#expensive-properties" aria-hidden="true">#</a></h3>
<p>CSS properties which affect layout such as <code>height</code> are very expensive to animate. Animating height causes a chain reaction where sibling elements have to move too. Use <code>transform</code> over layout-affecting properties such as <code>width</code> or <code>left</code> if you can.</p>
<p>Some other CSS properties are less expensive but still not ideal, for example <code>background-color</code>. It doesn't affect layout but requires a repaint per frame.</p>
<p>Test your animations on a popular low-end device.</p>
<h2 id="timing-functions" tabindex="-1">Timing functions <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#timing-functions" aria-hidden="true">#</a></h2>
<ul>
<li>linear goes at the same rate from start to finish. It’s not like most motion in the real world.</li>
<li>ease-out starts fast then gets really slow. Good for things that come in from off-screen, like a modal dialogue.</li>
<li>ease-in starts slow then gets really fast. Good for moving somethng off-screen.</li>
<li>ease-in-out is the combination of the previous two. It‘s symmetrical, having an equal amount of acceleration and deceleration. Good for things that happen in a loop such as element fading in and out.</li>
<li>ease is the default value and features a brief ramp-up, then a lot of deceleration. It’s a good option for most general case motion that doesn’t enter or exit the viewport.</li>
</ul>
<h2 id="practical-examples" tabindex="-1">Practical examples <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#practical-examples" aria-hidden="true">#</a></h2>
<p>You can find lots of animation inspiration in libraries such as <a href="https://animate.style/">animate.css</a> (and be sure to <a href="https://github.com/animate-css/animate.css">check animate.css on github</a> where you can search their source for specific <code>@keyframe</code> animation styles).</p>
<p>But here are a few specific examples of animations I or teams I’ve worked on have had to implement.</p>
<h3 id="skip-to-content" tabindex="-1">Skip to content <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#skip-to-content" aria-hidden="true">#</a></h3>
<p>The anchor’s <em>State A</em> sees its position <code>fixed</code>—i.e. positioned relative to the viewport—but then moved out of sight above it via <code>transform: translateY(-10em)</code>. However its <code>:focus</code> styles define a <em>State B</em> where the intial <code>translate</code> has been undone so that the link is visible (<code>transform: translateY(0em)</code>). If we <code>transition</code> the <code>transform</code> property then we can animate the change of state over a chosen duration, and with our preferred timing function for the <em>acceleration curve</em>.</p>
<p>HTML:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>u-visually-hidden-until-focused<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span><br /> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#skip-link-target<span class="token punctuation">"</span></span><br /> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>u-visually-hidden-until-focused__item<span class="token punctuation">"</span></span><br /> <span class="token punctuation">></span></span>Skip to main content<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>nav</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Home<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>News<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>About<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- …lots more nav links… --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Contact<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>nav</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>skip-link-target<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>This is the Main content<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Lorem ipsum <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/news/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>dolor sit amet<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span> consectetur adipisicing elit.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Lorem ipsum dolor sit amet consectetur adipisicing elit.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>CSS:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.u-visually-hidden-until-focused</span> <span class="token punctuation">{</span><br /> <span class="token property">left</span><span class="token punctuation">:</span> -100vw<span class="token punctuation">;</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span><br /><br /> <span class="token selector">&__item</span> <span class="token punctuation">{</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> fixed<span class="token punctuation">;</span><br /> <span class="token property">top</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /> <span class="token property">left</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translateY</span><span class="token punctuation">(</span>-10em<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">transition</span><span class="token punctuation">:</span> transform 0.2s ease-in-out<span class="token punctuation">;</span><br /><br /> <span class="token selector">&:focus</span> <span class="token punctuation">{</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translateY</span><span class="token punctuation">(</span>0em<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>To see this in action, visit my pen <a href="https://codepen.io/fuzzylogicx/debug/bGRjvVj">Hiding: visually hidden until focused</a> and press the <kbd>tab</kbd> key.</p>
<h3 id="animating-in-an-existing-element" tabindex="-1">Animating in an existing element <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#animating-in-an-existing-element" aria-hidden="true">#</a></h3>
<p>For this requirement we want an element to animate from invisible to visible on page load. I can imagine doing this with an image or an alert, for example. This is pretty straightforward with CSS only using <code>@keyframes</code>, <code>opacity</code> and <code>animation</code>.</p>
<p>Check out my <a href="https://codepen.io/fuzzylogicx/pen/ZNoLQB?editors=1100">fade in and out on page load with CSS</a> codepen.</p>
<h3 id="animating-in-a-newly-added-element" tabindex="-1">Animating in a newly added element <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#animating-in-a-newly-added-element" aria-hidden="true">#</a></h3>
<p>Stephanie Eckles shared a great CSS-only solution for <a href="https://thinkdobecreate.com/articles/css-animating-newly-added-element/">animating in a newly added element</a> which handily includes a Codepen demo. She mentions “CSS-only” because it’s common for developers to achieve the fancy animation via <code>transition</code> but that means needing to “make a fake event” via a JavaScript <code>setTimeout()</code> so that you can transition from the newly-added, invisible and class-free element state to adding a CSS class (perhaps called <code>show</code>) that contains the <code>opacity:1</code>, fancy transforms and a <code>transition</code>. However Stephanie’s alternative approach combines i) hiding the element in its default styles; with ii) an automatically-running <code>animation</code> that includes the necessary delay and also finishes in the keyframe’s single <code>100%</code> state… to get the same effect minus the JavaScript.</p>
<p>Avoiding reliance on JS and finding a solution lower down the stack is always good.</p>
<figure>
<p>HTML:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Add List Item<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum facilis perspiciatis dignissimos, et dolores pariatur.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
<p>CSS:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">li</span> <span class="token punctuation">{</span><br /> <span class="token property">animation</span><span class="token punctuation">:</span> show 600ms 100ms <span class="token function">cubic-bezier</span><span class="token punctuation">(</span>0.38<span class="token punctuation">,</span> 0.97<span class="token punctuation">,</span> 0.56<span class="token punctuation">,</span> 0.76<span class="token punctuation">)</span> forwards<span class="token punctuation">;</span><br /><br /> // Prestate<br /> <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /> // remove transform for just a fade-in<br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotateX</span><span class="token punctuation">(</span>-90deg<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">transform-origin</span><span class="token punctuation">:</span> top center<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token atrule"><span class="token rule">@keyframes</span> show</span> <span class="token punctuation">{</span><br /> <span class="token selector">100%</span> <span class="token punctuation">{</span><br /> <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Jhey Tompkins shared another CSS-only technique for <a href="https://codepen.io/jh3y/pen/KKyrQYZ">adding elements to the DOM with snazzy entrance animations</a>. He also uses just a single <code>@keyframes</code> state but in his case the <code>from</code> state which he uses to set the element’s initial <code>opacity:0</code>, then in his animation he uses an <code>animation-fill-mode</code> of <code>both</code> (rather than <code>forwards</code> as Stephanie used).</p>
<p>I can’t profess to fully understand <code>both</code> however if you change Jhey’s example to use <code>forwards</code> instead, then the element being animated in will temporarily appear before the animation starts (which ain’t good) rather than being initially invisible. Changing it to <code>backwards</code> gets us back on track, so I guess the necessary value relates to whether you’re going for <code>from</code>/<code>0%</code> or <code>to</code>/<code>100%</code>… and <code>both</code> just covers you for both cases. I’d probably try to use the appropriate one rather than <code>both</code> just in case there’s a performance implication.</p>
<h3 id="animated-disclosure" tabindex="-1">Animated disclosure <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#animated-disclosure" aria-hidden="true">#</a></h3>
<p>Here’s an interesting conundrum.</p>
<p>For disclosure (i.e. collapse and expand) widgets, I tend to either use the native HTML <code><details></code> element if possible or else a <a href="https://codepen.io/fuzzylogicx/pen/YzQjyoj?editors=1010">simple, accessible DIY disclosure</a> in which activating a <code>trigger</code> toggles a nearby content element’s visibility. In both cases, there’s no animation; the change from hidden to revealed and back again is immediate.</p>
<p>To my mind it’s generally preferable to keep it simple and avoid animating a disclosure widget. For a start, it’s tricky! The <code><details></code> element can’t be (easily) animated. And if using a DIY widget it’ll likely involve animating one of the <a href="https://fuzzylogic.me/posts/web-animation-tips/#expensive-properties">expensive properties</a>. Animating <code>height</code> or <code>max-height</code> is also gnarly when working with variable (auto) length content and often requires developers to go beyond CSS and reach for JavaScript to calculate computed element heights. Lastly, forgetting the technical challenges, there’s often <em>no real need</em> to animate disclosure; it might only hinder rather than help the user experience.</p>
<p>But let’s just say you <em>have to do it</em>, perhaps because the design spec requires it (like in <a href="https://www.bbc.co.uk/sounds/play/m0012d93">BBC Sounds’ expanding and collapsing tracklists</a> when viewed on narrow screens).</p>
<p>Options:</p>
<ul>
<li><a href="https://css-tricks.com/how-to-animate-the-details-element-using-waapi/">Animate the <code><details></code> element</a>. This is a nice, standards-oriented approach. But it might only be viable for when you don’t need to mess with <code><details></code> appearance too much. We’d struggle to apply very custom styles, or to handle a “show the first few list items but not all” requirement like in the BBC Sounds example;</li>
<li><a href="https://nemzes.net/posts/animating-height-auto/#the-solutions">Animate CSS Grid</a>. This is a nice idea but for now the animation only works in Firefox<sup>*</sup>. It’d be great to just consider it a progressive enhancement so it just depends on whether the animation is deemed core to the experience;</li>
<li><a href="https://codepen.io/fuzzylogicx/pen/wvPMxvm">Animate from a max-height of 0 to “something sufficient”</a> (my pen is inspired by <a href="https://codepen.io/scottohara/pen/ybLMOm">Scott O’Hara’s disclosure example</a>). This is workable but not ideal; you kinda need to set a max-height sweetspot otherwise your animation will be delayed and too long. You could of course add some JavaScript to get the exact necessary height then set it. BBC use <code>max-height</code> for their tracklist animation and those tracklists likely vary in length so I expect they use some JavaScript for height calculation.</li>
</ul>
<p>* Update 20/2/23: <a href="https://caniuse.com/mdn-css_properties_grid-template-rows_animation">the “animate CSS Grid” option now has wide browser support</a> and is probably my preferred approach. I made a codepen that demonstrates <a href="https://codepen.io/fuzzylogicx/pen/zYLbRxw/2dd66701b7198814e8f856d72eeee8f5">a disclosure widget with animation of <code>grid-template-rows</code></a>.</p>
<h3 id="ringing-bell-icon" tabindex="-1">Ringing bell icon <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#ringing-bell-icon" aria-hidden="true">#</a></h3>
<p>To be written.</p>
<h3 id="pulsing-%E2%80%9Cradar%E2%80%9D-effect" tabindex="-1">Pulsing “radar” effect <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#pulsing-%E2%80%9Cradar%E2%80%9D-effect" aria-hidden="true">#</a></h3>
<p>To be written.</p>
<!--
My animation-related pens that might be handy
- Auto slide-in (after delay) then slide out w. CSS and vanilla JS https://codepen.io/fuzzylogicx/pen/OYZmVQ
- Animate a scrolled-to element w. vanilla JS and CSS https://codepen.io/fuzzylogicx/pen/vwjgbq
- Fade in and out on page load with CSS https://codepen.io/fuzzylogicx/pen/ZNoLQB
- Using Vanilla JS Animations Helper Function and animate.css https://codepen.io/fuzzylogicx/pen/gywbwr
- Animate slide up like jQuery with just CSS & JS https://codepen.io/fuzzylogicx/pen/YMWRYB
- Fade out on click with a JS-applied class to trigger CSS transition and opacity https://codepen.io/fuzzylogicx/pen/6cd1db274f5ff23233b50c6140e600fa
-->
<h2 id="accessibility" tabindex="-1">Accessibility <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#accessibility" aria-hidden="true">#</a></h2>
<p>Accessibility and animation can co-exist, as Cassie Evans explains in her CSS-Tricks article <a href="https://css-tricks.com/empathetic-animation/">Empathetic Animation</a>. We should consider which parts of our website are suited to animation (for example perhaps not on serious, time-sensitive tasks) and we can also respect reduced motion preferences at a global level or in a more finer-grained way per component.</p>
<h2 id="notes" tabindex="-1">Notes <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#notes" aria-hidden="true">#</a></h2>
<ul>
<li><code>transition-delay</code> can be useful for avoiding common annoyances, such as when a dropdown menu that appears on hover disappears when you try to move the cursor to it.</li>
</ul>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/web-animation-tips/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://animate.style/">Inspiration: the animate.css library</a></li>
<li><a href="https://github.com/animate-css/animate.css">animate.css on github</a> (good for searching for keyframe CSS)</li>
<li><a href="https://thoughtbot.com/blog/transitions-and-transforms">CSS transitions and transforms</a> on Thoughtbot</li>
<li><a href="https://www.joshwcomeau.com/animation/css-transitions/">CSS Transitions</a> by Josh Comeau</li>
<li><a href="https://www.joshwcomeau.com/animation/keyframe-animations/">Keyframe Animations</a> by Josh Comeau</li>
<li><a href="https://cssanimation.rocks/transition-vs-animation/">Transition vs animation</a> on CSS Animation</li>
<li><a href="https://css-tricks.com/snippets/css/keyframe-animation-syntax/">Keyframe animation syntax</a> on CSS-Tricks</li>
<li><a href="https://thoughtbot.com/blog/css-animation-for-beginners">CSS animation for beginners</a> on Thoughtbot</li>
<li><a href="https://css-tricks.com/using-css-transitions-auto-dimensions/">Using CSS Transions on auto dimensions</a> on CSS-Tricks</li>
<li>Jhey Tompkins’s <a href="https://codepen.io/jh3y/pen/qBJWEzm">Image fade with interest</a> codepen</li>
</ul>
Limbo2021-12-22T20:17:15Zhttps://fuzzylogic.me/posts/limbo/<p>Enjoyed this funny and touching film about a Syrian asylum seeker searching for happiness on a remote Scottish island.</p>
<div class="l-frame">
<iframe title="Official Trailer for movie “Limbo”" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/3O--8AuuhgA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
I’ve started reading Station Eleven, by Emily St. John Mandel.2021-12-13T14:46:00Zhttps://fuzzylogic.me/posts/i-ve-started-reading-station-eleven-by-emily-st.john-mandel/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781447268970">Station Eleven</a>, by Emily St. John Mandel.</p>
GOV.UK introduce an experimental block link component2021-12-13T12:35:00Zhttps://fuzzylogic.me/posts/gov.uk-introduce-an-experimental-block-link-component/<p>Here’s an interesting development in the <a href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/">block link saga</a>: <a href="http://gov.uk/">GOV.UK</a> have introduced one (named <code>.chevron-card</code>) on their Homepage, citing how <a href="https://insidegovuk.blog.gov.uk/2021/12/13/updating-the-gov-uk-homepage/">it’ll improve accessibility by increasing mobile touch targets</a>. It’s not yet been added to their Design System while they’re monitoring it to see if it is successful. They’ve chosen the approach which starts with a standard, single, non-wrapping anchor then “stretches” it across the whole card via some pseudo elements and absolute positioning magic. I’m slightly surprised at this choice because it breaks the user’s ability to select text within the link. <a href="https://twitter.com/fuzzylogicx/status/1470369635681943561">Really interested to see how it pans out!</a></p>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Lovely write-up, & great rationale re. larger mobile tap targets! I’ve wrestled with “block links” & found that each approach has issues so it’s v. interesting that you chose the route that impacts text selection. Is that the lesser of the evils? Keen to hear how it pans out!</p>— Laurence Hughes (@fuzzylogicx) <a href="https://twitter.com/fuzzylogicx/status/1470369635681943561?ref_src=twsrc%5Etfw">December 13, 2021</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure>
Front-end architecture for a new website (in 2021)2021-12-12T00:41:22Zhttps://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/<p>Just taking a moment for some musings on which way the front-end wind is blowing (from my perspective at least) and how that might practically impact my approach on the next small-ish website that I code.</p>
<h2 id="i-might-lean-into-http2" tabindex="-1">I might lean into HTTP2 <a class="direct-link" href="https://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/#i-might-lean-into-http2" aria-hidden="true">#</a></h2>
<p>Breaking CSS into small modules then concatenating everything into a single file has traditionally been one of the key reasons for using Sass, but in the HTTP2 era where multiple requests are less of a performance issue it might be acceptable to simply include a number of modular CSS files in the <code><head></code>, as follows:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/css/base.css<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/css/component_1.css<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/css/component_2.css<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/css/component_3.css<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
<p>The same goes for browser-native JavaScript modules.</p>
<p>This isn’t something I’ve tried yet and it’d feel like a pretty radical departure from the conventions of recent years… but it‘s an option!</p>
<h2 id="i%E2%80%99ll-combine-es-modules-and-classes" tabindex="-1">I’ll combine ES modules and classes <a class="direct-link" href="https://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/#i%E2%80%99ll-combine-es-modules-and-classes" aria-hidden="true">#</a></h2>
<p>It’s great that JavaScript modules are natively supported in modern browsers. They allow me to remove build tools, work with web standards, and they perform well. They can also serve as a <a href="https://fuzzylogic.me/posts/browser-support-heuristics/">mustard cut</a> that allows me to use other syntax and features such as <code>async/await</code>, arrow functions, template literals, the spread operator etc with confidence and without transpilation or polyfilling.</p>
<p>In the <code><head></code>:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/js/main.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<p>In <code>main.js</code></p>
<pre class="language-html"><code class="language-html">import { Modal } from '/components/modal.js';<br /><br />const Modal = new Modal();<br />modal.init();</code></pre>
<p>In <code>modal.js</code></p>
<pre class="language-js"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">Modal</span> <span class="token punctuation">{</span><br /> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// modal functionality here</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<h2 id="i%E2%80%99ll-create-web-components" tabindex="-1">I’ll create Web Components <a class="direct-link" href="https://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/#i%E2%80%99ll-create-web-components" aria-hidden="true">#</a></h2>
<p>I’ve done a lot of preparatory reading and learning about web components in the last year. I’ll admit that I’ve found the concepts (including Shadow DOM) occasionally tough to wrap my head around, and I’ve also found it confusing that everyone seems to implement web components in different ways. However Dave Rupert’s <a href="https://fuzzylogic.me/posts/html-with-superpowers-from-dave-rupert/">HTML with Superpowers</a> presentation really helped make things click.</p>
<p>I’m now keen to create my own <em>custom elements</em> for javascript-enhanced UI elements; to give LitElement a spin; to progressively enhance a Light DOM baseline into Shadow DOM fanciness; and to check out how well the lifecycle callbacks perform.</p>
<h2 id="i%E2%80%99ll-go-deeper-with-custom-properties" tabindex="-1">I’ll go deeper with custom properties <a class="direct-link" href="https://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/#i%E2%80%99ll-go-deeper-with-custom-properties" aria-hidden="true">#</a></h2>
<p>I’ve been using custom properties for a few years now, but at first it was just as a native replacement for Sass variables, which isn’t really exploiting their full potential. However at work we’ve recently been using them as the special sauce powering component variations (<code>--gap</code>, <code>--mode</code> etc).</p>
<p>In our server-rendered components we’ve been using inline <code>style</code> attributes to apply variations via those properties, and this brings the advantage of no longer needing to create a CSS class per variation (e.g. one CSS class for each padding variation based on a spacing scale), which in turn keeps code and specificity simpler. However as I start using web components, custom properties will prove really handy here too. Not only can they be updated by JavaScript, but furthermore they provide a bridge between your global CSS and your web component because they can “pierce the Shadow Boundary”, make styling Shadow DOM HTML in custom elements easier.</p>
<h2 id="i%E2%80%99ll-use-bem%2C-but-loosely" tabindex="-1">I’ll use BEM, but loosely <a class="direct-link" href="https://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/#i%E2%80%99ll-use-bem%2C-but-loosely" aria-hidden="true">#</a></h2>
<p>Naming and structuring CSS can be hard, and is a topic which really divides opinion. Historically I liked to keep it simple using the cascade, element and contextual selectors, plus a handful of custom classes. I avoided “object-oriented” CSS methodologies because I found them verbose and, if I’m honest, slightly “anti-CSS”. However it’s fair to say that in larger applications and on projects with many developers, this approach lacked a degree of structure, modularisation and predictability, so I gravitated toward BEM.</p>
<p>BEM’s approach is a pretty sensible one and, compared to the likes of <a href="https://suitcss.github.io/">SUIT</a>, provides flexibility and good documentation. And while I’ve been keeping a watchful eye on new methodologies like <a href="https://cube.fyi/">CUBE CSS</a> and can see that they’re choc-full of ideas, my feeling is that BEM remains the more robust choice.</p>
<p>It’s also important to me that BEM has the concept of a <em>mix</em> because this allows you to place multiple block classes on the same element so as to (for example) apply an abstract layout in combination with a more implementation-specific component class.</p>
<pre><code><div class="l-stack c-news-feed">
</code></pre>
<p>Where I’ll happily deviate from BEM is to favour use of certain ARIA attributes as selectors (for example <code>[aria-current=page]</code> or <code>[aria-expanded=true]</code> because this <em>enforces</em> good accessibility practice and helps create equivalence between the visual and non-visual experience. I’m also happy to use the universal selector (<code>*</code>) which is great for <a href="https://fuzzylogic.me/posts/front-end-architecture-for-a-new-website-in-2021/">owl selectors</a> and I’m fine with adjacent sibling (and related) selectors.</p>
<p>Essentially I’m glad of the structure and maintainability that BEM provides but I don’t want a straitjacket that stops me from using my brain and applying CSS properly.</p>
Enhance! by Jeremy Keith—An Event Apart video (on Vimeo)2021-12-11T23:45:09Zhttps://fuzzylogic.me/posts/enhance-by-jeremy-keith-an-event-apart-video-on-vimeo/<p>A classic talk by Jeremy Keith on progressive enhancement and the nature of the web and its technologies.</p>
Learn Responsive Design (on web.dev)2021-12-11T22:50:19Zhttps://fuzzylogic.me/posts/learn-responsive-design-on-web.dev/<p>Jeremy Keith’s new course for Google’s web.dev learning platform is fantastic and covers a variety of aspects of responsive design including layout (macro and micro), images, icons and typography.</p>
Life lessons from Larry David and Adam Buxton2021-12-10T12:28:45Zhttps://fuzzylogic.me/posts/life-lessons-from-larry-david-and-adam-buxton/<p>Recently, during a period when pandemic woes were taking their toll and likely making me a little cranky at home, I found some funny and helpful words of wisdom on Adam Buxton’s podcast and when re-watching Ricky Gervais’s interview with Larry David.</p>
<p>On sustaining a happy marriage, <a href="https://www.adam-buxton.co.uk/podcasts/wmcgmfe7zj7chps-89fa4-2e48e-rwzy8-824b8-4mdjd-2hcs8-chrb2-7y8jj-5pcse-2wtsh-cz8zd-e3cdy-g68s7-3dezn-7k5mw">Buxton said</a>:</p>
<blockquote>
<p>Every now and then you think “they’re not doing what I <em>want</em> them to do and I think it’s important that they <em>do</em> do this thing that I want them to do! (But) you have to think really hard: is this thing actually <em>important</em>? Is it worth getting bent out of shape about?</p>
</blockquote>
<p>It’s good advice. He mentioned that he’s slowly getting better at that, and I’m trying my best to, too.</p>
<p>Meanwhile, on the reasons why he got into acting, <a href="https://www.youtube.com/watch?v=mL0m8BmxNq8">Larry David said</a>:</p>
<blockquote>
<p>it gets you out of the house!</p>
</blockquote>
<p>So simple but true—it’s good to get out of the house! We’re now emerging from a period of sustained isolation and I should probably avoid being completely remote (and going stir crazy) and get back into the office occasionally.</p>
Resources for learning front-end web development2021-12-07T09:17:00Zhttps://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/<p>A designer colleague recently asked me what course or resources I would recommend for learning front-end web development. She mentioned React at the beginning but I suggested that it’d be better to start by learning HTML, CSS, and JavaScript. As for React: it’s a subset or offshoot of JavaScript so it makes sense to understand vanilla JS first.</p>
<p>For future reference, here are my tips.</p>
<h2 id="everything-in-one-place" tabindex="-1">Everything in one place <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#everything-in-one-place" aria-hidden="true">#</a></h2>
<p>Google’s web.dev training resource have also been adding some excellent guides, such as:</p>
<ul>
<li><a href="https://web.dev/learn/html/">Learn HTML</a></li>
<li><a href="https://web.dev/learn/accessibility/">Learn Accessibility</a></li>
<li><a href="https://web.dev/learn/css/">Learn CSS</a></li>
<li><a href="https://web.dev/learn/design/">Learn Responsive Design</a></li>
</ul>
<p>Another great one-stop shop is <a href="https://developer.mozilla.org/en-US/">MDN Web Docs</a>. Not only is MDN an amazing general quick reference for all HTML elements, CSS properties, JavaScript APIs etc but for more immersive learning there are also <a href="https://developer.mozilla.org/en-US/docs/Learn">MDN’s guides</a>.</p>
<h2 id="pay-attention-to-html" tabindex="-1">Pay attention to HTML <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#pay-attention-to-html" aria-hidden="true">#</a></h2>
<p>One general piece of advice is that when people look at lists of courses (whether or not they are new to web development) they ensure to learn HTML. People tend to underestimate how complicated, fast-moving and important HTML is.</p>
<p>Also, everything else – accessibility, CSS, JavaScript, performance, resilience – requires a foundation of good HTML. Think <em>HTML first</em>!</p>
<h2 id="learning-css%2C-specifically" tabindex="-1">Learning CSS, specifically <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#learning-css%2C-specifically" aria-hidden="true">#</a></h2>
<p>CSS is as much about concepts and features – e.g. the cascade and specificity, layout, responsive design, typography, custom properties – as it is about syntax. In fact probably more so.</p>
<p>Most tutorials will focus on the concepts but not necessarily so much on practicalities like writing-style or file organisation.</p>
<p>Google’s <a href="https://web.dev/learn/css/">Learn CSS</a> course should be pretty good for the modern concepts.</p>
<p>Google also have <a href="https://web.dev/learn/design/">Learn Responsive Design</a>.</p>
<p>If you’re coming from a kinda non-CSS-oriented perspective, Josh W Comeau’s <a href="https://css-for-js.dev/">CSS for JavaScript Developers</a> (paid course) could be worth a look.</p>
<p>If you prefer videos, you could check out Steve Griffith’s video series <a href="https://www.youtube.com/playlist?list=PLyuRouwmQCjl4wTSNbb8RTKZuyMhoIxBe">Learning CSS</a>. Steve’s videos are comprehensive and well-paced. It contains a whole range of topics (over 100!), starting from the basics like <a href="https://www.youtube.com/watch?v=RubwqbzQUcg&list=PLyuRouwmQCjl4wTSNbb8RTKZuyMhoIxBe&index=6">CSS Box Model</a>.</p>
<p>In terms of HTML and CSS writing style (BEM etc) and file organisation (ITCSS etc), here’s a (version of a) “style guide” that my team came up with for one of our documentation websites. I think it’s pretty good!</p>
<p>CSS and HTML Style Guide (to do: add link here)</p>
<p>For more on ITCSS and Harry Roberts’s thoughts on CSS best practices, see:</p>
<ul>
<li><a href="https://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528">Manage large projects with ITCSS</a></li>
<li><a href="https://www.skillshare.com/en/classes/Modern-CSS-Writing-Better-Cleaner-More-Scalable-Code/771669373">Harry’s Skillshare course on ITCSS</a></li>
<li>Harry’s <a href="https://cssguidelin.es/">CSS Guidelines</a> rulebook</li>
<li>Harry’s <em>Discovr</em> demo project
<ul>
<li><a href="https://github.com/csswizardry/discovr/tree/master/css">Discovr CSS directory</a></li>
<li><a href="https://rawgit.com/csswizardry/discovr/master/index.html">Discovr demo site</a></li>
</ul>
</li>
</ul>
<h2 id="learning-javascript" tabindex="-1">Learning JavaScript <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#learning-javascript" aria-hidden="true">#</a></h2>
<p>I recommended choosing a course or courses from CSS-Tricks’ post <a href="https://css-tricks.com/beginner-javascript-notes/">Beginner JavaScript notes</a>, especially as it includes Wes Bos’s <a href="https://wesbos.com/javascript">Beginner JavaScript Notes + Reference</a>.</p>
<p>If you like learning by video, check out <a href="https://www.youtube.com/@SteveGriffith-Prof3ssorSt3v3/playlists?view=50&sort=dd&shelf_id=2">Steve Griffith’s JavaScript playlist</a>.</p>
<p>Once you start using JS in anger, I definitely recommend bookmarking Chris Ferdinandi’s <a href="https://vanillajstoolkit.com/reference/">Methods and APIs reference guide</a>.</p>
<p>If you’re then looking for a lightweight library for applying sprinkles of JavaScript, you could try <a href="https://stimulus.hotwired.dev/">Stimulus</a>.</p>
<h2 id="learning-responsive-design" tabindex="-1">Learning Responsive Design <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#learning-responsive-design" aria-hidden="true">#</a></h2>
<p>I recommend Jeremy Keith’s <a href="https://web.dev/learn/design/">Learn Responsive Design</a> course on web.dev.</p>
<h2 id="lists-of-courses" tabindex="-1">Lists of courses <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#lists-of-courses" aria-hidden="true">#</a></h2>
<p>You might choose a course or courses from CSS-Tricks’ post <a href="https://css-tricks.com/where-do-you-learn-html-css-in-2020/">Where do you learn HTML and CSS in 2020?</a></p>
<h2 id="recommended-books" tabindex="-1">Recommended books <a class="direct-link" href="https://fuzzylogic.me/posts/resources-for-learning-front-end-web-development/#recommended-books" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://resilientwebdesign.com/">Resilient Web Design</a> by Jeremy Keith. A fantastic wide-screen perspective on what we’re doing, who we’re doing it for, and how to go about it. Read online or listen as an audiobook.</li>
<li><a href="https://inclusive-components.design/">Inclusive Components</a> by Heydon Pickering. A unique, accessible approach to building interactive components, from someone who’s done this for BBC, Bulb, Spotify.</li>
<li><a href="https://every-layout.dev/">Every Layout</a> by Heydon Pickering & Andy Bell. Introducing layout primitives, for handling responsive design in Design Systems at scale (plus so many insights about the front-end)</li>
<li><a href="https://bradfrost.com/blog/post/atomic-web-design/">Atomic Design</a> by Brad Frost. A classic primer on Design Systems and component-composition oriented thinking.</li>
<li><a href="https://abookapart.com/products/practical-svg">Practical SVG</a> by Chris Coyier. Learn why and how to use SVG to make websites more aesthetically sharp, performant, accessible and flexible.</li>
<li><a href="http://book.webtypography.net/">Web Typography</a> by Richard Rutter. Elevate the web by applying the principles of typography via modern web typography techniques.</li>
</ul>
Collected web accessibility guidelines, tips and tests2021-12-04T09:14:53Zhttps://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/<p>At work, I’m sometimes asked accessibility questions or to provide guidelines. I’m with Anna Cook in considering myself an <a href="https://twitter.com/annaecook/status/1468602342639431682">accessibility advocate rather than an expert</a> however I have picked up lots of tips and knowledge over many years of developing websites. So I thought it’d be useful to gather some general web accessibility tips and tests in one place as a useful reference.</p>
<p>Caveats and notes:</p>
<ol>
<li>this is a living document which I’ll expand over time;</li>
<li>I’m standing on the shoulders of real experts and I list my <a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#references">references</a> at the foot of the article; and</li>
<li>if I’ve got anything wrong, please <a href="https://twitter.com/fuzzylogicx">let me know!</a></li>
</ol>
<h2 id="table-of-contents" tabindex="-1">Table of contents <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#table-of-contents" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#if-you-only-had-5-minutes">If you only had 5 minutes</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#content-structure">Content structure</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#semantic-html-and-aria">Semantic HTML and ARIA</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#favour-native-over-custom-components-except-where-they-have-known-issues">Favour native over custom components except where they have known issues</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#make-custom-components-convey-state-accessibly">Make custom components convey state accessibly</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#forms">Forms</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#links-and-buttons">Links and buttons</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#ensure-keyboard-support">Ensure keyboard support</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#content-resizing">Content resizing</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#better-link-text">Better link text</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#supporting-high-contrast-mode">Supporting high contrast mode</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#skip-links">Skip links</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#navigation-and-menus">Navigation and menus</a></li>
<li><a href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#modal-dialogues">Modal dialogues</a></li>
</ul>
<h2 id="if-you-only-had-5-minutes" tabindex="-1">If you only had 5 minutes <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#if-you-only-had-5-minutes" aria-hidden="true">#</a></h2>
<p>If someone had a web page and only had 5 minutes to find and tackle the lowest hanging fruit accessibility-wise, I’d probably echo <a href="https://skiptocontent.huxleydigital.co.uk/video/caring-about-the-world-wide-web-with-jeremy-keith/">Jeremy Keith’s advice</a> to ensure that the page covers the following:</p>
<ul>
<li>uses heading elements sensibly</li>
<li>uses landmarks (representing roles like <code>banner</code>, <code>navigation</code>, <code>main</code>, <code>contentinfo</code>)</li>
<li>marks up forms sensibly (for example using labels and appropriate buttons)</li>
<li>provides images with decent text alternatives</li>
</ul>
<p>(Note: headings and landmarks are used by screen reader users to get a feel for the page then jump to areas of interest.)</p>
<p>Spending just 5 minutes would be bad, of course, and you shouldn’t do that. The point is that if pushed, the above give good bang-for-your-buck.</p>
<h2 id="content-structure" tabindex="-1">Content structure <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#content-structure" aria-hidden="true">#</a></h2>
<p>The page’s content should be well structured as this makes it easier to understand for all, especially people with reading and cognitive disabilities.</p>
<p>It should consist of short sections of content preceded by clear headings. Use the appropriate heading level for the place in the page. Don’t use an inappropriate heading level to achieve a given appearance such as a smaller size. Instead use the appropriate heading element then use CSS to achieve your desired style.</p>
<p>It should employ lists where appropriate. It should place the most important content at the beginning of the page or section to give it prominence.</p>
<p>Check your page for any long passages of text with no structure. Ensure that sufficient prominence is given to the most important information and calls to action.</p>
<h2 id="semantic-html-and-aria" tabindex="-1">Semantic HTML and ARIA <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#semantic-html-and-aria" aria-hidden="true">#</a></h2>
<p>Apply ARIA carefully. <a href="https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/#x2-1-no-aria-is-better-than-bad-aria">No ARIA is better than bad ARIA.</a></p>
<p>Using semantic HTML elements is preferable to bolting on semantics via attributes since the semantics are conveyed natively avoiding redundancy and duplication. As Bruce Lawson says, “Built-in beats bolt-on, bigly”.</p>
<p>Create a small number of <a href="https://developer.mozilla.org/en-US/blog/aria-accessibility-html-landmark-roles/">landmarks</a> using the appropriate HTML elements.</p>
<p>For some landmark-generating elements it’s appropriate to bolster them with a label or <em>accessible name</em>. For example with <code>nav</code> and <code>aside</code>, i) there’s a decent chance there might be multiple on the page; and ii) each instance creates a landmark even when it’s nested within a deeper HTML element. So it’s helpful to distinguish each different landmark of the same type by using sensible accessible names otherwise you’d get multiple navigation menus all represented by the same “navigation” in the <em>Landmarks</em> menu. In the case of the <code>section</code> element it <em>needs</em> an acessible name in order for it to act as a <code>region</code> landmark. For all of these you can use <code>aria-labelledby</code> set to the <code>id</code> of an inner heading, or use <code>aria-label</code>.</p>
<p>Note that when using multiple <code><header></code> (or <code>footer</code>) elements on a page, where one and one only is a direct child of <code>body</code> while the others are used within <code>article</code> or similar elements, there’s perhaps less need to add custom accessible names. That’s because only a direct child of <code>body</code> will be treated as a landmark and the others won’t, therefore they won’t be butting against each other in a screen reader’s <em>Landmarks</em> menu and need distinguished.</p>
<h2 id="favour-native-over-custom-components-except-where-they-have-known-issues" tabindex="-1">Favour native over custom components except where they have known issues <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#favour-native-over-custom-components-except-where-they-have-known-issues" aria-hidden="true">#</a></h2>
<p>Native components require very little work, are familiar to users, and are generally accessible by default. Custom components can be built to appear and behave as designers want, but require much more effort to build and are challenging to make accessible.</p>
<p>There are exceptions. Since the native options are flawed across browsers, accessibility experts recommend using custom solutions for:</p>
<ul>
<li>form error field messages</li>
<li>focus indicator styles</li>
</ul>
<h2 id="make-custom-components-convey-state-accessibly" tabindex="-1">Make custom components convey state accessibly <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#make-custom-components-convey-state-accessibly" aria-hidden="true">#</a></h2>
<p>Now that you’re building a custom component you don’t get accessibility out of the box. Whether it’s a <em>Like</em> button or a disclosure widget, you can’t rely on a visual change alone to convey a UI change to all users. You’ll need to use the right element (note – it often starts with a <code>button</code>) and then use ARIA to convey states such as <em>pressed</em> or <em>expanded</em> to screen reader users.</p>
<h2 id="forms" tabindex="-1">Forms <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#forms" aria-hidden="true">#</a></h2>
<p>Because in the industry form fields are often handled with JavaScript and not submitted, people sometimes question whether form fields should live inside a form (<code><form></code>). My answer is <strong>yes</strong>, and here’s why.</p>
<h3 id="using-the-form-element-improves-usability-and-accessibility" tabindex="-1">Using the form element improves usability and accessibility <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#using-the-form-element-improves-usability-and-accessibility" aria-hidden="true">#</a></h3>
<p>Using a <code><form></code> provides additional semantics allowing additional accessibility. It helps assistive devices like screen readers better understand the content of the page and gives the person using them more meaningful information.</p>
<p>By putting form fields inside a form we also ensure we match user expectations. We support the functionality (such as the different ways of submitting a form) that users expect when presented with form fields.</p>
<p>If you’re thinking “but what about form fields that don’t <em>look like</em> form fields?” then you’ve entered the problem territory of “deceptive user interfaces” – the situation where perceived affordances don’t match actual functionality, which causes confusion for some people. This is to be avoided. We shouldn’t use form fields (nor a <code><form></code>) when they are <em>not</em> appropriate. A checkbox, radio button, or select menu is meant to <em>gather information</em>. So if your goal is instead <a href="https://fuzzylogic.me/posts/2022-07-15-perceived-affordances-and-the-functionality-mismatch-by-leonie-watson/">to let the user manipulate the current view, use a <code>button</code> rather than checkboxes or radio buttons</a>.</p>
<p>References:</p>
<ul>
<li><a href="https://gomakethings.com/why-use-a-form-element-when-submitting-fields-with-javascript/">Why use a form element when submitting fields with JavaScript</a></li>
<li><a href="https://fuzzylogic.me/posts/2022-07-15-perceived-affordances-and-the-functionality-mismatch-by-leonie-watson/">Lea Verou and Leonie Watson’s discussion regarding Toggles</a></li>
<li><a href="https://fuzzylogic.me/posts/2022-07-15-perceived-affordances-and-the-functionality-mismatch-by-leonie-watson/#update-july-19%2F7%2F22">My conversation about forms with accessibility expert Adrian Roselli</a></li>
</ul>
<h3 id="using-the-form-element-simplifies-your-javascript-for-event-handling" tabindex="-1">Using the form element simplifies your JavaScript for event handling <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#using-the-form-element-simplifies-your-javascript-for-event-handling" aria-hidden="true">#</a></h3>
<p>Using the <code>form</code> element can also make it easier for you to meet user expectations in your JS-powered experience. This is because it gives you a single element (<code>form</code>) and event combination that allows listening to <em>multiple</em> interactions. With a form element you can add a listener for the <code>submit()</code> event. This event fires automatically in response to the various ways users expect to submit a form, including pressing <kbd>enter</kbd> inside a field.</p>
<h2 id="anchors-and-buttons" tabindex="-1">Anchors and buttons <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#anchors-and-buttons" aria-hidden="true">#</a></h2>
<p>When you need to let the user navigate to another page (or part of a page) or download a file, use an anchor element.</p>
<p>For ea you need to let the user trigger an action such as copying to clipboard, launching a modal or submitting a form, use a button element.</p>
<p>Anchors should include an <code>href</code> attribute otherwise the browser will treat it like a non-interactive element. This means the link will not be included in the expected focus order and will not present a pointer to mouse users like it should. These days there is no remaining use case for an anchor without an <code>href</code>. We no longer need <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#name">named anchors</a> to create link-target locations within the page because we can use the <code>id</code> attribute (on any element) for that. And if you want an interactive element that does not link somewhere, you should use <code>button</code>.</p>
<p>Do not remove the focus outline from links and buttons in CSS, unless it’s to provide a better version.</p>
<p>Ensure you always give links and buttons an accessible name, even when they use icons rather than text. This might be through visually hidden text or perhaps using an ARIA-related attribute.</p>
<h2 id="ensure-keyboard-support" tabindex="-1">Ensure keyboard support <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#ensure-keyboard-support" aria-hidden="true">#</a></h2>
<p>Web pages need to support those who navigate the page by keyboard.</p>
<p>Use the tab key to navigate your page and ensure that you can reach all actionable controls such as links, buttons and form controls. Press the enter key or space bar to activate each control.</p>
<p>If during your test any actionable control is skipped, receives focus in an illogical order, or you cannot see where the focus is at any time, then keyboard support is not properly implemented.</p>
<h2 id="content-resizing" tabindex="-1">Content resizing <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#content-resizing" aria-hidden="true">#</a></h2>
<p>Try zooming your page up to 400%. In Chrome, Zoom is available from the kebab menu at the top-right, or by holding down command with plus or minus.</p>
<p>Content must resize and be available and legible. Everything should reflow.</p>
<p>Relative font settings and responsive design techniques are helpful in effectively handling this requirement.</p>
<p>Relatedly, setting font-sizes in <code>px</code> should be avoided because although a user can override the “fixed-ness” with zoom, it breaks the user’s ability to choose a larger or smaller <em>default font size</em> (which users often prefer over having to zoom every single page).</p>
<h2 id="better-link-text" tabindex="-1">Better link text <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#better-link-text" aria-hidden="true">#</a></h2>
<p>Blind and visually impaired users use a <a href="https://en.wikipedia.org/wiki/Screen_reader">screen reader</a> to browse web pages, and screen readers provide user-friendly access to all the links on the page via a Links menu. When links are encountered in that context, link text like “Click here” and “Read more” are useless.</p>
<p>Check your web page to ensure that links clearly describe the content they link to when read out of context.</p>
<p>Better link text also improves the flow and clarity of your content and so improves the experience for everyone.</p>
<h2 id="supporting-high-contrast-mode" tabindex="-1">Supporting high contrast mode <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#supporting-high-contrast-mode" aria-hidden="true">#</a></h2>
<p>Some people find it easier to read content when it’s in a particular colour against a specific background colour. Operating systems provide options to allow users to configure this to their preference. Websites must support support the user’s ability to apply this.</p>
<p>On a Windows computer go to Settings > Ease of access and turn on High contrast mode. On macOS go to System preferences > Accessibility settings > Display and select “Invert colours”.</p>
<p>Having changed the contrast, check that your web page’s content is fully visible and understandable, that images are still visible and that buttons are still discernible.</p>
<h2 id="skip-links" tabindex="-1">Skip links <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#skip-links" aria-hidden="true">#</a></h2>
<p>Websites should provide a “Skip to content” link because this provides an important accessibility aid to keyboard users and those who use specialised input devices. For these users, having to step through (typically via the tab key) all of the navigation links on every page would be tiring and frustrating. Providing a skip link allows them to bypass the navigation and skip to the page’s main content.</p>
<p>To test that a website contains a skip link, visit a page then press the tab key and the skip link should appear. Then activate it using the enter key and check that focus moves to the main content area. Press tab again to ensure that focus moves to the first actionable element in the main content.</p>
<h2 id="navigation-and-menus" tabindex="-1">Navigation and menus <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#navigation-and-menus" aria-hidden="true">#</a></h2>
<p>When developing a collapsible menu, place your menu <code><button></code> <em>within</em> your <code><nav></code> element and hide the inner list rather than hiding the <code><nav></code> element itself. That way, we are not obscuring from Assistive Technologies the fact that a navigation still exists. ATs can still access the nav via landmark navigation. This is important because landmark discovery is one of the fundamental ways AT users scan, determine and navigate a site’s structure.</p>
<h2 id="modal-dialogues" tabindex="-1">Modal dialogues <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#modal-dialogues" aria-hidden="true">#</a></h2>
<p><a href="https://stackoverflow.com/a/38467898">You probably don’t want to set the modal’s heading as an <code><h1></code></a>. It likely displays content that exists on the page (which already has an <code><h1></code>) at a lower level of the document hierarchy.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/collected-web-accessibility-guidelines-tips-and-tests/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/blog/aria-accessibility-html-landmark-roles/">Using HTML landmark roles to improve accessibility</a> MDN article. And <a href="https://github.com/orgs/mdn/discussions/383">Adrian R’s suggestions for additions</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/navigation_role">Navigation (landmark) role, on MDN</a></li>
<li>Tetralogical’s <a href="https://www.youtube.com/playlist?list=PLTqm2yVMMUKWTr9XWdW5hJ9tk512Ow0SE">Quick Accessibility Tests</a> YouTube playlist</li>
<li><a href="https://gomakethings.com/basic-accessibility-mistakes-i-often-see-in-audits/">Basic accessibility mistakes I often see in audits</a> by Chris Ferdinandi</li>
<li>Sara Soueidan’s video tutorial <a href="https://aneventapart.com/news/post/practical-tips-for-building-more-accessible-front-ends">Practical tips for building more accessible front-ends</a></li>
<li>Adrian Roselli’s <a href="https://adrianroselli.com/2019/12/responsive-type-and-zoom.html">Responsive type and zoom</a></li>
<li>Heydon Pickering’s tweet about <a href="https://twitter.com/heydonworks/status/766948134169620480">buttons in navs</a> and Scott O’Hara’s follow up article <a href="https://www.scottohara.me/blog/2016/08/10/discovering-landmarks.html">Landmark Discoverability</a></li>
<li>Tetralogical’s <a href="https://tetralogical.com/blog/2022/11/08/foundations-native-versus-custom-components/">Foundations: native versus custom components</a></li>
</ul>
Collapsible sections, on Inclusive Components2021-12-01T10:37:39Zhttps://fuzzylogic.me/posts/collapsible-sections-on-inclusive-components/<p>It’s a few years old now, but this tutorial from Heydon Pickering on how to create an accessible, progressively enhanced user interface comprised of multiple collapsible and expandable sections is fantastic. It covers using the appropriate HTML elements (buttons) and ARIA attributes, how best to handle icons (minimal inline SVG), turning it into a web component and plenty more besides.</p>
Icon has Cheezburger (a Clearleft dConstruct newsletter)2021-11-16T16:23:40Zhttps://fuzzylogic.me/posts/icon-has-cheezburger-a-clearleft-dconstruct-newsletter/<p>Jeremy Keith deconstructs the cheeseburger icon and—referencing Luke Wroblewski’s <a href="https://vimeo.com/288882119">Obvious Always Wins</a> mantra—argues that while icons alone look tasty they risk users failing to understand and engage.</p>
BBC WebCore Design System2021-11-14T22:48:39Zhttps://fuzzylogic.me/posts/bbc-webcore-design-system/<p>A Storybook UI explorer containing the components and layouts for making the front end of a BBC web experience.</p>
From designing interfaces to designing systems (on The history of the web)2021-11-12T00:16:52Zhttps://fuzzylogic.me/posts/from-designing-interfaces-to-designing-systems-on-the-history-of-the-web/<p>A history of Design Systems by Jay Hoffman taking in (amongst other milestones) the notion of <em>Front-end Style Guides</em>, followed by the arrival of Bootstrap, then Brad Frost’s Atomic Design, culminating in the dawn of the Design System movement with <a href="https://jina.design/">Jina Anne’s</a> Clarity Conference.</p>
Buttons and links: definitions, differences and tips2021-10-23T18:53:41Zhttps://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/<p>On the web buttons and links are fundamentally different materials. However some design and development practices have led to them becoming conceptually “bundled together” and misunderstood. Practitioners can fall into the trap of seeing the surface-level commonality that “you click the thing, then something happens” and mistakenly thinking the two elements are interchangeable. Some might even consider them as a single “button component” without considering the distinctions underneath. However this mentality causes our users problems <em>and</em> is harmful for effective web development. In this post I’ll address why buttons and links are different and exist separately, and when to use each.</p>
<h2 id="problematic-patterns" tabindex="-1">Problematic patterns <a class="direct-link" href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/#problematic-patterns" aria-hidden="true">#</a></h2>
<p>Modern website designs commonly apply the appearance of a button to a link. For isolated calls to action this can make sense however as a design pattern it is often overused and under-cooked, which can cause confusion to developers implementing the designs.</p>
<p>Relatedly, it’s now common for Design Systems to have a <em>Button</em> component which includes button-styled links that are referred to simply as buttons. Unless documented carefully this can lead to internal language and comprehension issues.</p>
<p>Meanwhile developers have historically used <a href="https://www.htmhell.dev/8-anchor-tag-used-as-button/">faux links</a> (<code><a href="#"></code>) or worse, a DIY clickable <code>div</code>, as a trigger for JavaScript-powered functionality where they should instead use native buttons.</p>
<p>These patterns in combination have given rise to a collective <em>muddle</em> over buttons and links. We need to get back to basics and talk about foundational HTML.</p>
<h2 id="buttons-and-anchors-in-html" tabindex="-1">Buttons and anchors in HTML <a class="direct-link" href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/#buttons-and-anchors-in-html" aria-hidden="true">#</a></h2>
<p>There are two HTML elements of interest here.</p>
<p>Hyperlinks are created using the HTML <em>anchor</em> element (<code><a></code>). Buttons (by which I mean real buttons rather than links styled to appear as buttons) are implemented with the HTML <em>button</em> element (<code><button></code>).</p>
<p>Although a slight oversimplification, I think <a href="https://twitter.com/davidmacd/status/1309954746602713098">David MacDonald’s heuristic</a> works well:</p>
<p>If it GOES someWHERE use a link</p>
<p>If it DOES someTHING use a button</p>
<p>A link…</p>
<ul>
<li><em>goes somewhere</em> (i.e. navigates to another place)</li>
<li>normally links to another document (i.e. page) on the current website or on another website</li>
<li>can alternatively link to a different section of the same page</li>
<li>historically and by default appears underlined</li>
<li>when hovered or focused offers visual feedback from the browser’s status bar</li>
<li>uses the “pointing hand” mouse pointer</li>
<li>results in browser making an HTTP <code>GET</code> request by default. It’s intended to <em>get</em> a page or resource rather than to <em>change</em> something</li>
<li>offers specific right-click options to mouse users (open in new tab, copy URL, etc)</li>
<li>typically results in an address which can be bookmarked</li>
<li>can be activated by pressing the return key</li>
<li>is announced by screen readers as “Link”</li>
<li>is available to screen reader users within an overall <em>Links</em> list</li>
</ul>
<p>A button…</p>
<ul>
<li><em>does something</em> (i.e. performs an action, such as “Add”, “Update” or "Show")</li>
<li>can be used as <code><button type=submit></code> within a form to submit the form. This is a modern replacement for <code><input type=submit /></code> and much better as it’s easier to style, allows nested HTML and supports CSS pseudo-elements</li>
<li>can be used as <code><button type=button></code> to trigger JavaScript. This type of button is different to the one used for submitting a <code><form></code>. It can be used for any type of functionality that happens in-place rather than taking the user somewhere, such as expanding and collapsing content, or performing a calculation.</li>
<li>historically and by default appears in a pill or rounded rectangle</li>
<li>uses the normal mouse pointer arrow</li>
<li>can be activated by pressing return <em>or space.</em></li>
<li>implictly gets the <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role">ARIA button role</a>.</li>
<li>can be extended with further ARIA button-related states like <code>aria-pressed</code></li>
<li>is announced by screen readers as “Button”</li>
<li>unlike a link is not available to screen reader users within a dedicated list</li>
</ul>
<h2 id="our-responsibilities" tabindex="-1">Our responsibilities <a class="direct-link" href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/#our-responsibilities" aria-hidden="true">#</a></h2>
<p>It’s our job as designers and developers to use the appropriate purpose-built element for each situation, to present it in a way that respects conventions so that users know what it is, and to then meet their expectations of it.</p>
<h2 id="tips" tabindex="-1">Tips <a class="direct-link" href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/#tips" aria-hidden="true">#</a></h2>
<ul>
<li>Visually distinguish button-styled call-to-action links from regular buttons, perhaps with a more pill-like appearance and a right-pointing arrow</li>
<li>Avoid a proliferation of call-to-action links by linking <em>content itself</em> (for example a news teaser’s headline). Not only does this reduce “link or button?” confusion but it also saves space, and provides more accessible link text.</li>
<li>Consider having separate Design System components for Button and <a href="https://seek-oss.github.io/braid-design-system/components/ButtonLink/">ButtonLink</a> to reinforce important differences.</li>
<li>For triggering JavaScript-powered interactions I’ll typically use a <code>button</code>. However in disclosure patterns where the trigger and target element are far apart in the DOM <a href="https://fuzzylogic.me/posts/2021-01-24-adactio-journalaccessible-interactions/">it can make sense to use a link as the trigger</a>.</li>
<li>For buttons which are reliant on JavaScript, it’s best to use them within a strategy of progressive enhancement and not render them on the server but rather with client-side JavaScript. That way, if the client-side JavaScript is unsupported or fails, the user won’t be presented with a broken button.</li>
</ul>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/buttons-versus-links-differences-and-tips/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://adactio.com/journal/17768">Get safe</a>, by Jeremy Keith</li>
<li><a href="https://yatil.net/blog/buttons-vs-links">Buttons vs. Links</a>, by Eric Eggert</li>
<li><a href="https://www.buttoncheatsheet.com/">The Button Cheat Sheet</a>, by Manuel Matuzović</li>
<li><a href="https://css-tricks.com/a-complete-guide-to-links-and-buttons/">A complete guide to links and buttons</a> on CSS-Tricks</li>
<li><a href="https://speakerdeck.com/marcysutton/the-links-vs-buttons-showdown">The Links vs Buttons Showdown</a>, by Marcy Sutton</li>
</ul>
HTML with Superpowers (from Dave Rupert)2021-10-19T14:50:51Zhttps://fuzzylogic.me/posts/html-with-superpowers-from-dave-rupert/<p>Here’s a great new presentation by Dave Rupert (of the <a href="https://shoptalkshow.com/">Shop Talk</a> show) in which he makes a compelling case for adopting Web Components. Not only do they provide the same benefits of encapsulation and reusability as components in proprietary JavaScript frameworks, but they also bring the reliability and portability of web standards, work without build tools, are suited to progressive enhancement, and may pave the way for a better web.</p>
<p>Dave begins by explaining that Web Components are based on not just a set of technologies but a set of <em>standards</em>, namely:</p>
<ul>
<li>Custom Elements (for example <code><custom-alert></code>)</li>
<li>Shadow DOM</li>
<li>ES Modules</li>
<li>the HTML <code><template></code> element</li>
</ul>
<p>Standards have the benefit that we can rely on them to endure and work into the future in comparison to proprietary technologies in JavaScript frameworks. That’s good news for people who like to avoid the burnout-inducing churn of learning and relearning abstractions. Of course the pace of technology change with web standards tends to be slower, however that’s arguably a price worth paying for cross-platform stability and accessibility.</p>
<p>Some of Web Components’ historical marketing problems are now behind them, since they are supported by all major browsers and reaching maturity. Furthermore, web components have two superpowers not found in other JavaScript component approaches:</p>
<p>Firstly, the Shadow DOM (which is both powerful and frustrating). The Shadow DOM provides <em>encapsulation</em> but furthermore in progressive enhancement terms it enables the final, <em>enhanced</em> component output which serves as an upgrade from the baseline <em>Light DOM</em> HTML we provided in our custom element instance. It can be a little tricky or confusing to style, however, although there are ways.</p>
<p>Secondly, you can use web components <em>standalone</em>, i.e. natively, without any frameworks, build tools, or package managers. All that’s required to use a “standalone” is to load the <code><script type=module …></code> element for it and then use the relevant custom element HTML on your page. This gets us closer to just writing HTML rather than wrestling with tools.</p>
<p>Dave highlights an education gap where developers focused on HTML, CSS, and Design Systems don’t tend to use Web Components. He suggests that this is likely as a result of most web component tutorials focusing on JavaScript APIs for JavaScript developers. However we can instead frame Web Component authoring as involving a layered approach that starts with HTML, adds some CSS, then <em>ends</em> by applying JavaScript.</p>
<p>Web Components are perfectly suited to progressive enhancement. And that progressive enhancement might for example apply lots of complicated ARIA-related accessibility considerations. I really like the <a href="https://genericcomponents.netlify.app/generic-tabs/demo/index.html">Tabs example</a> where one would create a <code><generic-tabs></code> instance which starts off with simple, semantic, resilient HTML that renders headings and paragraphs…</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>generic-tabs</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>About<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>About content goes here. Lorem ipsum dolor sit amet…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Contact<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Contact content goes here. Lorem ipsum dolor sit amet…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>generic-tabs</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>…but the Web Component’s JavaScript would include a <code>template</code> and use this to upgrade the Light DOM markup into the final interactive tab markup…</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>generic-tabs</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span> <span class="token attr-name">slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tab<span class="token punctuation">"</span></span> <span class="token attr-name">aria-selected</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tab<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>generic-tab-3-0<span class="token punctuation">"</span></span> <span class="token attr-name">aria-controls</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>generic-tab-3-0<span class="token punctuation">"</span></span> <span class="token attr-name">selected</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span>About<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tabpanel<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>generic-tab-3-0<span class="token punctuation">"</span></span> <span class="token attr-name">slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>panel<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>About content goes here. Lorem ipsum dolor sit amet…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span> <span class="token attr-name">slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tab<span class="token punctuation">"</span></span> <span class="token attr-name">aria-selected</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">tabindex</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>-1<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tab<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>generic-tab-3-1<span class="token punctuation">"</span></span> <span class="token attr-name">aria-controls</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>generic-tab-3-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Contact<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>tabpanel<span class="token punctuation">"</span></span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>generic-tab-3-1<span class="token punctuation">"</span></span> <span class="token attr-name">slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>panel<span class="token punctuation">"</span></span> <span class="token attr-name">hidden</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Contact content goes here. Lorem ipsum dolor sit amet…<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>generic-tabs</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>The idea is that the component’s JS would handle all the <a href="https://github.com/thepassle/generic-components/blob/master/generic-tabs/GenericTabs.js#L98">complex interactivity and accessibility requirements of Tabs</a> under the hood. I think if I were implementing something like Inclusive Components’ <a href="https://inclusive-components.design/tabbed-interfaces/">Tabs component</a> these days I’d seriously consider doing this as a Web Component.</p>
<p>Later, Dave discusses the JavaScript required to author a Custom Element. He advises that in order to avoid repeatedly writing the same lengthy, boilerplate code on each component we might use a lightweight library such as his favourite, <a href="https://lit-element.polymer-project.org/guide">LitElement</a>.</p>
<p>Lastly, Dave argues that by creating and using web components we are working with web standards rather than building for a proprietary library. We are creating compatible components which pave the cowpaths for these becoming future HTML standards (e.g. a <code><tabs></code> element!) And why is advancing the web important? Because an easier web lowers barriers: less complexity, less tooling and setup, less gatekeeping—a web for everyone.</p>
How to debug event listeners with your browser’s developer tools (on Go Make Things)2021-10-18T16:34:48Zhttps://fuzzylogic.me/posts/how-to-debug-event-listeners-with-your-browser-s-developer-tools-on-go-make-things/<blockquote>
<p>On the page, right-click the element you want to debug event listeners for, then click <em>Inspect Element</em>. In chromium-based browsers like MS Edge and Google Chrome, click the <em>Event Listeners</em> tab in Developer Tools. There, you’ll see a list of all of the events being listened to on that element. If you expand the event, you can see what element they’re attached to and click a link to open up the actual event listener itself in the JavaScript.</p>
</blockquote>
Conditional border-radius in CSS (by Ahmad Shadeed via CSS-Tricks)2021-10-16T14:05:05Zhttps://fuzzylogic.me/posts/conditional-border-radius-in-css-by-ahmad-shadeed-via-css-tricks/<p>Here’s a “media query free” CSS one-liner which lets you set an element to have no border-radius when it is the full width of the viewport, but otherwise to have a border-radius.</p>
<p>It uses the same 9999 multiplication technique as <a href="https://every-layout.dev/">Every Layout</a> do to create a toggle.</p>
<p>Great for <em>Card</em> components which need to be full-width and non-rounded only on narrow viewports.</p>
I’ve started reading Uncanny Valley, by Anna Wiener2021-10-15T23:00:00Zhttps://fuzzylogic.me/posts/i-ve-started-reading-uncanny-valley-by-anna-wiener/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9780008296865">Uncanny Valley</a>, by Anna Wiener.</p>
<p>Thanks for the recommendation, <a href="https://twitter.com/mrtomchurchill">@mrtomchurchill</a>.</p>
Design Engineering, on the Clearleft Podcast2021-10-04T08:56:49Zhttps://fuzzylogic.me/posts/design-engineering-on-the-clearleft-podcast/<p>Loved this short listen from Clearleft, on a subject close to my heart! New job titles can feel a bit “emperor’s new clothes” but with <em>Design Engineering</em> I think Clearleft, GitHub et al. might be onto something. It was fascinating hearing people from both design and engineering backgrounds give their perspectives, and how ultimately they’re addressing the same thing—the need to “finesse the overlaps/gaps” between design and the realisation of that design in engineering, especially in light of the complexities of the modern front-end.</p>
<p>(via <a href="https://twitter.com/stugoo">@Stugoo</a>)</p>
Broken Copy, on a11y-101.com2021-10-03T19:06:35Zhttps://fuzzylogic.me/posts/broken-copy-on-a11y-101.com/<p>Here’s an accessibility tip that’s new to me. When the content of a heading, anchor, or other semantic HTML element contains smaller “chunks” of <code>span</code> and <code>em</code> (etc), the <em>VoiceOver</em> screen reader on Mac and iOS annoyingly fails to announce the content as a single phrase and instead repeats the parent element’s role for each inner element. We can fix that by adding an inner “wrapper” element inside our parent and giving it <code>role=text</code>.</p>
<p>Make sure not to add this role directly to your parent element since it will override its original role causing it to lose its intended semantics.</p>
<p>The <code>text</code> role is not yet in the official ARIA spec but is supported by Safari.</p>
<p>(via <a href="https://fuzzylogic.me/posts/broken-copy-on-a11y-101.com/">@Seraphae and friends</a> on Twitter)</p>
Motion One: The Web Animations API for everyone2021-10-02T21:28:21Zhttps://fuzzylogic.me/posts/motion-one-the-web-animations-api-for-everyone/<blockquote>
<p>A new animation library, built on the Web Animations API for the smallest filesize and the fastest performance.</p>
</blockquote>
<p>This JavaScript-based animation library—which can be installed via npm—leans on <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API">an existing web API</a> to keep its file size low and uses hardware accelerated animations where possible to achieve impressively smooth results.</p>
<p>For fairly basic animations, this might provide an attractive alternative to the heavier Greensock. The Motion docs do however flag the limitation that it can only animate “CSS styles”. They also say “SVG styles work fine”. I hope by this they mean SVG presentation attributes rather than inline CSS on an SVG, although it’s hard to tell. However <a href="https://motion.dev/examples/path-drawing">their examples look promising</a>.</p>
<p>The docs website also contains some really great background information regarding <a href="https://motion.dev/guides/performance">animation performance</a>.</p>
Testing ES modules with Jest2021-10-01T07:37:58Zhttps://fuzzylogic.me/posts/testing-es-modules-with-jest/<p>Here are a few troubleshooting tips to enable Jest, the JavaScript testing framework, to be able to work with ES modules without needing Babel in the mix for transpilation. Let’s get going with a basic set-up.</p>
<p><code>package.json</code></p>
<figure>
<pre><code>…,
"scripts": {
"test": "NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest"
},
"type": "module",
"devDependencies": {
"jest": "^27.2.2"
}
</code></pre>
</figure>
<p>Note: take note of the crucial <code>"type": "module"</code> part as it’s the least-documented bit and your most likely omission!</p>
<p>After that set-up, you’re free to <code>import</code> and <code>export</code> to your heart’s content.</p>
<p><code>javascript/sum.js</code></p>
<figure>
<pre><code>export const sum = (a, b) => {
return a + b;
}
</code></pre>
</figure>
<p><code>spec/sum.test.js</code></p>
<figure>
<pre><code>import { sum } from "../javascript/sum.js";
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
</code></pre>
</figure>
<p>Hopefully that’ll save you (and future me) some head-scratching.</p>
<p>(Reference: <a href="https://jestjs.io/docs/ecmascript-modules">Jest’s EcmaScript Modules docs page</a>)</p>
Harry Roberts says “Get Your Head Straight”2021-09-30T08:42:27Zhttps://fuzzylogic.me/posts/harry-roberts-says-get-your-head-straight/<p>Harry Roberts (who created ITCSS for organising CSS at scale but these days focuses on performance) has just given a presentation about the importance of getting the content, order and optimisation of the <code><head></code> element right, including lots of measurement data to back up his claims. Check out the slides: <a href="https://speakerdeck.com/csswizardry/get-your-head-straight">Get your Head Straight</a></p>
<p>While some of the information about asset loading best practices is not new, the stuff about <em>ordering</em> of <code>head</code> elements is pretty interesting. I’ll be keeping my eyes out for a video recording of the presentation though, as it’s tricky to piece together his line of argument from the slides alone.</p>
<p>However one <em>really</em> cool thing he’s made available is a bookmarklet for evaluating any website’s <code><head></code>:<br />
— <a href="https://csswizardry.com/ct/">ct.css</a></p>
The accessibility of conditionally revealed questions (on GOV.UK)2021-09-22T10:21:20Zhttps://fuzzylogic.me/posts/the-accessibility-of-conditionally-revealed-questions-on-gov.uk/<p>Here’s something to keep in mind when designing and developing forms. <a href="http://gov.uk/">GOV.UK</a>’s accessibility team found last year that there are some accessibility issues with the “conditional reveal” pattern, i.e. when selecting a particular radio button causes more inputs to be revealed.</p>
<p><a href="https://accessibility.blog.gov.uk/2021/09/21/an-update-on-the-accessibility-of-conditionally-revealed-questions/">The full background story</a> is really interesting but the main headline seems to be: <em>Keep it simple.</em></p>
<ol>
<li>Don’t reveal any more than a <em>single input</em>, otherwise the revealed section should not be in a show-and-hide but rather in its own form in the next step of the process.</li>
<li>Conditionally show <em>questions only</em> (i.e. another form input such as <em>Email address</em>)—do not show or hide anything that’s not a question.</li>
</ol>
<p>Doing otherwise causes some users confusion making it difficult for them to complete the form.</p>
<p>See also the <em>Conditionally revealing a related question</em> section on <a href="https://design-system.service.gov.uk/components/radios/">the Radios component on the GDS Design System</a></p>
W3C Design System2021-09-19T18:07:24Zhttps://fuzzylogic.me/posts/w3c-design-system/<p>The <a href="https://www.w3.org/Consortium/">W3C</a> have just published a new Design System. It was developed by British Digital Agency <a href="https://fuzzylogic.me/posts/w3c-design-system/">Studio 24</a>, who are also working (in the open) on <a href="https://www.studio24.net/work/working-in-the-open-with-w3c/">the redesign of the W3C website</a>.</p>
<p>My initial impression is that this Design System feels pretty early-stage and work-in-progress. I’m not completely sold on <em>all</em> of the technical details, however it definitely contains a number of emergent best practices and lots of interesting parts.</p>
<p>I particularly liked the very detailed <a href="https://design-system.w3.org/styles/forms.html">Forms</a> section which assembles lots of good advice from Adam Silver and <a href="http://gov.uk/">GOV.UK</a>, and I also found it interesting and useful that they include a <a href="https://design-system.w3.org/templates/">Page Templates</a> section rather than just components and layouts.</p>
<p>It’s cool to see an institution like the W3C have a Design System, and I’m looking forward to seeing how it evolves.</p>
Note 2021-0-16T10:02:50: Octavia E. Butler – Kindred2021-09-15T23:00:00Zhttps://fuzzylogic.me/posts/note-2021-4-20t13-00-50-ted-chiang-stories-of-your-life-and-others-copy/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781472258229">Kindred</a>, by Octavia E. Butler.</p>
Accessibility Testing (on adactio.com)2021-09-15T12:32:02Zhttps://fuzzylogic.me/posts/accessibility-testing-on-adactio.com/<p>In this journal entry, Jeremy Keith argues that when it comes to accessibility testing it’s not just about finding issues—it’s about finding the issues at the right time.</p>
<p>Here’s my summary:</p>
<ul>
<li>Accessibility Audits performed by experts and real Assistive Technology users are <em>good!</em></li>
<li>But try to get the most out of them by having them focus on the things that you can’t easily do yourself.</li>
<li>We ourselves can handle things like colour contrast. It can be checked at the design stage before a line of code is written.</li>
<li>Likewise HTML structure such as ensuring accessible form labels, ensuring images have useful <code>alt</code> values, using landmarks like <code>main</code> and <code>nav</code>, heading structure etc. These are not tricky to find and fix ourselves <em>and</em> they have a big accessibility impact.</li>
<li>As well as fixing those issues ourselves we should also put in place new processes, checks and automation if possible to stop them recurring</li>
<li>As for <em>custom interactive elements</em> (tabs, carousels, navigation, dropdowns): these are specific to our site and complicated/error-prone by nature, so <em>those</em> are the things we should be aiming to have professional Accessibility Audits focus on in order to get best value for money.</li>
</ul>
Practical front-end performance tips2021-09-14T12:53:18Zhttps://fuzzylogic.me/posts/practical-performance-tips/<p>I’ve been really interested in the subject of Web Performance since I read Steve Souders’ book <em>High Performance Websites</em> back in 2007. Although some of the principles in that book are still relevant, it’s also fair to say that a lot has changed since then so I decided to pull together some current tips. Disclaimer: This is a living document which I’ll expand over time. Also: I’m a performance <em>enthusiast</em> but not an expert. If I have anything wrong, please let me know.</p>
<h2 id="inlining-css-and-or-javascript" tabindex="-1">Inlining CSS and or JavaScript <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#inlining-css-and-or-javascript" aria-hidden="true">#</a></h2>
<p>The first thing to know is that both CSS and JavaScript are (by default) render-blocking, meaning that when a browser encounters a standard <code>.css</code> or <code>.js</code> file in the HTML, it waits until that file has finished downloading before rendering anything else.</p>
<p>The second thing to know is that there is a “magic file size” when it comes to HTTP requests. File data is transferred in small chunks of about 14 kb. So if a file is larger than 14 kb, it requires multiple roundtrips.</p>
<p>If you have a lean page and minimal CSS and or JavaScript to the extent that the page in combination with the (minified) CSS/JS content would weigh 14 kb or less after minifying and gzipping, you can achieve better performance by inlining your CSS and or JavaScript into the HTML. This is because there’d be only one request, thereby allowing the browser to get everything it needs to start rendering the page from that single request. So your page is gonna be <em>fast</em>.</p>
<p>If your page including CSS/JS is <em>over</em> 14 kb after minifying and gzipping then you’d be better off not inlining those assets. It’d be better for performance to link to external assets and let them be <em>cached</em> rather than having a bloated HTML file that requires multiple roundtrips and doesn’t get the benefit of static asset caching.</p>
<h2 id="avoid-css-%40import" tabindex="-1">Avoid CSS <code>@import</code> <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#avoid-css-%40import" aria-hidden="true">#</a></h2>
<p><a href="https://csswizardry.com/2018/11/css-and-network-performance/#avoid-import-in-css-files">CSS @import is really slow!</a></p>
<h2 id="javascript-modules-in-the-head" tabindex="-1">JavaScript modules in the head <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#javascript-modules-in-the-head" aria-hidden="true">#</a></h2>
<p>Native JavaScript modules are included on a page using the following:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>main.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<p>Unlike standard <code><script></code> elements, module scripts are deferred (non render-blocking) by default. Rather than placing them before the closing <code></body></code> tag I place them in the <code><head></code> so as to allow the script to be downloaded <em>early</em> and in parallel with the DOM being processed. That way, the JavaScript is already available as soon as the DOM is ready.</p>
<h2 id="background-images" tabindex="-1">Background images <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#background-images" aria-hidden="true">#</a></h2>
<p>Sometimes developers implement an image as a CSS background image rather than a “content image”, either because they feel it’ll be easier to manipulate that way—a typical example being a responsive hero banner with overlaid text—or simply because it’s decorative rather than meaningful. However it’s worth being aware of how that impacts the way that image loads.</p>
<p>Outgoing requests for images defined in CSS rather than HTML won’t start until the browser has created the <a href="https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction">Render Tree</a>. The browser must first download and parse the CSS then construct the CSSOM before it knows that “Element X” should be visible and has a background image specified, in order to then decide to download that image. For important images, that might feel too late.</p>
<p><a href="https://csswizardry.com/2018/06/image-inconsistencies-how-and-when-browsers-download-images/#0">As Harry Roberts explains</a> it’s worth considering whether the need might be served as well or better by a content image, since by comparison that allows the browser to discover and request the image nice and early.</p>
<blockquote>
<p>By moving the images to <img> elements… the browser can discover them far sooner—as they become exposed to the browser’s preload scanner—and dispatch their requests before (or in parallel to) CSSOM completion</p>
</blockquote>
<p>However if still makes sense to use a background image and performance is important <a href="https://twitter.com/csswizardry/status/1276854595382325248">Harry recommends including an accompanying hidden image</a> inline or preloading it in the <code><head></code> via <code>link rel=preload</code>.</p>
<h2 id="preload" tabindex="-1">Preload <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#preload" aria-hidden="true">#</a></h2>
<p>From <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload">MDN’s preload docs</a>, preload allows:</p>
<blockquote>
<p>specifying resources that your page will need very soon, which you want to start loading early in the page lifecycle, before browsers' main rendering machinery kicks in. This ensures they are available earlier and are less likely to block the page's render, improving performance.</p>
</blockquote>
<p>The benefits are most clearly seen on large and late-discovered resources. For example:</p>
<ul>
<li>Resources that are pointed to from inside CSS, like fonts or images.</li>
<li>Resources that JavaScript can request such as JSON and imported scripts.</li>
<li>Larger images and videos.</li>
</ul>
<p>I’ve recently used the following to assist performance of a large CSS background image:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>preload<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>bg-illustration.svg<span class="token punctuation">"</span></span> <span class="token attr-name">as</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(min-width: 60em)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
</figure>
<h2 id="self-host-your-assets" tabindex="-1">Self-host your assets <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#self-host-your-assets" aria-hidden="true">#</a></h2>
<p>Using third-party hosting services for fonts or other assets no longer offers the previously-touted benefit of the asset potentially already being in the user’s browser cache. Cross domain caching has been disabled in all major browsers.</p>
<p>You can still take advantage of the benefits of CDNs for reducing network latency, but preferably as part of your own infrastructure.</p>
<h2 id="miscellaneous" tabindex="-1">Miscellaneous <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#miscellaneous" aria-hidden="true">#</a></h2>
<p><a href="https://csswizardry.com/2022/09/critical-css-not-so-fast/">Critical CSS is often a wasted effort</a> due to CSS not being a bottleneck, so is generally not worth doing.</p>
<!--
Other stuff to add:
- optimise font loading (WOFF2, …, …) ref https://www.zachleat.com/web/font-checklist/
- Use HTTP2 which is now supported by all major browsers to optimise asset delivery to users’ devices
-->
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/practical-performance-tips/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://gomakethings.com/inlining-literally-everything-for-better-performance/">Inlining literally everything</a> on Go Make Things</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules">MDN’s guide to native JavaScript modules</a></li>
<li><a href="https://csswizardry.com/2018/06/image-inconsistencies-how-and-when-browsers-download-images/#0">How and when browsers download images</a> by Harry Roberts</li>
</ul>
Doppler: Type scale with dynamic line-height2021-09-07T10:38:35Zhttps://fuzzylogic.me/posts/doppler-type-scale-with-dynamic-line-height/<p><code>line-height</code> on the web is a tricky thing, but this tool offers a clever solution.</p>
<p>It’s relatively easy to set a sensible unit-less default ratio for body text (say <code>1.5</code>), but that tends to need tweaked and tested for headings (where spacious line-height doesn’t quite work; but tight line-height is nice until the heading wraps, etc).</p>
<p>Even for body text it’s a not a one-size-fits-all where a line-height like <code>1.5</code> is appropriate for all fonts.</p>
<p>Then you’ve got different devices to consider. For confined spaces, tighter line-height works better. But this can mean you might want one line-height for narrow viewports and another for wide.</p>
<p>Then, factor in vertical rhythm based on your modular type and spacing scales if you really want to blow your mind.</p>
<p>It can quickly get really complicated!</p>
<p>Doppler is an interesting idea and tool that I saw in CSS-Tricks’ newsletter this morning. It lets you apply <code>line-height</code> using <code>calc()</code> based on one <code>em</code>-relative value (for example <code>1em</code>) and one <code>rem</code>-relative value (for example <code>0.25rem</code>).</p>
<p>In effect you’ll get something like:</p>
<blockquote>
<p>set line-height to the font-size of the current element plus a quarter of the user’s preferred font-size</p>
</blockquote>
<p>The examples look pretty promising and seem to work well across different elements. I think I’ll give it a spin.</p>
Big list of http static server one-liners2021-09-01T20:03:21Zhttps://fuzzylogic.me/posts/big-list-of-http-static-server-one-liners/<p>Lots of different options for running a local web server. Choose from npx, ruby, python and many more.</p>
<p>I also like Ritwick Dey’s <a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer">Live Server extension for VS Code</a>.</p>
Accessible Color Generator2021-08-30T14:40:07Zhttps://fuzzylogic.me/posts/accessible-color-generator/<p>There are many <a href="https://fuzzylogic.me/tags/contrast/">colour contrast checking tools</a> but I like this one from Erik Kennedy (of <a href="https://learnui.design/">Learn UI Design</a>) a lot. It features an intuitive UI using simple, human language that mirrors the task I’m there to achieve, and it’s great that if your target colour doesn’t have sufficient contrast to meet accessibility guidelines it will intelligently suggest alternatives that do.</p>
<p>I’m sure everyone has their favourite tools; I just find this one really quick to use!</p>
SVG Gobbler2021-08-26T10:26:11Zhttps://fuzzylogic.me/posts/svg-gobbler/<blockquote>
<p>SVG Gobbler is a browser extension that finds the vector content on the page you’re viewing and gives you the option to download, optimize, copy, view the code, or export it as an image.</p>
</blockquote>
<p>This is a pretty handy Chrome extension that grabs all the SVGs on a webpage and lets you see them all in a grid.</p>
Progressively enhanced burger menu tutorial by Andy Bell2021-08-12T21:13:26Zhttps://fuzzylogic.me/posts/progressively-enhanced-burger-menu-tutorial-by-andy-bell/<p>Here’s a smart and comprehensive tutorial from Andy Bell on how to create a progressively enhanced narrow-screen navigation solution using a custom element. Andy also uses <code>Proxy</code> for “enabled” and “open” state management, <code>ResizeObserver</code> on the custom element’s containing <code>header</code> for a Container Query like solution, and puts some serious effort into accessible focus management.</p>
<p>One thing I found really interesting was that Andy was able to style child elements of the custom element (as opposed to just elements which were present in the original unenhanced markup) from his global CSS. My understanding is that you can’t get styles other than inheritable properties through the <em>Shadow Boundary</em> so this had me scratching my head. I think the explanation is that Andy is not attaching the elements he creates in JavaScript to the Shadow DOM but rather rewriting and re-rendering the element’s <code>innerHTML</code>. This is an interesting approach and solution for getting around web component styling issues. I see elsewhere online that <a href="https://developers.google.com/web/fundamentals/web-components/customelements#addingmarkup">the <code>innerHTML</code> based approach is frowned upon</a> however Andy doesn’t “throw out” the original markup but instead augments it.</p>
Should I use the HTML5 section element and if so, where? 2021-08-05T20:08:02Zhttps://fuzzylogic.me/posts/should-i-use-the-html5-section-element-and-if-so-where/<p>Unlike other HTML5 elements such as <code>header</code>, <code>footer</code> and <code>nav</code>, it’s never been particularly clear to me when is appropriate to use <code>section</code>. This is due in large part to many experts having expressed that it doesn’t quite work as intended.</p>
<p>I like <a href="https://www.htmhell.dev/tips/the-section-element/">HTMHell’s rule-of-thumb regarding <code>section</code></a>:</p>
<blockquote>
<p>If you’re not sure whether to use a <code><section></code>, it’s probably best to avoid it.</p>
</blockquote>
<p>They go on to recommend that it’s much more important to create a sound document outline. That phrase can be confusing because of the related history of the browser document outline algorithm (or lack thereof) but I think what the author means here is to use and nest headings logically because that alone will give you a “document outline” and also helps AT users scan and skip around the page.</p>
<p>Relatedly: don’t let the original intended use of <code>section</code> tempt you to put multiple H1s on a page in the vain hope that browsers and assistive technology will interpret their nesting level to handle hierarchy appropriately. That would rely on on a document outline algorithm but <a href="https://adrianroselli.com/2016/08/there-is-no-document-outline-algorithm.html">no browser implements document outlining</a>.</p>
<p>One sensible application of <code>section</code> is to provide additional information to screen reader users about the semantic difference between two adjoining content areas, when that distinction is otherwise only being made visually with CSS.</p>
<p>Here’s an example. Smashing Magazine’s blog articles begin with a <em>quick summary</em>, followed by a horizontal line separating the summary from the article proper. But the separator is purely decorative, so if the summary were wrapped in a <code>div</code> then a screen reader user wouldn’t know where it ends and the article begins. However by instead wrapping the summary in <code><section aria-label="quick summary"></code>:</p>
<ul>
<li>our wrapper has the built-in ARIA role of <code>region</code><em>.</em> A <code>region</code> is a type of generic <a href="https://www.scottohara.me/blog/2018/03/03/landmarks.html">landmark</a> element, and as a landmark a screen reader user will find it listed in a summary of the page and can navigate to it easily.</li>
<li>by giving it an accessible name (here via <code>aria-label</code>) it will be <em>announced</em> by a screen reader, with “Quick summary region” before and “Quick summary region end” after.</li>
</ul>
<h2 id="update-07%2F11%2F22" tabindex="-1">Update 07/11/22 <a class="direct-link" href="https://fuzzylogic.me/posts/should-i-use-the-html5-section-element-and-if-so-where/#update-07%2F11%2F22" aria-hidden="true">#</a></h2>
<p><a href="https://twitter.com/aardrian/status/1587524667325177864">Adrian Roselli’s twitter thread on section</a> is gold. Here’s what I’ve gleaned from it:</p>
<p>The reason you would use a <code>section</code> element for accessibility purposes is to create a <a href="https://www.w3.org/TR/html-aria/#el-section"><code>region</code> landmark</a>. If you are using headings properly, in most cases your content is already well-structured and will not require a region landmark. If you do need a section, note that from an accessibility perspective using the <code>section</code> tag alone is meaningless without providing an accessible name. To provide this, ensure your section has a heading and connect the <code>section</code> to that using <code>aria-labelledby</code>.</p>
<p>You <em>can</em> use <code>section</code> without the above measures and it will not harm users. But be aware it’s aiding your developer experience only, because it’s not helping users. And it may also mislead you and others into thinking you are providing semantics and accessibility which in reality you are not.</p>
<h2 id="references%3A" tabindex="-1">References: <a class="direct-link" href="https://fuzzylogic.me/posts/should-i-use-the-html5-section-element-and-if-so-where/#references%3A" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.scottohara.me/blog/2021/07/16/section.html">Accessibility of the section element</a>, by Scott O’Hara</li>
<li><a href="https://www.smashingmagazine.com/2020/01/html5-article-section/">Why you should choose HTML5 <code>article</code> over <code>section</code></a>, by Bruce Lawson</li>
</ul>
Use Eleventy templating to include static code demos2021-08-03T16:02:03Zhttps://fuzzylogic.me/posts/use-eleventy-templating-to-include-static-code-demos/<p>Here’s a great tutorial from Eleventy guru <a href="https://twitter.com/5t3ph">Stephanie Eckles</a> in which she explains how to create a page that displays multiple code demos, similar to <a href="https://smolcss.dev/">SmolCSS.dev</a>.</p>
<p>It’s interesting that Stephanie uses 11ty shortcodes over <a href="https://fuzzylogic.me/posts/reusable-code-snippets-and-components-in-eleventy/">other 11ty templating options</a> and that she sometimes declares a variable (via Nunjucks’s <code>set</code>) at the top of the page then intentionally <em>reuses it unchanged</em> in repeated shortcode instances… the example being times where you want to illustrate the same HTML code (variable) being styled differently in progressive demos.</p>
<p>I also like the <em>Open in CodePen</em> feature and section on scoped styling.</p>
Reusable code snippets and components in Eleventy2021-08-03T15:04:22Zhttps://fuzzylogic.me/posts/reusable-code-snippets-and-components-in-eleventy/<p>There are (at least) three cunning ways in Eleventy to get “reusable snippet” or “reusable component” functionality.</p>
<ol>
<li>Nunjucks’s <code>include</code>: Great for just including a common, static element in your template, say a <code>header</code> or <code>footer</code> partial. (Note that while you <em>can</em> <code>set</code> a variable just before your <code>include</code> line to make that variable available to the included partial, it’s not really “passing in” and scoping the variable like a parameter, so it’s best to reserve <code>include</code> for simple stuff.)</li>
<li>Nunjucks’s <code>macro</code>: Takes things up a notch by supporting passing in parameters which are then locally scoped. You could use this to create a simple component. See Trys Mudford’s article <a href="https://www.trysmudford.com/blog/encapsulated-11ty-components/">Encapsulated 11ty Components</a>.</li>
<li>11ty Shortcodes and Named Shortcodes: Shortcodes feel to me pretty much like a wrapper for <code>macro</code>, whilst also supporting the inclusion of <code>npm</code> packages and the use of <code>async</code> functions. However with <em>Named Shortcodes</em>, unlike <code>macro</code> you can also pass in a <code>block</code> of content (rather than arguments alone). This would be handy for any component or layout into which you nest lots of varied content (such as a <a href="https://every-layout.dev/layouts/stack/">Stack</a>, for example). See 11ty docs on <a href="https://www.11ty.dev/docs/shortcodes/#paired-shortcodes">paired shortcodes</a> for more details.</li>
</ol>
<p>Hat tip to Jérome Coupé who <a href="https://twitter.com/jeromecoupe/status/1419726991994068994">recently tweeted on this topic</a> and prompted me to gather my thoughts too.</p>
Note 2021-4-20T13:00:50: Ted Chiang – Stories of your life and others2021-08-01T15:40:00Zhttps://fuzzylogic.me/posts/note-2021-4-20t13-00-50-ted-chiang-exhalation-copy/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781529039436">Stories of your life and others</a> by Ted Chiang.</p>
Crafting Component API, Together (by Nathan Curtis, on Medium)2021-07-19T09:35:03Zhttps://fuzzylogic.me/posts/crafting-component-api-together-by-nathan-curtis-on-medium/<p>Nathan (of <a href="https://eightshapes.com/">EightShapes</a>) discusses how to unify anatomy and props across code and design tools.</p>
<p>I love this article. It tackles some difficult, real problems that occur during the process of trying to align design and development but proposes interesting ways of mitigating them.</p>
<p>I particularly like the idea of adding a formal “API planning” step to the component creation process, and that it’s carried out by a designer and engineer pair, and that it’s documented using a standardised template that can be iterated.</p>
<p>This idea not only tackles those difficult language and conceptual discrepancies between design and code perspectives on a component, but also provides a means through which:</p>
<blockquote>
<p>developers and designers naturally connect</p>
</blockquote>
<p>I’d like to explore this idea further at work in our Design System team.</p>
Manage Design Tokens in Eleventy2021-07-12T20:59:35Zhttps://fuzzylogic.me/posts/manage-design-tokens-in-eleventy/<p>One interesting aspect of the <a href="https://www.duetds.com/">Duet Design System</a> is that they use <a href="https://www.11ty.dev/">Eleventy</a> to not only generate their reference website but also to generate their Design Tokens.</p>
<p>When I think about it, this makes sense. Eleventy is basically a sausage-machine; you put stuff in, tell it how you want it to transform that stuff, and you get something new out the other end. This isn’t just for markdown-to-HTML, but for a variety of formatA-to-formatB transformation needs… including, for example, using JSON to generate CSS.</p>
<p>Now this is definitely a more basic approach than using a design token tool like <a href="https://amzn.github.io/style-dictionary/#/">StyleDictionary</a>. StyleDictionary handles lots of low-level stuff that would otherwise be tricky to implement. So I’m not suggesting that this is a <em>better</em> approach than using StyleDictionary. However it definitely feels pretty straightforward and low maintenance.</p>
<p>As Heydon Pickering explains, it also opens up the opportunity to <a href="https://heydonworks.com/article/design-tokens-in-eleventy/">make the Design Tokens CMS-editable in Netlify CMS</a> without content editors needing to go near the code.</p>
<p>So you’d have a <code>tokens.json</code> file containing your design tokens, but it’d be within the same repo as your reference website. That’s probably not as good as having the tokens in a separate repo and making them available as a package, but of course a separate 11ty repo is an option too if you prefer.</p>
<p>For a smaller site at least, the “manage design tokens with 11ty” is a nice option, and I think I might give it a try on my personal website.</p>
Duet Design System2021-07-05T23:00:00Zhttps://fuzzylogic.me/posts/duet-design-system/<p>Here’s a lovely Design System that interestingly uses <a href="https://www.11ty.dev/">Eleventy</a> for its reference website and other generated artefacts:</p>
<blockquote>
<p>We use Eleventy for both the static documentation and the dynamically generated parts like component playgrounds and design tokens. We don’t currently use a JavaScript framework on the website, except Duet’s own components.</p>
</blockquote>
<p>I find Duet interesting both from the Design System perspective (it contains lots of interesting component techniques and options) but also in terms of how far 11ty can be pushed.</p>
Favourite Eleventy (11ty) Resources2021-07-03T14:24:03Zhttps://fuzzylogic.me/posts/favourite-eleventy-11ty-resources/<p>Here are my current go-to resources when building a new site using Eleventy (11ty).</p>
<p><a href="https://egghead.io/courses/build-an-eleventy-11ty-site-from-scratch-bfd3">Build an Eleventy site from scratch</a> by Stephanie Eckles. As the name suggests, this is for starting from a blank canvas. It includes a really simple and effective way of setting up a Sass watch-and-build pipeline that runs alongside that of Eleventy, using only <code>package.json</code> scripts rather than a bundler.</p>
<p><a href="https://github.com/11ty/eleventy-base-blog">Eleventy Base Blog</a> from 11ty. If rather than a blank canvas you want a boilerplate that includes navigation, a blog, an RSS feed and prism CSS for code block styling (among other things) then this is a great option. Of course, you can also just cherry-pick the relevant code you need, as I often do.</p>
<p><a href="https://www.11ty.dev/docs/plugins/navigation/">Eleventy Navigation Plugin</a>. This allows you to set a page or post as a navigation item. It handily supports ordering and hierarchical nesting (for subnavigation). You can then render out your navigation from a layout in a one-liner or in a custom manner.</p>
<p><a href="https://www.11ty.dev/docs/plugins/cache/">Eleventy Cache Assets Plugin</a>. This is really handy for caching fetched data so as not to exceed API limits or do undue work on every build.</p>
<p><a href="https://11ty-netlify-jumpstart.netlify.app/">11ty Netlify Jumpstart</a> is another from Stephanie Eckles but this time a “quick-start boilerplate” rather than blank canvas. It includes a minimal Sass framework, generated sitemap, RSS feed and social share preview images. The <a href="https://11ty-netlify-jumpstart.netlify.app/about/">About page it generates</a> contains lots of useful info on its features.</p>
<p><a href="https://github.com/forestryio/eleventy-base-forestry/tree/forestry/.forestry">forestry.io settings for 11ty Base Blog</a> and <a href="https://github.com/DirtyF/hylia-forestry/tree/forestry/.forestry">forestry.io settings for Hylia</a> (Andy Bell’s 11ty starter)</p>
<p><a href="https://www.netlifycms.org/docs/add-to-your-site/">Add Netlify CMS to an 11ty-based website</a></p>
<p><a href="https://fuzzylogic.me/tags/11ty/">All my posts tagged “11ty”</a></p>
<p>More to follow…</p>
Adapting Stimulus usage for better Progressive Enhancement2021-07-01T08:48:00Zhttps://fuzzylogic.me/posts/adapting-stimulus-usage-for-better-progressive-enhancement/<p>A while back, <a href="https://twitter.com/jaffathecake/status/1230388412806520833">Jake Archibald tweeted</a>:</p>
<blockquote>
<p>Don't render buttons on the server that require JS to work.</p>
</blockquote>
<p>The idea is that user interface elements which depend on JavaScript (such as buttons) should be rendered <em>on the client-side</em>, i.e. with JavaScript.</p>
<p>In the context of a progressive enhancement mindset, this makes perfect sense. Our <em>minimum viable experience</em> should work without JavaScript due to the <a href="https://kryogenix.org/code/browser/everyonehasjs.html">fragility of a JavaScript-dependent approach</a> so should not include script-triggering buttons which might not work. The JavaScript which applies the enhancements should not only listen for and act upon button events, but should also be responsible for actually rendering the button.</p>
<p>This is how I used to build JavaScript interactions as standard, however sadly due to time constraints and framework conventions I don’t always follow this best practice on all projects.</p>
<p>At work, we use <a href="https://stimulus.hotwired.dev/">Stimulus</a>. Stimulus has a pretty appealing philosophy:</p>
<blockquote>
<p>Stimulus is designed to enhance <em>static</em> or <em>server-rendered</em> HTML—the “HTML you already have”</p>
</blockquote>
<p>However in <a href="https://stimulus.hotwired.dev/handbook/hello-stimulus">their examples</a> they always render buttons on the server; they always assume the JavaScript-powered experience is the baseline experience. I’ve been pondering whether that could easily be adapted toward better progressive enhancement and it seems it can.</p>
<p>My hunch was that I should use the <code>connect()</code> lifecycle method to render a <code>button</code> into the component (and introduce any other script-dependent markup adjustments) at the <em>earliest opportunity</em>. I wasn’t sure whether creating new DOM elements at this point and fitting them with Stimulus-related attributes such as <code>action</code> and <code>target</code> would make them available via the standard Stimulus APIs like server-rendered elements but was keen to try. I started by checking if anyone was doing anything similar and found a thread where <a href="https://github.com/hotwired/stimulus/issues/41#issuecomment-355961542">Stimulus contributor Javan suggested that DIY target creation is fine</a>.</p>
<p>I then gave that a try and it worked! Check out my pen <a href="https://codepen.io/fuzzylogicx/pen/oNWzgzO?editors=1111">Stimulus with true progressive enhancement</a>. It’s a pretty trivial example for now, but proves the concept.</p>
Astro2021-06-25T13:17:34Zhttps://fuzzylogic.me/posts/2021-06-25-astro/<p>Astro looks <em>very</em> interesting. It’s in part a static site builder (a bit like <a href="https://www.11ty.dev/">Eleventy</a>) but it also comes with a modern (revolutionary?) developer experience which lets you author components as web components or in a JS framework of your choice but then renders those to static HTML for optimal performance. Oh, and as far as I can tell theres no build pipeline!</p>
<blockquote>
<p>Astro lets you use any framework you want (or none at all). And if most sites only have islands of interactivity, shouldn’t our tools optimize for that?</p>
</blockquote>
<p>People have been posting some great thoughts and insights on Astro already, for example:</p>
<ul>
<li><a href="https://css-tricks.com/astro/">Chris Coyier’s review</a></li>
<li><a href="https://css-tricks.com/newsletter/255-thoughts-on-astro/">Review in CSS-Tricks Newsletter #255</a> including links to Chris’s Astro demo site</li>
<li><a href="https://www.robinrendle.com/notes/the-web-is-too-damn-complex.html">The web is too damn complex</a>, by Robin Rendle</li>
<li><a href="https://astro.build/blog/introducing-astro">Astro’s introductory blog post</a></li>
</ul>
<p>(via <a href="https://twitter.com/css">@css</a>)</p>
GDS on Twitter: The GOV.UK Design System is turning 3 years old!2021-06-21T14:53:20Zhttps://fuzzylogic.me/posts/2021-06-21-gds-on-twitter-the-govuk-design-system-is-turning-3-years-old/<p>The <a href="http://gov.uk/">GOV.UK</a> Design System is a nice Design System success story. At 3 years old it’s reporting high traffic, usage and satisfaction ratings. GDS do so much great, thoughtful and inclusive work (which they also share with the community) and it’s inspiring to see it being a success.</p>
<blockquote>
<p>There are now more than 900 live cross-government services using the <a href="http://gov.uk/">GOV.UK</a> Design System - 75% more than a year ago. It’s being used in more than 2,600 repositories on GitHub and has been forked more than 200 times.</p>
</blockquote>
clipboard.js - Copy to clipboard without Flash2021-06-19T13:08:24Zhttps://fuzzylogic.me/posts/2021-06-19-clipboardjs-copy-to-clipboard-without-flash/<p>Here’s a handy JS package for “copy to clipboard” functionality that’s lightweight and installable from npm.</p>
<p>It also appears to have good legacy browser support plus a means for checking/confirming support too, which should assist if your approach is to only add a “copy” button to the DOM as a progressive enhancement.</p>
<p>(via <a href="https://twitter.com/chriscoyier">@chriscoyier</a>)</p>
Inclusive language around buttons2021-06-18T10:58:47Zhttps://fuzzylogic.me/posts/2021-06-18-inclusive-language-around-buttons/<p><a href="https://twitter.com/Amy_Hupe">@Amy_Hupe</a> recently posed a great question on Twitter regarding inclusive language for buttons:</p>
<blockquote>
<p>What's an inclusive way to describe what you do to a (digital) button, given it might be pressed with a mouse click, a screen tap, a key on a keyboard, and so on? I've tended to use "select" but wondering if that's right?</p>
</blockquote>
<p>There are a lot of good suggestions and my current feeling is that:</p>
<ol>
<li>it depends. What’s right for one context may not be for another; and</li>
<li>there are a few good ones.</li>
</ol>
<p>My favourites are:</p>
<ul>
<li>use;</li>
<li>“click or tap”; and <em>maybe</em></li>
<li>press (which may work as a common abstraction).</li>
</ul>
<p>I also offerered this alternative/remix:</p>
<blockquote>
<p>Could another way to do this / work around the awkwardness be via the pattern “Do thing X by using the Y button”? i.e. describe the action/result, making the button itself less important so you can just use “using” as your verb. So… “Submit the form using the “Submit” button”.</p>
<p>“via” is another word/pattern that’d similarly allow less need to worry about physical stuff. So “Launch a preview via the “Preview” button”. Same idea as “using”.</p>
</blockquote>
<p>And I liked Craig Abbot’s observation:</p>
<blockquote>
<p>it’s actually a bit weird to describe the physical interactions anyway. It should be intuitive. If a button says continue, it’s pretty obvious you need to interact with it. If you need to explain the UI usually there’s a bigger problem.</p>
</blockquote>
<p>I’m not such a fan of these suggestions:</p>
<ul>
<li>select; and</li>
<li>activate</li>
</ul>
Kazuo Ishiguro – Never Let Me Go2021-06-13T22:43:17Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-kazuo-ishiguro-%E2%80%93-never-let-me-go/<p>I’ve just finished reading <a href="https://www.hive.co.uk/Product/Kazuo-Ishiguro/Never-Let-Me-Go/1518724">Never Let Me Go</a> by Kazuo Isihiguro.</p>
<p>Afterwards I was also keen to see <a href="https://www.imdb.com/title/tt1334260/">the film</a>, which I enjoyed. It featured great performances by Carey Mulligan and Andrew Garfield in particular, and a haunting score. Although I enjoyed the book, I found it a little slow-paced and so watching the film helped bring it all together (despite taking a few liberties with the plot).</p>
<p>Lastly, I enjoyed <a href="https://youtu.be/_jCB59pPG7k">this short interview with the author</a> in which he interestingly remarked that the sci-fi element was just a device to support the primary topic of managing friendship and loving relationships within our short lifetimes.</p>
Lightning Design System2021-06-09T12:54:43Zhttps://fuzzylogic.me/posts/2021-06-09-lightning-design-system/<p>I should have bookmarked it long before now, but just revisiting the Lightning Design System I’m reminded that is really well organised and executed.</p>
<blockquote>
<p>SLDS saves time and energy, freeing designers and developers to focus on larger issues of usability and meaning. Standardized, reusable components support collaboration, reinforce branding, and provide a consistent look and user experience.</p>
</blockquote>
Plant43 – Light Pollution2021-05-29T22:28:35Zhttps://fuzzylogic.me/posts/plant43-%E2%80%93-light-pollution/<p>Having a nice moment revisiting this amazing 2006 Ai records double-header from <a href="https://twitter.com/datassette">@datassette</a> and <a href="https://twitter.com/plant43_">@plant43_</a> and remembering pre-lockdown Glasgow life.</p>
<div class="l-frame"><iframe title="Artist – Title" width="560" height="315" src="https://www.youtube-nocookie.com/embed/_JVmPmd5s4g" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
Inspire.js2021-05-24T15:35:50Zhttps://fuzzylogic.me/posts/2021-05-24-inspirejs/<blockquote>
<p>Lean, hackable, extensible slide deck framework</p>
</blockquote>
<p>I’ve been on the lookout for a lightweight, web standards based slide deck solution for a while and this one from Lea Verou could well be perfect.</p>
<p>It has keyboard navigation, video and code demo support, an index page and much more… and it’s all powered by straightforward HTML, CSS and JavaScript. I need to give this a spin!</p>
Shifting left: how introducing accessibility earlier helps the BBC’s design system (by Sophie Beaumont)2021-05-24T10:17:38Zhttps://fuzzylogic.me/posts/2021-05-24-shifting-left-how-introducing-accessibility-earlier-helps-the-bbcs-design-system-or-by-sophie-beaumont-or-bbc-design-engineering/<p>Absolute gold here regarding accessibility, bloated components, and purpose versus appearance.</p>
<blockquote>
<p>It’s easy for a component to become bloated and its purpose increasingly ambiguous.</p>
</blockquote>
<p>The article also makes a fundamental point.</p>
<p>When you need a new UI element, just because an existing component <em>looks similar</em> does not mean it’s appropriate. It’s tempting to think that way—especially when you prioritise reusability—however on the web the way something <em>looks</em> is only part of the story.</p>
<p>A well-built component that was made to handle whatever is thrown at it will convey meaning and purpose at a lower-level than the visual (CSS) level, so that it is understandable in both non-visual and visual environments.</p>
<p>That’s why sometimes the existing component is not a good fit because the purpose of the new thing, and the user’s intent when using it, are different to that of the existing thing. And bloating the existing component to change or muddy its purpose is bad for maintainability and reusability.</p>
<p>I loved this nugget on shifting left during design:</p>
<blockquote>
<p>One of the things I’ve really pushed for in the most recent features is UX accessibility documentation during the design phase. What does that mean? Well, it means that when we are designing a new feature, we request that our UX designers and architects chat with our developers early and draft a basic semantic HTML structure and any specific accessibility behaviours. Think landmarks, headings, buttons, links, and careful focus management, to name a small selection.</p>
</blockquote>
<p>I did this recently when working on a <em>Data Table</em> component with <a href="https://twitter.com/zitafreeburn">Zita</a>. We found that early discovery of user intent allied to coding early semantic markup prototypes really informed our understanding of constraints, opportunities and architecture for the remainder of the process.</p>
<p>Additionally, this is great advice for comparing and choosing between components:</p>
<blockquote>
<p>Focus on what components achieve rather than their appearance</p>
</blockquote>
<p>To me this also highlights one of the key benefits of modern <a href="https://every-layout.dev/">micro-layouts</a>. Separate the content (and purpose) from the layout…then you get maximum reusability from those common, <em>workhorse</em> layouts because they are meaning-agnostic.</p>
Dragula - Browser drag-and-drop so simple it hurts2021-05-24T07:35:26Zhttps://fuzzylogic.me/posts/2021-05-24-dragula-browser-draganddrop-so-simple-it-hurts/<p>Here’s a nice, lightweight and framework-free drag and drop UI solution, that’s sure to come in handy.</p>
<blockquote>
<p>Drag and drop so simple it hurts</p>
</blockquote>
<p>(via <a href="https://twitter.com/mxbck">@mxbck</a>)</p>
Container Queries in Web Components | Max Böck2021-05-23T09:26:30Zhttps://fuzzylogic.me/posts/2021-05-23-container-queries-in-web-components-or-max-bock/<p>Max’s demo is really clever and features lots of interesting web component related techniques.</p>
<blockquote>
<p>I came up with this demo of a book store. Each of the books is draggable and can be moved to one of three sections, with varying available space. Depending on where it is placed, different styles will be applied to the book.</p>
</blockquote>
<p>Some of the techniques I found interesting included:</p>
<ul>
<li>starting with basic HTML for each book and its image, title, and author elements rather than an empty custom element, thereby providing a resilient baseline</li>
<li>wrapping each book in a custom <code>book-element</code> tag (which the browser would simply treat like a <code>div</code> in the worst case scenario)</li>
<li>applying the <code>slot</code> attribute to each of the nested elements, for example <code>slot="title"</code></li>
<li>including a <code>template</code> with <code>id="book-element"</code> at the top of the HTML. This centralises the optimal book markup, which makes for quicker, easier, and less disruptive maintenance. (A <code>template</code> is parsed but not rendered by the browser. It is available solely to be referenced and used by JavaScript)</li>
<li>including <em>slots</em> within the <code>template</code>, such as <code><slot name="title"></code></li>
<li>putting a <code>style</code> block within the <code>template</code>. These styles target the book component only, and include container query driven responsiveness</li>
<li>targetting the <code><book-element></code> wrapper element in CSS via the <code>:host</code> selector, and applying <code>contain</code> to set it as a container query context</li>
<li>targetting a <code>slot</code> in the component CSS using (for example) <code>::slotted(img)</code></li>
</ul>
<h2 id="thoughts" tabindex="-1">Thoughts <a class="direct-link" href="https://fuzzylogic.me/posts/2021-05-23-container-queries-in-web-components-or-max-bock/#thoughts" aria-hidden="true">#</a></h2>
<p>Firstly, in the basic HTML/CSS, I might ensure images are <code>display: block</code> and use <code>div</code> rather than <code>span</code> for a better baseline appearance should JavaScript fail.</p>
<p>Secondly, even though this tutorial is really nice, I still find myself asking: why use a Web Component to render a book rather than a server-side solution when the latter removes the JS dependency? Part of the reason is no doubt developer convenience—people want to build component libraries in JavaScript if that’s their language of choice. Also, it requires less backend set-up and leads to a more portable stack. And back-end tools for component-based architectures are generally less mature and feature-rich then those for the front-end.</p>
<p>One Web Component specific benefit is that Shadow DOM provides an encapsulation mechanism to style, script, and HTML markup. This encapsulation provides private scope that both prevents the content of the component from being affected by the external document, and keeps its CSS and JS from leaking <em>out</em>… which might be nice for avoiding the namespacing you’d otherwise have to do.</p>
<p>I have a feeling that Web Components might make sense for some components but be neither appropriate nor required for others. Therefore just because you use Web Components doesn’t mean that you suddenly need to feel the need to write or refactor every component that way. It’s worth bearing in mind that client-side JavaScript based functionality comes with a performance cost—the user needs to wait for it to download. So I feel there might be a need to exercise some restraint. I want to think about this a little more.</p>
<h2 id="other-references" tabindex="-1">Other references <a class="direct-link" href="https://fuzzylogic.me/posts/2021-05-23-container-queries-in-web-components-or-max-bock/#other-references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots">Using Templates and Slots, on MDN</a></li>
</ul>
Ruthlessly eliminating layout shift on netlify.com, by Zach Leatherman2021-05-12T17:02:07Zhttps://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/<p>I love hearing about clever front-end solutions which combine technologies and achieve multiple goals. In Zach’s post we hear how Netlify’s website suffered from layout shift when conditionally rendering dismissible promo banners, and how he addressed this by rethinking the problem and shifting responsibilities around the stack.</p>
<p>Here’s my summary of the smart ideas covered in the post:</p>
<ul>
<li>decide on the appropriate server-rendered content… in this case showing rather than hiding the banner, making the most common use case faster to load</li>
<li>have the banner “dismiss” button’s event handling script store the banner’s <code>href</code> in the user’s localStorage as an identifier accessible on return visits</li>
<li>process lightweight but critical JavaScript logic <em>early</em> in the <code><head></code>… in this case a check for this banner’s identifier existing in localStorage</li>
<li>under certain conditions – in this case when the banner was previously seen and dismissed – set a “state” class (<code>banner--hide</code>) on the <code><html></code> element, leading to the component being hidden seamlessly by CSS</li>
<li>build the banner as a web component, the first layer of which being a custom element <code><announcement-banner></code> and the second a JavaScript class to enhance it</li>
<li>delegate responsibility for presenting the banner’s “dismiss” button to the same script responsible for the component’s enhancements, meaning that a broken button won’t be presented if that script were to break.</li>
</ul>
<p>So much to like in there!</p>
<p>Here are some further thoughts the article provoked.</p>
<h2 id="web-components-ftw" tabindex="-1">Web components FTW <a class="direct-link" href="https://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/#web-components-ftw" aria-hidden="true">#</a></h2>
<p>It feels like creating a component such as this one as a <em>web component</em> leads to a real convergence of benefits:</p>
<ul>
<li>tool-free, async loading of the component JS as an ES module</li>
<li>fast, native element discovery (no need for a <code>document.querySelector</code>)</li>
<li>enforces using a nice, idiomatic class providing encapsulation and high-performing native callbacks</li>
<li>resilience and progressive enhancement by putting all your JS-dependent stuff into the JS class and having that enhance your basic custom element. If that JS breaks, you still have the basic element and won’t present any broken elements.</li>
</ul>
<p>Even better, you end up with framework-independent, standards-based component that you could share with others for reuse elsewhere, just like Zach did.</p>
<h2 id="multiple-banners" tabindex="-1">Multiple banners <a class="direct-link" href="https://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/#multiple-banners" aria-hidden="true">#</a></h2>
<p>I could see there being a case where there are multiple banners during the same time period. I guess in that situation the localStorage <code>banner</code> value could be a stringified object rather than a simple, single-URL string.</p>
<h2 id="setting-context-on-the-root" tabindex="-1">Setting context on the root <a class="direct-link" href="https://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/#setting-context-on-the-root" aria-hidden="true">#</a></h2>
<p>It’s really handy to have a way to exert just-in-time control over the display of a server-rendered element in a way that avoids flashes of content… and adding a class to the <code><html></code> element offers that. In this approach, we run the small amount of JavaScript required to test a local condition (e.g. checking for a value in localStorage) <em>really early</em>. That lets us process our conditional logic before the element is rendered… although this also means that it’s not yet available in the DOM for direct manipulation. But adding a class to the HTML element means that we can pre-prepare CSS to use that class as a contextual selector for hiding the element.</p>
<p>We’re already familiar with the technique of placing classes on the root element from libraries like <a href="https://modernizr.com/">modernizr</a> and some font-loading approaches, but this article serves as a reminder that we can employ it whenever we need it.</p>
<h2 id="handling-the-close-button" tabindex="-1">Handling the close button <a class="direct-link" href="https://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/#handling-the-close-button" aria-hidden="true">#</a></h2>
<p>Zach’s approach to handling the banner’s dismiss button was interesting. He makes sure that it’s not shown unless the web component’s JavaScript runs successfully which is great, but rather than inject it with JavaScript he includes it in the initial HTML but hidden with CSS, and his method of hiding is <code>opacity</code>.</p>
<blockquote>
<p>We use opacity to toggle the close button so that it doesn’t reflow the component when it’s enabled via JavaScript.</p>
</blockquote>
<p>I think what Zach’s saying is that the alternatives – inserting the button with JS, or toggling the <code>hidden</code> attribute or its CSS counterpart <code>display:none</code> – would <a href="https://csstriggers.com/display">affect geometry causing the browser to perform layout</a>… whereas <a href="https://csstriggers.com/opacity">modifying opacity does not</a>.</p>
<p>I love that level of diligence! Typically I prefer to <a href="https://twitter.com/jaffathecake/status/1230388412806520833">delegate responsibility for inserting JS-dependent buttons to JavaScript</a> because in comparison to including a button in the server-rendered HTML then hiding it, it feels more resilient and a more maintainable separation of concerns. However as always the best solution depends on the situation.</p>
<p>If I were going down Zach’s route I think I’d replace <code>opacity</code> with <code>visibility</code> since the latter hiding method removes the hidden element from the document which feels more accessible, while still <a href="https://csstriggers.com/visibility">avoiding triggering the reflow</a> that <code>display</code> would.</p>
<h2 id="side-thoughts" tabindex="-1">Side-thoughts <a class="direct-link" href="https://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/#side-thoughts" aria-hidden="true">#</a></h2>
<p>In a server-side scripted application – one using Rails or PHP, for example – you could alternatively handle persisting state with <em>cookies</em> rather than localStorage… allowing you to test for the presence of the cookie on the <em>server</em> then handle conditional rendering of the banner on the server too, rather than needing classes which trigger hiding. I can see an argument for that. Thing is though, not everyone’s working in that environment. Zach has provided a standalone solution.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/ruthlessly-eliminating-layout-shift-on-netlify.com-by-zach-leatherman/#references" aria-hidden="true">#</a></h2>
<ul>
<li>Zach’s <a href="https://github.com/zachleat/herald-of-the-dog">Herald of the dog</a> web component</li>
<li><a href="https://csstriggers.com/">CSS Triggers</a> of reflow and repaint</li>
<li><a href="https://www.harrytheo.com/blog/2021/09/dom-reflow-and-layout-thrashing/">Minimising layout thrashing</a></li>
</ul>
One web component to rule them all? (on Filament Group, Inc.)2021-05-11T17:02:01Zhttps://fuzzylogic.me/posts/2021-05-11-one-web-component-to-rule-them-all-on-filament-group-inc/<p>Scott Jehl has taken a refreshingly Progressive Enhancement -centric look at Web Components.</p>
<blockquote>
<p>this pattern provides a nice hook for adding progressive enhancements to already-meaningful HTML contained in these custom elements, leaving them resilient in the case of of script loading failures and allowing the page to start rendering before the JS happens to run.</p>
</blockquote>
<p>He goes further and creates a <em>factory</em> for creating Web Components which allows adding to a single element many small behavioural script enhancements that may or may not relate to each other.</p>
<p>There are also some great notes on polyfilling and the performance upgrade provided by lifecycle callbacks.</p>
<p>And <a href="https://github.com/filamentgroup/wc-experiments">Scott’s wc-experiments repo</a> contains some interesting demos.</p>
Changes at Basecamp2021-05-02T14:50:08Zhttps://fuzzylogic.me/posts/2021-05-02-changes-at-basecamp/<p>Basecamp—makers of project management, team communication and email software—have taken a controversial new stance against (amongst other things) political discussion at work, “paternalistic benefits” and 360 performance reviews.</p>
<blockquote>
<p>These are difficult enough waters to navigate in life, but significantly more so at work. It's become too much. It's a major distraction. It saps our energy, and redirects our dialog towards dark places. It's not healthy, it hasn't served us well.</p>
</blockquote>
<p>On the surface I can see the appeal of “keeping it simple” in the modern workplace where so many different things vie for our attention. However the move to “silence conversation” feels out of step with a moment when—as a society—we’re trying hard to correct institutional, longstanding inequalities. Perhaps the channels where political/societal discourse can happen need better demarcated and the “house rules” properly set. But especially after the year we’ve just had it also feels wrong to take a dictatorial approach toward staff.</p>
<p>It seems that <a href="https://techcrunch.com/2021/04/30/basecamp-employees-quit-ceo-letter/">many departing employees feel the same way</a>.</p>
Changing visual order with CSS2021-04-27T08:21:10Zhttps://fuzzylogic.me/posts/dos-and-dont%E2%80%99s-of-changing-visual-order-with-css/<p>When considering using Flexbox or CSS Grid to change the visual order of elements, remember that “with great power comes great responsibility”.</p>
<p>Flexbox and CSS Grid have given us new powers to shuffle the visual order of elements on a web page such that it is different to the element order in the source code.</p>
<p>However many smart developers have rightly pointed out that although this is really convenient and can help in conquering gnarly design and responsive challenges, it’s often not a good idea. Rachel Andrew in particular has regularly offered the following advice:</p>
<blockquote>
<p>Don’t fix source problems with Grid or Flexbox.</p>
</blockquote>
<p>See Rachel’s talk <a href="https://noti.st/rachelandrew/Mny9Vg/grid-content-re-ordering-and-accessibility#sd6FiEH">Grid, content re-ordering and accessibility</a> for more detail.</p>
<p>So, what’s the problem?</p>
<p>Essentially we cause people problems when we create a disconnect between tabbing order and visual order.</p>
<p>Let’s dig into the detail.</p>
<h2 id="people-browse-web-pages-in-different-ways" tabindex="-1">People browse web pages in different ways <a class="direct-link" href="https://fuzzylogic.me/posts/dos-and-dont%E2%80%99s-of-changing-visual-order-with-css/#people-browse-web-pages-in-different-ways" aria-hidden="true">#</a></h2>
<p>We know that a web page’s visitors are likely to have a range of different abilities. While some experience the full extent of our visual design, others are visually-impaired or blind. Others still have motor impairments. The web was intended to be accessible and therefore web pages should cater appropriately to this range of user needs.</p>
<p>Relatedly we also know that people will use one or more of the following methods to move around a web page:</p>
<ul>
<li>a thumb and fingers;</li>
<li>a mouse (or trackpad) and keyboard;</li>
<li>a keyboard alone.</li>
</ul>
<p>There are probably other methods I’m forgetting, but those are the most common.</p>
<p>In order to cater to people who navigate a web page using a keyboard without a mouse (a.k.a. <em>keyboard users</em>), we must ensure that the page is tab-friendly. We want the page’s interactive elements to be navigable and focusable by pressing the <kbd>Tab</kbd> key. Those elements should be focusable one by one in the same order as they are defined in the HTML document.</p>
<p>Often, achieving tab-friendliness requires little or no additional development effort because the browser gives us so much of the necessary behaviour natively. Interactive HTML elements like anchors (links) and form controls are focusable by default. And for any custom interactions where we want to make a normally non-focusable element (such as a <code>div</code>) focusable (thus giving it a keyboard tab-stop) we can apply <a href="https://fuzzylogic.me/posts/using-the-tabindex-attribute/">the tabindex attribute</a>, setting its <code>tabindex="0"</code>.</p>
<p>A simple, well-formed web page will natively offer a natural and predictable tabbing order.</p>
<p>With CSS Grid and Flexbox we now have new CSS options such as <code>order</code>, <code>flex-direction: row-reverse</code> and <code>grid-auto-flow</code> which let us reorder elements on the page. This can be really handy for situations where a design spec calls for Element 1 to appear above Element 2 on narrow viewports but to its right on wider viewports. Using these new CSS properties we might let the elements follow the source order on narrow viewports but change their order within a media query for wider viewports.</p>
<p>However this means we are now messing with the natural order of things. And if we move <em>focusable</em> elements around such that their visual order is different from their source order this creates a disconnect between tabbing order and visual order.</p>
<p>The disconnect is unlikely to be apparent to sighted people on a tablet/phone or on a desktop setup and navigating with their mouse, because they are not using tab to navigate. Blind users using a screen reader will be similarly unaffected because they don’t experience the visual order.</p>
<p>We might assume that all keyboard (only) users are also blind, using a screen reader, and not perceiving visual order. However keyboard users also include sighted people who have trouble operating a pointing device such as a mouse or trackball, or whose mouse is currently not working, or who simply prefer to use a keyboard where possible.</p>
<p><strong>For the sighted person who navigates by keyboard our change of order would be confusing.</strong> When you use tab and expect that to follow convention and set focus on one element but it actually sets focus on another, you’ll likely assume that something is broken.</p>
<p>Rachel Andrew argues that <a href="https://rachelandrew.co.uk/archives/2019/06/04/grid-content-re-ordering-and-accessibility/">creating this kind of disconnect is to be avoided</a>. Léonie Watson suggests that in simple examples such a disconnect may only be mildly awkward, however in complex interfaces <a href="https://tink.uk/flexbox-the-keyboard-navigation-disconnect/">it could make things horribly unusable</a>.</p>
<h2 id="is-it-ever-ok-to-change-visual-order-with-css%3F" tabindex="-1">Is it ever OK to change visual order with CSS? <a class="direct-link" href="https://fuzzylogic.me/posts/dos-and-dont%E2%80%99s-of-changing-visual-order-with-css/#is-it-ever-ok-to-change-visual-order-with-css%3F" aria-hidden="true">#</a></h2>
<p>At work I recently reviewed a PR where the visual order of a Flexbox layout was being updated via <code>order: -1</code> in a media query for wide viewports. Although it was a really elegant solution on paper, I advised caution in light of the pitfalls mentioned above.</p>
<p>However a colleague rightly pointed out that the elements being reordered were two <code>div</code>s. In this case and any others where the elements (and their children) are non-focusable and we’re not messing with the likes of navigation links or form elements, I <em>think</em> we are safe.</p>
<h2 id="the-future" tabindex="-1">The Future <a class="direct-link" href="https://fuzzylogic.me/posts/dos-and-dont%E2%80%99s-of-changing-visual-order-with-css/#the-future" aria-hidden="true">#</a></h2>
<p>We’ve recently been given a few new CSS layout powers only to subsequently be <a href="https://fuzzylogic.me/posts/using-css-display-contents-to-snap-grandchild-elements-to-a-grid/">advised not to use them</a>.</p>
<p>How do we move forward?</p>
<p>Rachel Andrew argues that this problem needs addressed at a CSS level; that developers should be able to set the tab and reading order to follow the visual rather than source order under certain circumstances.</p>
<p>Until that becomes a CSS reality we should continue to be judicious in our usage to ensure we don’t break user expectations. We can also use tools like the Source Order Viewer in Chrome DevTools (DevTools > Elements > Accessibility) to check our work.</p>
SVG Crop2021-04-24T19:03:16Zhttps://fuzzylogic.me/posts/2021-04-24-svg-crop/<p>Here’s a handy-looking tool for the SVG editing toolkit.</p>
<blockquote>
<p>Remove blank space from around any SVG instantly.</p>
</blockquote>
<p>(via <a href="https://twitter.com/chriscoyier">@chriscoyier</a>)</p>
Note 2021-4-20T13:00:50: Ted Chiang – Exhalation2021-04-20T15:40:00Zhttps://fuzzylogic.me/posts/note-2021-4-20t13-00-50-ted-chiang-%E2%80%93-exhalation/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781529014495">Exhalation</a> by Ted Chiang.</p>
Swipey image grids (on cassie.codes)2021-04-18T09:46:45Zhttps://fuzzylogic.me/posts/2021-04-18-swipey-image-grids-on-cassiecodes/<p>A lovely post by Cassie Evans in which she demonstrates that SVG is not just for icons and illustrations. You might also reach for it to create a responsive, animated grid of images.</p>
<blockquote>
<p>we have another grid at our disposal. SVG has its own internal coordinate system and it's responsive by design.</p>
</blockquote>
<p>There are lots of interesting techniques in here such as:</p>
<ul>
<li>layering an <code><image></code> on top of a shape such as a <code><rect></code>;</li>
<li>using <code>preserveAspectRatio</code> to make the image fully cover and <em>fit</em> the shape when their aspect ratios differ;</li>
<li>using <code><clipPath></code> as a custom-shaped window to an image (for example a <code><circle></code>);</li>
<li>giving the <code><clipPath></code>’s nested shape a solid <code>fill</code> to <em>hide</em> the <code><image></code> to which it’s applied;</li>
<li>animating a rectangular <code><clipPath></code> applied to an image to give the effect of the image “sliding into view”; and</li>
<li>using Greensock to make sequencing multiple animations easy and to ensure they work consistently across browsers.</li>
</ul>
<p>However I also loved this simple piece of practical advice to help picture the SVG’s <code>viewbox</code> and plot shapes on top:</p>
<blockquote>
<p>I usually get a pen and paper out at this point and doodle it out.</p>
</blockquote>
Observer APIs in a nutshell2021-04-17T12:39:22Zhttps://fuzzylogic.me/posts/observer-apis-in-a-nutshell/<p>I’ve played with the various HTML5 Observer APIs (<code>IntersectionObserver</code>, <code>ResizeObserver</code> and <code>MutationObserver</code>) a little over the last few years—for example using <code>ResizeObserver</code> in a container query solution for responsive grids. But in all honesty their roles, abilities and differences haven’t yet fully <em>stuck</em> in my brain. So I’ve put together a brief explainer for future reference.</p>
<h2 id="intersection-observer" tabindex="-1">Intersection Observer <a class="direct-link" href="https://fuzzylogic.me/posts/observer-apis-in-a-nutshell/#intersection-observer" aria-hidden="true">#</a></h2>
<p>Lets you watch for when an element of your choice intersects with a root element of your choice—typically the viewport—and then take action in response.</p>
<p>So you might watch for a <code>div</code> that’s way down the page entering the viewport as a result of the user scrolling, then act upon that by applying a class which animates that <code>div</code>’s opacity from <code>0</code> to <code>1</code> to make it fade in.</p>
<p>Here’s how it works:</p>
<ul>
<li>Instantiate a new <code>IntersectionObserver</code> object, passing in firstly a callback function and secondly an options array which specifies your root element (usually the viewport, or a specific subsection of it).</li>
<li>Call <code>observe</code> on your instance, passing in the element you want to watch. If you have multiple elements to watch, you could call <code>observe</code> repeatedly in a loop through the relevant <code>NodeList</code>.</li>
<li>in the callback function add the stuff you want to happen in response to “intersecting” and “no longer intersecting” events.</li>
</ul>
<h2 id="mutation-observer" tabindex="-1">Mutation Observer <a class="direct-link" href="https://fuzzylogic.me/posts/observer-apis-in-a-nutshell/#mutation-observer" aria-hidden="true">#</a></h2>
<p>Lets you watch for changes to the attributes or content of DOM elements then take action in response.</p>
<p>You might use this if you have code that you want to run if and when an element changes because of another script.</p>
<p>Here’s how it works:</p>
<ul>
<li>Your typical starting point is that you already have one or more event listeners which modify the DOM in response to an event.</li>
<li>Instantiate a new <code>MutationObserver</code> object, passing in a callback function.</li>
<li>The callback function will be called every time the DOM is changed.</li>
<li>Call <code>observe</code> on your instance, passing in as first argument the element to watch and as second argument a config object specifying what type of changes you’re interested in, for example you might only care about changes to specific attributes.</li>
<li>your callback function provides an array of <em>MutationRecord</em> objects—one for each change that has just taken place—which you can loop through and act upon.</li>
</ul>
<h2 id="resize-observer" tabindex="-1">Resize Observer <a class="direct-link" href="https://fuzzylogic.me/posts/observer-apis-in-a-nutshell/#resize-observer" aria-hidden="true">#</a></h2>
<p>Lets you watch for an element meeting a given size threshold then take action in response.</p>
<p>For example you might add a class of <code>wide</code> to a given container only when it is wider than <code>60em</code> so that new styles are applied. This is a way of providing <em>container query</em> capability while we wait for that to land in CSS.</p>
<p>Or you might load additional, heavier-weight media in response to a certain width threshold because you feel you can assume a device type that indicates the user is on wifi. Adding <em>functionality</em> rather than applying styles is something we could not achieve with CSS alone.</p>
<!--
One question I find myself asking is whether this is only for watching for _changes_ to an element’s size?
something I wouldn’t imagine happens too often unless the user resizes their browser
…or reorients their phone or iPad which is more likely!
—or whether it’s also for checking the element’s _initial_ size? Well, …
Here’s how it works:
- …
- …
At the moment it feels to me like `ResizeObserver` is only useful for mimicking container queries. I’ve done this once or twice in the past but as at April 2021 I’m no longer sure it’s something I need _so_ much (and can’t wait for) to the extent that I’ll keep reaching for JavaScript to achieve it. Perhaps other practical uses for this API may become apparent to me over time.
-->
<p>Given that Container Query support is coming in CSS and that we can usually get by without it in the meantime, I don’t think it’s something I need <em>so</em> desperately that I’ll keep reaching for JavaScript to achieve it. However that’s not the only use for <code>ResizeObserver</code>.</p>
<p>It’s also worth remembering that it’s not all about <em>width</em>: <code>ResizeObserver</code> can also be used to detect and respond to changes to an element’s <em>height</em>. An example might be <a href="https://web.dev/resize-observer/#application">watching for changes to a chat window’s height</a>—something that’s liable to happen as new messages appear—and then ensuring the focus stays at the bottom, on the latest message.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/observer-apis-in-a-nutshell/#references" aria-hidden="true">#</a></h2>
<p>Steve Griffiths has some great video tutorials on these topics.</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=gQ8WggeHoJU&t=0s">Intersection Observer</a></li>
<li><a href="https://www.youtube.com/watch?v=gQ8WggeHoJU&t=0s">Mutation Observer</a></li>
<li><a href="https://www.youtube.com/watch?v=gQ8WggeHoJU&t=0s">Intersection Observer</a></li>
</ul>
Design-ish systems (by Ethan Marcotte)2021-04-09T08:07:23Zhttps://fuzzylogic.me/posts/2021-04-09-designish-systems-by-ethan-marcotte/<p>Here’s an interesting new article from Ethan Marcotte, in which he muses on better ways to think about Design Systems based on his recent experience.</p>
<blockquote>
<p>Once you’ve identified the root causes, you’ll be in a far, far better place to choose the right things — and, more importantly, to create a system that finally supports your design.</p>
</blockquote>
<p>Here’s what I took from it:</p>
<p>We can consider the difference between <em>things</em>, <em>issues</em> and <em>broader goals</em>.</p>
<p>It’s easy to focus on the <em>things</em> (design tokens, choice of design tool, programming language).</p>
<p>But things are just elements of the system; they don’t <em>solve</em> design systems.</p>
<p>Focusing too much or too early on the <em>things</em> leads to a tendency to <em>patch</em> problems.</p>
<p>Whereas discussing the current wider organisational issues we need to address leads to defining broader goals.</p>
<p>This in turn helps us choose and focus on the <em>right things</em> for the right reasons.</p>
Diffchecker - Online diff tool2021-04-05T17:26:54Zhttps://fuzzylogic.me/posts/2021-04-05-diffchecker-online-diff-tool-to-compare-text-to-find-the-difference-between-two-text-files/<blockquote>
<p>Diffchecker is a diff tool to compare text differences between two text files.</p>
</blockquote>
<p>I had cause to use this free diff tool recently to compare two large minified CSS files and it did the trick better than any others I’ve tried. Thumbs up!</p>
Building a resilient frontend using progressive enhancement (on GOV.UK)2021-04-05T12:06:45Zhttps://fuzzylogic.me/posts/2021-04-05-building-a-resilient-frontend-using-progressive-enhancement-service-manual-govuk/<p><a href="http://gov.uk/">GOV.UK</a>’s guidance on developing using progressive enhancement is pretty great in all departments. It begins with this solid advice:</p>
<blockquote>
<p>you should start by making your page work with just HTML, before adding anything else like Cascading Style Sheets (CSS) and JavaScript. This is because HTML is the most resilient layer. If the HTML fails there’s no web page. Should the CSS or JavaScript fail, the HTML will still render correctly.</p>
</blockquote>
<p>I particularly like the section where they address the misconception that a resilient baseline is only required in places where the user has explicitly disabled JavaScript and therefore not worth worrying about.</p>
<blockquote>
<p>You should not assume the reason for designing a service that works without CSS or JavaScript is because a user chooses to switch these off. There are many situations when extra layers can fail to load or are filtered.</p>
</blockquote>
<p>As their subsequent list of scenarios illustrates, a user turning JavaScript off is probably the least likely of a range of reasons why extra layers on top of HTML can fail.</p>
<p>Relatedly, I’ve often found that <a href="https://kryogenix.org/code/browser/everyonehasjs.html">Everyone has JavaScript, right?</a> serves as a great go-to reference for these sorts of conversations around resilience.</p>
Note 2021-4-01T13:00:50: Blake Crouch – Recursion2021-04-01T20:21:05Zhttps://fuzzylogic.me/posts/note-2021-4-01t13-00-50-blake-crouch-%E2%80%93-recursion/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781509866670">Recursion</a> by Blake Crouch.</p>
Encapsulated Eleventy/Nunjucks components with macros (by Trys Mudford)2021-03-22T20:49:00Zhttps://fuzzylogic.me/posts/2021-03-22-encapsulated-eleventynunjucks-components-with-macros-by-trys-mudford/<p>Trys shows us how to use the Nunjucks <code>macro</code> to create encapsulated components. This works out less leaky and more predictable than an <code>include</code> preceded by variables assigned with <code>set</code>.</p>
<p>Trys’s solution allows us to render components like so:</p>
<figure>
<pre class="language-twig"><code class="language-twig"><span class="token twig language-twig"><span class="token delimiter punctuation">{{</span> component<span class="token punctuation">(</span><span class="token string"><span class="token punctuation">'</span>button<span class="token punctuation">'</span></span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> text<span class="token punctuation">:</span> <span class="token string"><span class="token punctuation">'</span>Press me<span class="token punctuation">'</span></span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token delimiter punctuation">}}</span></span><br /><br /><span class="token twig language-twig"><span class="token comment">{# Output #}</span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Press me<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p><strong>Update, 8th Aug 2021</strong>: when I tried implementing this I found that it results in errors when attempting to render components anywhere other than on the base template where Trys recommended including the <code>import</code> line. The workaround—as <a href="https://github.com/trys/11ty-component-macro/issues/1">Paul Salaets points out</a>—is to include the <code>import</code> at the top of every page-level template (<code>index.njk</code>, <code>archive.njk</code> etc) that uses the component macro.</p>
In Praise of the Unambiguous Click Menu (on CSS-Tricks)2021-03-19T11:51:33Zhttps://fuzzylogic.me/posts/2021-03-19-in-praise-of-the-unambiguous-click-menu-on-csstricks/<p>Mark Root-Wiley explains why navigation menus that appear on click rather than hover are better.</p>
<p>I like the fact that it calls out that:</p>
<blockquote>
<p>When you first make this change, it’s true that some visitors might still expect hover menus. They may even say they prefer them if you ask.</p>
</blockquote>
<p>But then goes on to provide some rationale (ammunition?) from various big guns on why click menus are better.</p>
<p>From the US Web Design System:</p>
<blockquote>
<p>Avoid using hover to expand dropdown lists. Hover is difficult for some users and won’t work on touch screens. Dropdowns should expand on click or with keyboard navigation.</p>
</blockquote>
<p>From popular frontend framework <a href="https://getbootstrap.com/docs/3.4/">Bootstrap</a>:</p>
<blockquote>
<p>What it really boils down to is user intent. The purpose of a hover state is to indicate something is clickable (underlined text). The purpose of a click is to actually do something, to take an explicit action. Opening a dropdown is an explicit action and should only happen on click.</p>
</blockquote>
<p>(via <a href="https://twitter.com/jamesmockett">@jamesmockett</a>)</p>
How to Favicon in 2021 (on CSS-Tricks)2021-03-17T10:33:03Zhttps://fuzzylogic.me/posts/2021-03-17-how-to-favicon-in-2021-on-csstricks/<p>Some excellent favicon tips from Chris Coyier, referencing <a href="https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs">Andrey Sitnik’s recent article</a> of the same name.</p>
<blockquote>
<p>I always appreciate someone looking into and re-evaluating the best practices of something that literally every website needs and has a complex set of requirements.</p>
</blockquote>
<p>Chris is using:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>icon<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/favicon.ico<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!-- 32x32 --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>icon<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/icon.svg<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>apple-touch-icon<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/apple-touch-icon.png<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!-- 180x180 --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>manifest<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/manifest.webmanifest<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>And in <code>manifest.webmanifest</code>:</p>
<figure>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"icons"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">{</span> <span class="token property">"src"</span><span class="token operator">:</span> <span class="token string">"/192.png"</span><span class="token punctuation">,</span> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"image/png"</span><span class="token punctuation">,</span> <span class="token property">"sizes"</span><span class="token operator">:</span> <span class="token string">"192x192"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span> <span class="token property">"src"</span><span class="token operator">:</span> <span class="token string">"/512.png"</span><span class="token punctuation">,</span> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"image/png"</span><span class="token punctuation">,</span> <span class="token property">"sizes"</span><span class="token operator">:</span> <span class="token string">"512x512"</span> <span class="token punctuation">}</span><br /> <span class="token punctuation">]</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>(via <a href="https://twitter.com/mxbck">@mxbck</a>)</p>
How I subset web fonts2021-03-07T11:14:27Zhttps://fuzzylogic.me/posts/how-i-subset-web-fonts/<p>On <a href="https://fuzzylogic.me/">my personal website</a> I currently use three web fonts from the <em>Source Sans 3</em> group: regular, italic and semibold. I self-host my fonts because <a href="https://csswizardry.com/2019/05/self-host-your-static-assets/">that’s a good practice</a>. Additionally I use a variety of special characters to add some typographic life to the text.</p>
<p>When self-hosting it’s important from a performance perspective to minimise the weight of the font files your visitors must download. To achieve this I subset my fonts so as to include only the characters my pages use but no more. Here’s how I do it.</p>
<p>Note: to follow these steps, you’ll need to install <a href="https://github.com/filamentgroup/glyphhanger">glyphhanger</a>. The Github page includes installation and usage guidelines however there are a few common installation pitfalls so if you’re on a Mac and run into trouble I recommend checking Sara Soueidan’s <a href="https://www.sarasoueidan.com/blog/glyphhanger/"><em>How I set up Glyphhanger on macOS</em></a> to get you back on track.</p>
<p>For the purposes of this walkthrough I’ll assume you have a directory in your application named <code>fonts</code>.</p>
<p>Start by deleting any existing custom font files from your application’s <code>fonts</code> directory.</p>
<p>Run your site locally in an incognito browser window. For my Eleventy-based site, I run <code>npm run serve</code> which serves the site at <code>http://localhost:8080</code>.</p>
<p>Visually check your locally-running site to ensure that now you’ve deleted your web fonts it’s no longer serving them and is instead rendering text using system fonts.</p>
<p>Visit the source page for your custom fonts—in my case <a href="https://github.com/adobe-fonts/source-sans">the Github repository for Source Sans 3</a>. Download in <code>.ttf</code> format the latest versions of the fonts you need and place them in your <code>fonts</code> directory. For me these are:</p>
<ul>
<li>Regular,</li>
<li>Italic; and</li>
<li>Semibold.</li>
</ul>
<p>You’ll notice the large file sizes of these <code>.ttf</code> files. For example Source Sans 3’s <code>Regular.ttf</code> font is 299 kb.</p>
<p>At the command line, <code>cd</code> into your <code>fonts</code> directory.</p>
<p>Now we’re going to run glyphhanger on one font at a time. This fantastic tool will intelligenty crawl your website to check which glyphs are currently in use for the specified weight then include those in a subset file which it outputs in <code>.ttf</code>, <code>.woff</code> and <code>.woff2</code> formats. I use glyphhanger’s <code>spider</code> option so that it spiders multiple pages (rather than just one) at a time, meaning that it is more likely to catch all the special characters I’m using.</p>
<figure>
<pre class="language-bash"><code class="language-bash">glyphhanger http://localhost:8080/posts/ --subset<span class="token operator">=</span>SourceSans3-Regular.ttf --spider-limit<span class="token operator">=</span><span class="token number">0</span></code></pre>
</figure>
<p>If all went well you should see output like this:</p>
<figure>
<pre class="language-bash"><code class="language-bash">U+20-23,U+25-2A,U+2C-5B,U+5D,U+5F,U+61-7D,U+A9,U+B7,U+BB,U+D7,U+E9,U+F6,U+200B,U+200E,U+2013,U+2014,U+2018,U+2019,U+201C,U+201D,U+2026,U+2122,U+2190,U+2192,U+2615,U+FE0F<br />Subsetting SourceSans3-Regular.ttf to SourceSans3-Regular-subset.ttf <span class="token punctuation">(</span>was <span class="token number">292.24</span> KB, now <span class="token number">46.99</span> KB<span class="token punctuation">)</span><br />Subsetting SourceSans3-Regular.ttf to SourceSans3-Regular-subset.zopfli.woff <span class="token punctuation">(</span>was <span class="token number">292.24</span> KB, now <span class="token number">22.14</span> KB<span class="token punctuation">)</span><br />Subsetting SourceSans3-Regular.ttf to SourceSans3-Regular-subset.woff2 <span class="token punctuation">(</span>was <span class="token number">292.24</span> KB, now <span class="token number">17.77</span> KB<span class="token punctuation">)</span></code></pre>
</figure>
<p>The <code>.woff2</code> subset file has reduced the file size from 299 kb to 17.77 kb which is pretty impressive!</p>
<p>Update your CSS to point at the new <code>woff2</code> and <code>woff</code> subset files for your font. My updated CSS looks like this:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@font-face</span></span> <span class="token punctuation">{</span><br /> <span class="token property">font-family</span><span class="token punctuation">:</span> Source Sans Pro<span class="token punctuation">;</span><br /> <span class="token property">src</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>/fonts/sans/SourceSans3-Regular-subset.woff2<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff2"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>/fonts/sans/SourceSans3-Regular-subset.zopfli.woff<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">font-weight</span><span class="token punctuation">:</span> 400<span class="token punctuation">;</span><br /> <span class="token property">font-display</span><span class="token punctuation">:</span> swap<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Check your locally running application to ensure that the relevant text (body copy in this case) is now being served using the web font rather than fallback font, and that special characters are also being served using the web font.</p>
<p>I’ll usually crack open the Fonts panel in Firefox’s DevTools and check that, amongst other things, my pagination links which use the rightward pointing arrow character (→ or unicode <code>U+2192</code>) are rendering it using Source Sans Pro and not sticking out like a sore thumb by using Helvetica due to the glyph not being present in the subset.</p>
<p>Delete the <code>.ttf</code> file you started with and any <code>.ttf</code> subsets generated, because you won’t serve files in that format to your website visitors.</p>
<p>Repeat the glyphhanger subsetting and CSS updating process for any other weights (italic, semibold) or custom fonts you want to subset.</p>
<p>One last handy tip: if there’s a weight for which I don’t need a fancy character set (for example the Semibold I use for headings), I might just grab default <em>latin</em> charset <code>woff</code> and <code>woff2</code> files from the <a href="https://google-webfonts-helper.herokuapp.com/fonts/source-sans-pro">Google Webfonts Helper</a>. The files tend to be small and well-optimised and this can save a little time. (This is only possible if the font is available from Google Fonts which is true in the case of <em>Source Sans 3</em>.)</p>
Note 2021-3-01T13:00:50: The Rise of the Ultra Runners, by Adharanand Finn2021-03-01T21:26:27Zhttps://fuzzylogic.me/posts/note-2021-3-01t13-00-50-the-rise-of-the-ultra-runners-by-adharanand-finn/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781783351336">The Rise of the Ultra Runners</a>, by Adharanand Finn.</p>
Images on the Web: The Big Picture, Part 12021-02-28T11:30:00Zhttps://fuzzylogic.me/posts/images-on-the-web-the-big-picture/<p>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.</p>
<h2 id="scope" tabindex="-1">Scope <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#scope" aria-hidden="true">#</a></h2>
<p>This article is primarily about the HTML <code>img</code> element (and related markup). I might mention CSS background images at some point, but by and large I’m focusing on images as <em>content</em> rather than decoration.</p>
<p>Similarly I probably won’t mention <em>icons</em> at all. I see them as a separate concern and recommend you use inline SVG rather than any image-based approach.</p>
<h2 id="terminology" tabindex="-1">Terminology <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#terminology" aria-hidden="true">#</a></h2>
<h3 id="replaced-element" tabindex="-1">Replaced element <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#replaced-element" aria-hidden="true">#</a></h3>
<p>The image element is a replaced element which means that the element is replaced by the resource (file) referenced in its <code>src</code> attribute.</p>
<h3 id="aspect-ratio" tabindex="-1">Aspect Ratio <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#aspect-ratio" aria-hidden="true">#</a></h3>
<p>You get an image’s aspect ratio by dividing its width by its height.</p>
<p>A 160px wide × 90px tall image can be represented as 16:9, or 1.777.</p>
<p>Aspect Ratio is an <em>intrinsic</em> characteristic of an image—i.e. it is “part of the image”—therefore outside of our control as developers. We can apply <em>extrinsic</em> 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.</p>
<h2 id="assumptions" tabindex="-1">Assumptions <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#assumptions" aria-hidden="true">#</a></h2>
<p>CSS-wise, assume that we’ll start with nothing more complex than the following boilerplate:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">html</span> <span class="token punctuation">{</span><br /> <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">*, *:before, *:after</span> <span class="token punctuation">{</span><br /> <span class="token property">box-sizing</span><span class="token punctuation">:</span> inherit<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">img</span> <span class="token punctuation">{</span><br /> <span class="token property">border-style</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<h2 id="a-basic-image" tabindex="-1">A basic image <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#a-basic-image" aria-hidden="true">#</a></h2>
<p>Let’s start by going back to basics. I can include an image on a web page like so:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/img/250x377.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>A Visit… by Jennifer Egan<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
</figure>
<p>Note that our markup contains no <code>width</code> or <code>height</code> attributes, just an <code>alt</code> 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:</p>
<img src="https://images-eu.bookshop.org/product-images/images/9781780330969.jpg?width=250" alt="“A Visit from the Goon Squad“ by Jennifer Egan" />
<p>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.</p>
<p>However I still occasionally encounter use cases for displaying a relatively narrow image <em>as-is</em>.</p>
<p>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.</p>
<p>See also <a href="https://railstutorial.org/book/toy_app#sec-modeling_demo_microposts">this figure illustrating a simple database schema</a> on the <em>Ruby on Rails Tutorial</em> 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.</p>
<p>In summary, there remain times when you might need a narrow, fixed-size image so I want to keep that option open.</p>
<h2 id="include-size-attributes" tabindex="-1">Include size attributes <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#include-size-attributes" aria-hidden="true">#</a></h2>
<p>When we know the dimensions of our image in advance, we can improve upon our previous markup by explicitly adding the <code>width</code> and <code>height</code> attributes.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/img/250x377.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>250<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>377<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
</figure>
<p>Don’t expect fireworks; this renders the image exactly as before.</p>
<img width="250" height="377" src="https://images-eu.bookshop.org/product-images/images/9781780330969.jpg?width=250" alt="“A Visit from the Goon Squad“ by Jennifer Egan" />
<p>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 <em>shift</em> jarringly after the image loads.</p>
<p>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.</p>
<h2 id="flexible-images" tabindex="-1">Flexible Images <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#flexible-images" aria-hidden="true">#</a></h2>
<p>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.</p>
<p>RWD proposed making layout and content <em>adaptable</em>. This included the idea of <em>flexible images</em>—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.</p>
<p>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 <em>tolerance</em> 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 <code>max-width</code>.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/img/wide.png<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>…<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
<pre class="language-css"><code class="language-css"><span class="token selector">img</span> <span class="token punctuation">{</span><br /> <span class="token property">max-width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>The eagle-eyed will have noticed that the above snippet once again excludes the HTML <code>width</code> and <code>height</code> 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.</p>
<p>Regardless, some content management systems (most notably Wordpress) continued to output images with HTML <code>width</code> and <code>height</code> attributes as standard. This introduced a challenge. Without the attributes we could rely on the browser to take our simple <code>max-width:100%</code> declaration and also implicitly apply <code>height:auto</code> thereby always preserving the image‘s aspect ratio when scaling it down. To achieve the same goal when the HTML <code>height</code> attribute is present, we needed the following revised CSS:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">img</span> <span class="token punctuation">{</span><br /> <span class="token property">max-width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Here’s an example of a flexible image. It’s 2000 pixels wide, but shrinks to fit inside its narrower parent. Magic!</p>
<img src="https://via.placeholder.com/2000x1500.png/000" />
<h2 id="jank-free-responsive-images" tabindex="-1">Jank-free responsive images <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#jank-free-responsive-images" aria-hidden="true">#</a></h2>
<p>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).</p>
<p>This means that adding the <code>width</code> and <code>height</code> attributes is once again a good idea.</p>
<p>If you know the image’s aspect ratio in advance, you can now use any combination of <code>width</code> and <code>height</code> 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.</p>
<p>However this presents a couple of challenges.</p>
<p>Firstly, having the <code>height</code> HTML attribute once again means that for any image we want flexibly scaled and safely constrained by CSS <code>max-width</code>, we’ll also need to override that explicit height attribute value with CSS.</p>
<p>Secondly, having the <code>width</code> 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 <code>width</code> attribute value is less than the containing element’s current width. If the only CSS you have on your image is <code>max-width:100%</code> then the image will adopt the value from its <code>width</code> attribute and consequently be narrower than its parent, ruining the effect. One approach might be to always use a sufficiently high <code>width</code> value but that feels a tad brittle; I’d rather employ a solution that is more explicit and decisive.</p>
<p>To solve both of the above challenges, we can apply some additional CSS.</p>
<figure>
<pre class="language-css"><code class="language-css"> <span class="token comment">/*<br /> Ensure correct aspect ratio is preserved when<br /> max-width: 100% is triggered and image<br /> has the HTML height attribute set,<br /> while doing no harm otherwise.<br /> */</span><br /><span class="token selector">img[height]</span> <span class="token punctuation">{</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /> <span class="token comment">/*<br /> Optional class to make an image 100% container-width.<br /> Overrides the 'width' attribute, avoiding the risk of the image<br /> being too narrow because its width value is narrower than the container.<br /> When using this try to ensure your image’s intrinsic width is at least as<br /> wide as its container’s maximum width because otherwise on wide<br /> viewports the image would stretch and the results might not be great.<br /> */</span><br /><span class="token selector">.u-full-parent-width</span> <span class="token punctuation">{</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<h2 id="pros-and-cons-of-the-%E2%80%9Cone-large-image%E2%80%9D-approach" tabindex="-1">Pros and cons of the “one large image” approach <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#pros-and-cons-of-the-%E2%80%9Cone-large-image%E2%80%9D-approach" aria-hidden="true">#</a></h2>
<p>I’d like to quickly take stock.</p>
<p>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.</p>
<p>If we make the image flexible using <code>max-width:100%</code>, it’ll work on wide viewports and narrow viewports (such as a mobile phone) alike.</p>
<p>On the plus-side, we only need to create one image for our blog post and we’re done.</p>
<p>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.</p>
<p>On the downside, we are delivering a <em>much</em> 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).</p>
<p>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?</p>
<p>Dealing with these challenges using modern <em>Responsive Images</em> will be the subject of Part #2.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/images-on-the-web-the-big-picture/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://alistapart.com/article/responsive-web-design/">Ethan Marcotte: Responsive Web Design</a></li>
<li><a href="https://www.youtube.com/watch?v=4-d_SoCHeWE&feature=youtu.be">Jen Simmons: Do this to improve image loading</a></li>
<li><a href="https://every-layout.dev/layouts/frame/">Every Layout’s <em>Frame</em></a></li>
<li><a href="https://www.zachleat.com/web/fluid-images/">Zach Leatherman—Barebones CSS for Fluid Images</a></li>
</ul>
Front-of-the-front-end and back-of-the-front-end web development (by Brad Frost)2021-02-19T13:11:56Zhttps://fuzzylogic.me/posts/2021-02-19-frontofthefrontend-and-backofthefrontend-web-development-by-brad-frost/<p><a href="https://css-tricks.com/the-great-divide/">The Great Divide</a> between so-called front-end developers is real! Here, Brad Frost proposes some modern role definitions.</p>
<blockquote>
<p>A front-of-the-front-end developer is a web developer who specializes in writing HTML, CSS, and presentational JavaScript code.</p>
</blockquote>
<blockquote>
<p>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.</p>
</blockquote>
<p>Brad also offers:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>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 <em>sort-of</em> 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).</p>
<p>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.</p>
Making sense of atomic design: molecules and organisms (on Future Learn)2021-02-11T19:11:43Zhttps://fuzzylogic.me/posts/2021-02-11-making-sense-of-atomic-design-molecules-and-organisms-on-future-learn/<p>From 2015: Alla Kholmatova reflects on the difficulty in choosing between <em>molecule</em> or <em>organism</em> when categorising components using atomic design at FutureLearn. She also provides some handy insights into how they handled it.</p>
<blockquote>
<p>When thinking about complexity of elements, it helps viewing molecules as “helpers” and organisms as “standalone” modules.</p>
</blockquote>
<p>Whereas <em>helpers</em> can’t really exist on their own, <em>standalone</em> modules can.</p>
<p>Alla also recommends than in cases where an element doesn’t clearly fall into either group, asking the following questions may help:</p>
<ul>
<li>Is this <em>more</em> of a supporting element or a standalone one?</li>
<li>Would it normally be part of something else and be reused within various components? (if so it’s probably a molecule)</li>
<li>Is it a well defined and relatively independent part or section of a page? (if so it’s probably an organism)</li>
</ul>
<p>(via <a href="https://twitter.com/jamesmockett">@jamesmockett</a>)</p>
Guest mix for Multiverse Sessions, December 2020 by Tom Churchill2021-02-09T15:10:53Zhttps://fuzzylogic.me/posts/2021-02-09-guest-mix-for-multiverse-sessions-december-2020-by-tom-churchill/<blockquote>
<p>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.</p>
</blockquote>
<p>Lovely mix of mellow electro and techno vibes by my friend <a href="https://www.tomchurchill.com/">Tom</a>.</p>
Issues with Source Code Pro in Firefox appear to be fixed2021-02-06T14:46:36Zhttps://fuzzylogic.me/posts/issues-with-source-code-pro-in-firefox-appear-to-be-fixed/<p>Last time I tried <a href="https://github.com/adobe-fonts/source-code-pro">Source Code Pro</a> 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.</p>
<p>It now looks like I can try Source Code Pro again because <a href="https://github.com/adobe-fonts/source-code-pro/issues/250#issuecomment-728646917">the issue has been resolved</a>. This is great news!</p>
<p>So, I should grab <a href="https://github.com/adobe-fonts/source-code-pro/releases/latest">the latest release</a> and give it another go. Actually, for optimum subsetting and performance I reckon in this case I can just download the default files from <a href="https://google-webfonts-helper.herokuapp.com/fonts/source-code-pro?subsets=latin">Source Code Pro on Google Webfonts Helper</a> and that’ll give me the lightweight <code>woff2</code> file I need.</p>
<p>I’d also mentioned the other day that I was planning to <a href="https://fuzzylogic.me/posts/2021-01-31-source-serif-4/">give Source Serif another bash</a> so if everything works out, with these two allied to my existing Source Sans Pro I could have a nice complimentary set.</p>
Design system components, recipes, and snowflakes (on bradfrost.com)2021-02-05T11:18:03Zhttps://fuzzylogic.me/posts/2021-02-05-design-system-components-recipes-and-snowflakes-on-bradfrostcom/<p>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.</p>
<p>In light of some recent conversations at work, this was in equal measure interesting, reassuring, and thought-provoking.</p>
<p>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:</p>
<ul>
<li>this new thing should be a component in programming terms but is it a Design System component?</li>
<li>is everyone aware that <em>component</em> 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?</li>
<li>With this difference in meaning, do we maybe need to all be more careful with that word <em>component</em> and perhaps define its meaning in Design Systems terms a bit better, including its boundaries?</li>
<li>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?</li>
<li>isn’t it better for components to be really <em>simple</em> because the less opinionated one is, the more reusable it is, therefore the more we can build things by composition?</li>
</ul>
<p>When I read Brad’s article last night it kind of felt like it was speaking to many of those questions directly!</p>
<p>Some key points he makes:</p>
<ul>
<li>If in doubt: everything should be a component</li>
<li>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.</li>
<li>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).</li>
</ul>
<p>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 <code>Card</code> recently:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>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.</p>
<p>(via <a href="https://twitter.com/jamesmockett">@jamesmockett</a>)</p>
A First Look at aspect-ratio (on CSS-Tricks)2021-02-02T11:37:57Zhttps://fuzzylogic.me/posts/2021-02-02-a-first-look-at-aspectratio-on-csstricks/<p>Chris Coyier takes the new CSS <code>aspect-ratio</code> property for a spin and tests how it works in different scenarios.</p>
<p>Note that he’s applying it here to elements which do not have an intrinsic aspect-ratio. So, think a container element (<code>div</code> or whatever is appropriate) rather than an <code>img</code>. This is line with a <a href="https://twitter.com/jensimmons/status/1347583682496892929">Jen’s Simmons’ recent replies to me</a> when I asked her <a href="https://twitter.com/fuzzylogicx/status/1347307685826469894">whether or not we should apply <code>aspect-ratio</code> to an <code>img</code></a> after she announced <a href="https://twitter.com/jensimmons/status/1347287421633892356">support for <code>aspect-ratio</code> in Safari Technical Preview 118</a>.</p>
<p>A couple of interesting points I took from Chris’s article:</p>
<ul>
<li>this simple new means of declaring aspect-ratio should soon hopefully supersede all the <a href="https://css-tricks.com/aspect-ratio-boxes/">previous DIY techniques</a>;</li>
<li>if you apply a CSS aspect-ratio to an element which has no explicit <code>width</code> set, we still get the effect because the element’s <code>auto</code> (rendered) width is used, then by combining that with the CSS <code>aspect-ratio</code> the browser can calculate the required height, then apply that height;</li>
<li>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 <code>min-height: 0</code>;</li>
<li>if the element has either a height or a width set, the other of the two is calculated from the aspect ratio;</li>
<li>if the element has <em>both</em> a height and width set, <code>aspect-ratio</code> is ignored.</li>
</ul>
<p>Regarding <a href="https://caniuse.com/?search=aspect-ratio">browser support</a>: at the time of writing <code>aspect-ratio</code> 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.</p>
Vanilla JS List2021-02-02T10:19:14Zhttps://fuzzylogic.me/posts/2021-02-02-vanilla-js-list/<p>Here’s Chris Ferdinandi’s curated list of organisations which use vanilla JS to build websites and web apps.</p>
<p>You don’t <em>need</em> a heavyweight JavaScript framework, and vanilla JS <em>does</em> scale.</p>
<p>At the time of writing the list includes Marks & Spencer, Selfridges, Basecamp and GitHub.</p>
<p>(via <a href="https://twitter.com/ChrisFerdinandi">@ChrisFerdinandi</a>)</p>
Bleep Mix #221 - Datassette (on Bleep.com)2021-02-01T15:53:53Zhttps://fuzzylogic.me/posts/2022-11-26-bleep-mix-221-datassette-bleep-your-source-for-independent-and-innovative-music-buy-vinyl-and-cd-download-mp3-wavflac-24bit-wav-and-buy-merchandise/<p>Great DJ mix by one of my favourite electronic producers, Datassette.</p>
<blockquote>
<p>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!</p>
</blockquote>
<p>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.</p>
Source Serif 42021-01-31T21:14:42Zhttps://fuzzylogic.me/posts/2021-01-31-source-serif-4/<p>Here’s a nice demo page for Source Serif 4 which illustrates its versatility.</p>
<blockquote>
<p>Source Serif is an open-source typeface for setting text in many sizes, weights, and languages. The design of Source Serif represents a contemporary interpretation of the transitional typefaces of Pierre-Simon Fournier. Additionally, Source Serif has been conceived as a friendly companion to Paul D. Hunt’s Source Sans.</p>
</blockquote>
<p>Back when I first started using Source Sans Pro for text for my personal website, I tried pairing it with Source Serif for headings. It didn’t quite work for me then but the typeface seems to have undergone some changes in the interim and also now comes with a variable font option. I might give it another spin.</p>
Being – Broxburn Funk2021-01-28T20:41:33Zhttps://fuzzylogic.me/posts/being-%E2%80%93-broxburn-funk/<p>Being’s <em>Broxburn Funk</em> arrived in today’s post and it’s a thing of beauty.</p>
<figure>
<img class="u-full-parent-width" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_414/v1611869319/0022405579_10_bsdsvt.jpg 414w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_480/v1611869319/0022405579_10_bsdsvt.jpg 480w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_646/v1611869319/0022405579_10_bsdsvt.jpg 646w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_828/v1611869319/0022405579_10_bsdsvt.jpg 828w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1611869319/0022405579_10_bsdsvt.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1200/v1611869319/0022405579_10_bsdsvt.jpg 1200w" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_646/v1611869319/0022405579_10_bsdsvt.jpg" alt="Being – Broxburn Funk LP, on vinyl from Firecracker Records" width="600" height="455" loading="lazy" decoding="async" />
</figure>
<p>Enjoying it now with a ☕️. Amazing work all round—music, sound, artwork, the lot. Big up <a href="https://twitter.com/WeeDjs">@WeeDjs</a> for the stellar tunes and if <a href="https://twitter.com/firecracker_rec">@firecracker_rec</a>’s 50th is their last, then they’ve finished with a bang.</p>
<p><a href="https://www.rubadub.co.uk/records/broxburn-funk">Grab a copy at Rubadub</a></p>
Use CSS Clamp to create a more flexible wrapper utility (on Piccalilli)2021-01-26T22:35:54Zhttps://fuzzylogic.me/posts/2021-01-26-use-css-clamp-to-create-a-more-flexible-wrapper-utility-on-piccalilli/<p>Here’s Andy Bell recommending using CSS <code>clamp()</code> to control your wrapper/container <code>width</code> because it supports setting a preferred value in <code>vw</code> to ensure sensible gutters combined with a maximum tolerance in <code>rem</code>—all in a single line of code.</p>
<blockquote>
<p>If we use clamp() to use a viewport unit as the ideal and use what we would previously use as the max-width as the clamp’s maximum value, we get a much more flexible setup.</p>
</blockquote>
<p>The code looks like this:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.container</span> <span class="token punctuation">{</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> <span class="token function">clamp</span><span class="token punctuation">(</span>16rem<span class="token punctuation">,</span> 90vw<span class="token punctuation">,</span> 70rem<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">margin-left</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /> <span class="token property">margin-right</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>This is pretty cool because I know from experience that coding responsive solutions for wrappers can be tricky and you can end up with a complex arrangement of max-width and media queries whilst still—as Andy highlights—not providing optimal readability for medium-sized viewports.</p>
<p><a href="https://fuzzylogic.me/posts/2020-11-17-breaking-out-with-css-grid-layout-on-cloudfourcom/">Using CSS Grid with minmax()</a> is one possible approach to controlling wrappers however this article offers another (potentially better) tool for your kit.</p>
<p>It’s worth noting that Andy could probably have just used <code>width: min(90vw, 70rem)</code> here (<a href="https://twitter.com/c__beck/status/1351515957034889219">as Christopher suggested</a>) because setting the <em>lower bound</em> provided by <code>clamp()</code> is only necessary if your element is likely to shrink unexpectedly and a regular block-level element wouldn’t do that. The <code>clamp</code> approach might be handy for flex items, though.</p>
<p>(via <a href="https://twitter.com/piccalilli_">@piccalilli_</a>)</p>
Music For Programming2021-01-26T20:05:02Zhttps://fuzzylogic.me/posts/2021-01-26-music-for-programming/<p>Feel like I’m probably really late to discover this website, but here’s “Music for Programming” from Datassette. Hopefully this’ll be of use to fellow programmers who like music, although I daresay you can probably enjoy it if you’re a normal person too.</p>
<blockquote>
<p>Through years of trial and error - skipping around internet radio stations, playing our entire music collections on shuffle, or just hammering single albums on repeat, we have found that the most effective music to aid prolonged periods of intense concentration tends to have a mixture of the following qualities: Drones, Noise, Fuzz, Field recordings, Vagueness (Hypnagogia), Textures without rhythm…</p>
</blockquote>
<p>As both a programmer and big fan of <a href="http://datassette.net/">Datassette</a> (the creator/curator of this website), how did I not know about this sooner?! Anyway, plenty to dive into now.</p>
<p>(via <a href="https://twitter.com/datassette">@datassette</a>)</p>
Complete Guide to Source Sans Pro (on Beautiful Web Type)2021-01-26T19:48:37Zhttps://fuzzylogic.me/posts/2021-01-26-complete-guide-to-source-sans-pro-on-beautiful-web-type/<p>At the time of writing, my personal website uses the typeface <em>Source Sans Pro</em> and has done for around two years. I already employ a number of its cool features however this lovely demo page provides further inspiration.</p>
<blockquote>
<p>Source Sans Pro is a versatile typeface designed particularly for user interfaces. Its letterforms are slightly condensed allowing them to fit into tight spaces within a UI, and remain well-defined even at small sizes.</p>
</blockquote>
<p>I might consider going back to using Source Serif Pro for headings again, too.</p>
<p>(via <a href="https://twitter.com/stugoo">@stugoo</a>)</p>
Use Mac Zoom to show the text a screen reader gets2021-01-26T14:31:02Zhttps://fuzzylogic.me/posts/use-mac-zoom-to-show-the-text-a-screen-reader-gets/<p>I picked up a good accessibility testing tip from my work colleague Max today.</p>
<p>On a Mac, if you open System > Accessibility > Zoom, you can enable “hover text”. This allows you to hold down command (cmd) and then whatever is under the mouse will be shown. This shows the same text that a screen reader sees so it’s good for checking if bits of the page respond to a screen reader.</p>
Robb Owen - Independent Creative Developer2021-01-25T10:23:35Zhttps://fuzzylogic.me/posts/2021-01-25-robb-owen-independent-creative-developer/<p>Definite “personal website goals” here in Robb’s beautiful online portfolio and blog.</p>
<blockquote>
<p>From interaction design to scaleable design systems, single-page apps to something more experimental with WebGL. I help awesome people to build ambitious yet accessible web projects - the wilder, the better.</p>
</blockquote>
<p>Robb combines beautiful typography and colours with fun and smooth animation… and the words ain’t half bad, either.</p>
<p>Inspirational work!</p>
Accessible interactions (on Adactio)2021-01-24T13:12:43Zhttps://fuzzylogic.me/posts/2021-01-24-adactio-journalaccessible-interactions/<p>Jeremy Keith takes us through his thought process regarding the choice of link or <code>button</code> when planning accessible interactive disclosure elements.</p>
<p>A <code>button</code> is generally a solid choice as it’s built for general interactivity and carries the expectation that when activated, something somewhere happens. However in some cases a link might be appropriate, for example when the <em>trigger</em> and <em>target content</em> are relatively far apart in the DOM and we feel the need move the user to the target / give it focus.</p>
<p>For a typical disclosure pattern where some content is shown/hidden by an adjacent trigger, a <code>button</code> suits perfectly. The DOM elements are right next to each other and flow into each other so there’s no need to move or focus anything.</p>
<p>However in the case of a log-in link in a navigation menu which—when enhanced by JavaScript—opens a log-in form inside a modal dialogue, a link might be better. In this case you might use an anchor with a fragment identifier (<code><a href="#login-modal">Log in</a></code>) pointing to a login-form far away at the bottom of the page. This simple baseline will work if JavaScript is unavailable or fails, however when JavaScript <em>is</em> available we can intercept the link’s default behaviour and enhance things. Furthermore because the expectation with links is that you’ll <em>go somewhere</em> and modal dialogues are kinda like faux pages, the link feels appropriate.</p>
<p>While not explicit in the article, another thing I take from this is that by structuring your no-JavaScript experience well, this will help you make appropriate decisions when considering the with-JavaScript experience. There’s a kind of virtuous circle there.</p>
Meta Tags - Preview, Edit and Generate2021-01-24T09:25:33Zhttps://fuzzylogic.me/posts/2021-01-24-meta-tags-preview-edit-and-generate/<p>A handy tool which lets you type in a URL then inspects that page’s meta tags and shows you how it will be presented on popular websites.</p>
<p>This is really useful for testing how an article will look as a Google search result or when shared on Facebook, Slack and Twitter based on different meta tag values.</p>
Comparing Browsers for Responsive Design (on CSS-Tricks)2021-01-23T20:00:14Zhttps://fuzzylogic.me/posts/2021-01-23-comparing-browsers-for-responsive-design-on-csstricks/<p>Chris Coyier checks out Sizzy, Polypane et al and decides which suits him best.</p>
<blockquote>
<p>There are a number of these desktop apps where the goal is showing your site at different dimensions all at the same time. So you can, for example, be writing CSS and making sure it’s working across all the viewports in a single glance.</p>
</blockquote>
<p>I noticed Andy Bell recommending <a href="https://sizzy.co/">Sizzy</a> so I’m interested to give it a go. Polypane got Chris’s vote, but is a little more expensive at ~£8 per month versus ~£5, so I should do a little shoot-out of my own.</p>
Progressively enhanced JavaScript In Real Life2021-01-22T11:46:08Zhttps://fuzzylogic.me/posts/progressively-enhanced-javascript-in-real-life/<p>Over the last couple of days I’ve witnessed a good example of progressive enhancement “In Real Life”. And I think it’s good to log and share these validations of web development best practices when they happen so that their benefits can be seen as real rather than theoretical.</p>
<p>A few days ago I noticed that the search function on <a href="https://fuzzylogic.me/">my website</a> wasn’t working optimally. As usual, I’d click the navigation link “Search” then some JavaScript would reveal a search input and set keyboard focus to it, prompting me to enter a search term. Normally, the JavaScript would then “look ahead” as I type characters, searching the website for matching content and presenting (directly underneath) a list of search result links to choose from.</p>
<p>The problem was that although the search input was appearing, the search result suggestions were no longer appearing as I typed.</p>
<p>Fortunately, back when I built the feature I had just read Phil Hawksworth’s <a href="https://www.hawksworx.com/blog/adding-search-to-a-jamstack-site/">Adding Search to a Jamstack site</a> which begins by creating a non-JavaScript baseline using a standard <code>form</code> which submits to <a href="https://www.google.co.uk/">Google Search</a> (scoped to your website), passing as search query the search term you just typed. This is how I built mine, too.</p>
<p>So, just yesterday at work I was reviewing a PR which prompted me to search for a specific article on my website by using the term “aria-label”. And although the enhanced search wasn’t working, the baseline search functionally was there to deliver me to a Google search result page (<code>site:https://fuzzylogic.me/ aria-label</code>) with the exact article I needed appearing top of the search results. Not a rolls-royce experience, but perfectly serviceable!</p>
<p>Why had the enhanced search solution failed? It was because the <code>.json</code> file which is the data source for the lookahead search had at some point allowed in a weird character and become malformed. And although the site’s JS was otherwise fine, this malformed data file was preventing the enhanced search from working.</p>
<p>JavaScript is brittle and fails for many reasons and in many ways, making it different from the rest of the stack. Added to that there’s the “unavailable until loaded” aspect, or <a href="https://twitter.com/jaffathecake/status/207096228339658752">as Jake Archibald put it</a>:</p>
<blockquote>
<p>all your users are non-JS while they’re downloading your JS.</p>
</blockquote>
<p>The best practices that we as web developers have built up for years are not just theoretical. Go watch a screen reader user browse the web if you want proof that providing descriptive link text rather than “click here”, or employing headings and good document structure, or describing images properly with <code>alt</code> attributes are worthwhile endeavours. Those users <em>depend</em> on those good practices.</p>
<p>Likewise, JavaScript <em>will</em> fail to be available on ocassion, so building a baseline no-JS solution will ensure that when it does, the show still goes on.</p>
Assistiv Labs2021-01-18T09:38:32Zhttps://fuzzylogic.me/posts/2021-01-18-assistiv-labs/<p>A tool for testing how accessible your experience is on various assistive technologies – perhaps “like BrowserStack but for screen readers”?</p>
<blockquote>
<p>Assistiv Labs remotely connects you to real assistive technologies, like NVDA, VoiceOver, and TalkBack, using any modern web browser.</p>
</blockquote>
<p>I use a Mac for development which means that when I do screen reader testing <a href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/">I use the Mac’s VoiceOver tool</a>. However the majority of screen reader users are using NVDA via Firefox on a PC. Perhaps this tool might let me test on that stack without buying a PC.</p>
<p>Next action: sign up for a free trial and give it a go!</p>
<p>(via <a href="https://www.matthewroach.me/">Matthew</a> and <a href="https://twitter.com/paddyduke">@paddyduke</a>)</p>
VisualSitemaps: Autogenerate Beautiful Sitemaps and Screenshots2021-01-16T18:21:17Zhttps://fuzzylogic.me/posts/2021-01-16-visualsitemaps-autogenerate-beautiful-sitemaps-and-screenshots/<p>A great tool for automatically generating a visual sitemap (<em>visual</em> because it attaches a screenshot to each node) for any given website.</p>
<blockquote>
<p>Simply enter a URL and get a thumbnail-based visual architecture of the entire site.</p>
</blockquote>
<p>You can even have it <a href="https://support.visualsitemaps.com/en/articles/3673081-how-to-crawl-a-password-protected-private-website">crawl a password-protected website</a>.</p>
07/01/21 DJ Mix – Manifold2021-01-07T21:26:38Zhttps://fuzzylogic.me/posts/dj-mix-manifold/<p>First in a series of mainly short, off the cuff mixes where I just hit record and see where it goes. This one’s on the Electro tip, having kicked it off with Versalife’s <em>Manifold</em> from last year.</p>
<iframe title="“07/01/21 DJ Mix – Manifold by Laurence Hughes" width="100%" height="120" src="https://www.mixcloud.com/widget/iframe/?hide_cover=1&feed=%2Flaurencehughes%2F7121-mix-manifold%2F" frameborder="0"></iframe>
<h2 id="tracklist%3A" tabindex="-1">Tracklist: <a class="direct-link" href="https://fuzzylogic.me/posts/dj-mix-manifold/#tracklist%3A" aria-hidden="true">#</a></h2>
<ol>
<li>Versalife – Manifold</li>
<li>Carl Finlow – Components</li>
<li>Sedgwick – Rhythm & Isolation</li>
<li>ESB – Tethys</li>
<li>Reedale Rise – Transluscent</li>
<li>Anthiliawaters – Barcelona</li>
<li>Turner Street Sound – Dunes (Oceanic Mix)</li>
</ol>
<p>The mix was recorded on two Technics SL1210s and an Isonoe ISO420 mixer.</p>
<p>If you like talking music feel free to give me a shout on Twitter <a href="https://twitter.com/fuzzylogicx">@fuzzylogicx</a>.</p>
A Utility Class for Covering Elements (on CSS { In Real Life })2021-01-06T15:25:29Zhttps://fuzzylogic.me/posts/2021-01-06-a-utility-class-for-covering-elements-on-css-in-real-life/<p>Need to overlay one HTML element on top of and fully covering another, such as a heading with translucent background on top of an image? Michelle Barker has us covered with this blog post in which she creates an <code>overlay</code> utility to handle this. She firstly shows how it can be accomplished with positioning, then modernises her code using the <code>inset</code> CSS logical property, before finally demonstrating a neat CSS Grid based approach.</p>
<p>I like this and can see myself using it – especially the Grid-based version because these days I try to avoid absolute positioning and use modern layout tools instead where possible.</p>
<p>I’ve <a href="https://codepen.io/fuzzylogicx/pen/XWjYmyZ">mocked up a modified version on Codepen</a>, sticking with CSS Grid for simplicity. I was going to also wrap it in an <code>@supports (display:grid)</code> however the styles are all grid-based so in the case of no grid support they simply wouldn’t run, rather than causing any problems.</p>
Newsletters, by Robin Rendle2021-01-05T21:41:59Zhttps://fuzzylogic.me/posts/2021-01-05-newsletters-by-robin-rendle/<p>A fantastic so-called “Scroll Story” from Robin Rendle. In his own words it’s “an elaborate blog post where I rant about a thing” however given the beautiful typography, layout and illustrations on show I think he’s selling it a little short!</p>
<p>The content of this “story” is pretty interesting – Robin laments the fact that web authors often need newsletters, or to “spam social media” in order to publicise articles on their websites, because most people don’t use RSS (awareness is too low and barriers to entry too great).</p>
<p>However it’s the story’s design and technical implementation which really caught my eye.</p>
<p>Robin does some really cool stuff with the CSS <code>scroll-snap-type</code> property and also explains some steps he had to take to tame differing implementations of <code>height:100vh</code> across browsers.</p>
BBC GEL | The lessons learnt creating a design system for BBC Online2021-01-05T11:45:29Zhttps://fuzzylogic.me/posts/2021-01-05-bbc-gel-or-the-lessons-learnt-creating-a-design-system-for-bbc-online/<p>Interesting insight into the BBC design system and the five areas it’s split into: Foundations, Components, Layout Components (including Stack, Grid etc) Levers and Containers.</p>
<p>(via <a href="https://twitter.com/piccalilli_">@piccalilli_</a>)</p>
Note 2020-10-25T16:00:58: Andrew Weatherall – A Jockey Slut Tribute2021-01-04T19:56:46Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-andrew-weatherall-%E2%80%93-a-jockey-slut-tribute/<p>I’ve started reading <a href="https://jockeyslut.ochre.store/merch/210070-andrew-weatherall-a-jockey-slut-tribute">Andrew Weatherall – A Jockey Slut Tribute</a>.</p>
Merch Table2021-01-04T17:50:15Zhttps://fuzzylogic.me/posts/2021-01-04-merch-table/<p>A neat online tool (with a positive goal) which lets you paste in a link to one of your Spotify playlists then lets you know which of the tracks or albums are available to buy on Bandcamp.</p>
<blockquote>
<p>Support the artists you listen to by buying their stuff.</p>
</blockquote>
Create an Automatically Responsive Flexbox Gallery (on egghead.io)2021-01-03T22:57:03Zhttps://fuzzylogic.me/posts/2021-01-03-create-an-automatically-responsive-flexbox-gallery-on-eggheadio/<p>Here’s a lovely intrinsically responsive (no media queries) photo gallery solution from <a href="https://twitter.com/5t3ph">Stephanie Eckles</a>. It can accommodate differently sized images and achieves its layout by a combination of flexbox features (<code>flex-wrap</code>, <code>flex-basis</code>) and by applying <code>object-fit: cover</code> to photos to make them fully <em>cover</em> their parent list items.</p>
<p><a href="https://codepen.io/fuzzylogicx/pen/QWKmBOp">Here’s my crack at it on Codepen.</a></p>
Big picture performance analysis using Lighthouse Parade (on Cloud Four)2021-01-03T18:42:11Zhttps://fuzzylogic.me/posts/2021-01-03-big-picture-performance-analysis-using-lighthouse-parade-on-cloud-four/<p>I like the sound of this performance analysis tool from the clever folks at <a href="https://cloudfour.com/">Cloud Four</a>, especially because it covers your entire site rather than just a single page.</p>
<blockquote>
<p>Lighthouse Parade is a Node.js command line tool that crawls a domain and gathers lighthouse performance data for every page. With a single command, the tool will crawl an entire site, run a Lighthouse report for each page, and then output a spreadsheet with the aggregated data.</p>
</blockquote>
<p>It was also easy to run with no local installation, via:</p>
<figure>
<pre class="language-bash"><code class="language-bash">npx lighthouse-parade https://fuzzylogic.me</code></pre>
</figure>
<p>However it was taking a <em>long</em> time to run over all the pages of my statically generated site (there are lots of pages), so much so that I felt I needed to stop it due to my laptop sounding like it was about to take off. So if running it again, I’d probably only do so on a smaller site, or first check <a href="https://github.com/cloudfour/lighthouse-parade">the tool’s documentation</a> to see if either scope-limiting or sitemap-based crawling support have been added.</p>
My Command Line Cheatsheet2020-12-28T16:58:08Zhttps://fuzzylogic.me/posts/my-command-line-cheatsheet/<p>Here’s a list of useful terminal commands for my reference and yours.</p>
<h2 id="using-iterm2-(terminal-emulator)" tabindex="-1">Using iTerm2 (Terminal Emulator) <a class="direct-link" href="https://fuzzylogic.me/posts/my-command-line-cheatsheet/#using-iterm2-(terminal-emulator)" aria-hidden="true">#</a></h2>
<h3 id="composer" tabindex="-1">Composer <a class="direct-link" href="https://fuzzylogic.me/posts/my-command-line-cheatsheet/#composer" aria-hidden="true">#</a></h3>
<p>Make editing long lines easier by using Composer.</p>
<p>Open Composer: <kbd class="block">Shift-Cmd-.</kbd></p>
<p>Type your long command and enjoy using standard text editing controls:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> commit -am <span class="token string">"A very long commit message"</span></code></pre>
</figure>
<p>Send Composer command to terminal: <kbd class="block">Shift-Return</kbd></p>
<h3 id="snippets" tabindex="-1">Snippets <a class="direct-link" href="https://fuzzylogic.me/posts/my-command-line-cheatsheet/#snippets" aria-hidden="true">#</a></h3>
<p><kbd class="block">Toolbelt > Show Toolbelt</kbd></p>
<p>Then add, edit and delete commands.</p>
<p>Select a command then use <code>Send</code> to insert it on the terminal.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/my-command-line-cheatsheet/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://abookapart.com/products/working-the-command-line"><em>Working the Command Line</em></a> by Remy Sharp from <em>A List Apart</em></li>
</ul>
The Race for a Vaccine (on BBC One - Panorama)2020-12-20T22:44:22Zhttps://fuzzylogic.me/posts/2021-01-24-the-race-for-a-vaccine-on-bbc-one-panorama/<blockquote>
<p>Panorama tells the inside story of the development of the Oxford vaccine against Covid-19. For the past 11 months, the BBC's medical editor Fergus Walsh followed the team at Oxford University and AstraZeneca, as they designed, developed, manufactured and trialled the vaccine.</p>
</blockquote>
<p>In the middle of a pretty depressing period, this is fantastic TV about an inspirational scientific effort.</p>
My DevTools Cheatsheet2020-12-13T12:25:28Zhttps://fuzzylogic.me/posts/my-devtools-cheatsheet/<p>Here’s a (work in progress) list of useful (Mac) Browser DevTools tips, tricks and keyboard shortcuts for my reference and yours. This is a work in progress and I’ll update it as I go.</p>
<h2 id="console-panel" tabindex="-1">Console Panel <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#console-panel" aria-hidden="true">#</a></h2>
<h3 id="return-currently-selected-element-to-work-with" tabindex="-1">Return currently selected element to work with <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#return-currently-selected-element-to-work-with" aria-hidden="true">#</a></h3>
<p><kbd>$0</kbd></p>
<p>Then you can execute its methods or inspect its attribute values, for example:</p>
<p><kbd>$0.offsetParent</kbd></p>
<h3 id="debug-event-based-behaviour" tabindex="-1">Debug event-based behaviour <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#debug-event-based-behaviour" aria-hidden="true">#</a></h3>
<p>In Chrome, right-click on the relevant element (e.g. a button) and select “Inspect Element”. By default, the Styles panel is selected but instead select the <em>Event Listeners</em> panel. In there you can see all events (e.g. <em>click</em>) currently being listened for on that element (and its parent elements so as to include instances of <em>event delegation</em>).</p>
<p>Each event can be expanded to show which element has the event listener attached – for example it might be the current element or might be <code>document</code>. From here you can get to the script containing the code. Click a line number within the code to add a breakpoint. This will pause code execution on that line until you click the play button to continue. You might also log the current value of a variable here.</p>
<h2 id="pause-javascript-execution" tabindex="-1">Pause JavaScript execution <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#pause-javascript-execution" aria-hidden="true">#</a></h2>
<p><kbd>Cmd + backslash</kbd></p>
<h2 id="firefox" tabindex="-1">Firefox <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#firefox" aria-hidden="true">#</a></h2>
<h3 id="get-responsive-img-element%E2%80%99s-currentsrc" tabindex="-1">Get responsive <code>img</code> element’s <code>currentSrc</code> <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#get-responsive-img-element%E2%80%99s-currentsrc" aria-hidden="true">#</a></h3>
<p>Inspect the element, right click and select Show DOM Properties from the context menu.</p>
<h2 id="google-chrome" tabindex="-1">Google Chrome <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#google-chrome" aria-hidden="true">#</a></h2>
<h3 id="open-the-command-menu" tabindex="-1">Open the Command Menu <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#open-the-command-menu" aria-hidden="true">#</a></h3>
<p><kbd>Command+Shift+P</kbd></p>
<h3 id="disable-javascript" tabindex="-1">Disable JavaScript <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#disable-javascript" aria-hidden="true">#</a></h3>
<p>Open the Command Menu then type “disable” and you’ll see the option.</p>
<h3 id="get-responsive-img-element%E2%80%99s-currentsrc-1" tabindex="-1">Get responsive <code>img</code> element’s <code>currentSrc</code> <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#get-responsive-img-element%E2%80%99s-currentsrc-1" aria-hidden="true">#</a></h3>
<p>Inspect the element, click the properties tab, toggle open the top item.</p>
<h3 id="throttle-network%2Fbandwidth" tabindex="-1">Throttle network/bandwidth <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#throttle-network%2Fbandwidth" aria-hidden="true">#</a></h3>
<p>Go to tab <em>Network</em> then change <em>Throttling</em> to your desired setting, for example “Slow 3G”, or “offline”.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/my-devtools-cheatsheet/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://gomakethings.com/how-to-view-and-edit-javascript-in-your-browsers-developer-tools/">How to view and edit JavaScript in your browser's developer tools</a></li>
</ul>
Words and phrases I always struggle with2020-12-12T00:00:00Zhttps://fuzzylogic.me/posts/words-and-phrases-i-always-struggle-with/<p>I’m not sure if it‘s just me, but there are certain words and phrases which—no matter how many times I look up—just seem to be beyond me! So I’ve decided to note their meanings for future reference. Hopefully this might help make the meanings stick.</p>
<dl>
<dt>Hubris</dt>
<dd>excessive pride or self-confidence</dd>
<dt>Pathos</dt>
<dd>a quality (e.g. of a person) that evokes pity or sadness. For example an actor might inject pathos into a character.</dd>
<dt>Single point of failure</dt>
<dd>a part of a system that, if it fails, the whole system fails. It’s generally a bad thing.</dd>
<dt>Non-zero-sum game</dt>
<dd>in game theory, a situation where one player's gain is not necessarily another player's loss. There are actions from which everyone can benefit.</dd>
</dl>
Browser Support Heuristics2020-12-07T20:33:37Zhttps://fuzzylogic.me/posts/browser-support-heuristics/<p>In web development it’s useful when we can say “if the browser supports X, then we know it also supports Y”.</p>
<p>There was a small lightbulb moment at work earlier this year when we worked out that:</p>
<blockquote>
<p>if the user’s browser supports CSS Grid, then you know you it also supports custom properties.</p>
</blockquote>
<p>Knowing this means that if you wrap some CSS in an <code>@supports(display:grid)</code> then you can also safely use custom properties within that block.</p>
<p>I love this rule of thumb! It saves you looking up <a href="https://caniuse.com/">caniuse.com</a> for each feature and comparing the browser support.</p>
<p>This weekend I did some unplanned rabbit-holing on the current state of (and best practices for using) ES modules in the browser, as-is and untranspiled. That revealed another interesting rule of thumb:</p>
<blockquote>
<p>any browser that supports <code><script type="module"></code> also supports <code>let</code> and <code>const</code>, <code>async/await</code>, the spread operator, etc.</p>
</blockquote>
<p>One implication of this is that if you currently build a large JavaScript bundle (due to being transpiled down to ES 3/5 and including lots of polyfills) and ship this to <em>all</em> browsers including the modern ones… you could instead improve performance for the majority of your visitors by configuring your bundler to generate <em>two</em> bundles from your code then doing:</p>
<figure>
<pre class="language-html"><code class="language-html">// only one of these will be used. <br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>lean-and-modern.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">nomodule</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>bulky-alternative-for-old-browsers.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>I might make a little page or microsite for these rules of thumb. They’re pretty handy!</p>
A11y is not “extra effort for people with disabilities”2020-12-07T10:35:47Zhttps://fuzzylogic.me/posts/2020-12-07-a11y-is-not-extra-effort-for-people-with-disabilities/<p>Strong agree with these sentiments regarding accessibility expressed by Max Böck and Andrey Okonetchnikov on Twitter.</p>
<p>From Andrey:</p>
<blockquote>
<p>If you’re building UI, it’s your responsibility to make it work for everyone. Clients often tell me “we don’t care about accessibility” but in reality they do want keyboard support at the very least. So I just build my UI in a way it works without discussing it. It’s my job.</p>
</blockquote>
<p>To which Max replies:</p>
<blockquote>
<p>This. A11y is not “extra effort for people with disabilities”, it‘s just part of a well-crafted UI.</p>
</blockquote>
Note 2020-10-25T16:00:58: Rudy is 6 months old2020-12-06T19:56:16Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-rudy-is-6-months-old/<p>Our wee Border Terrier, Rudy, is six months old. It’s funny to think how far he’s come since needing carried everywhere just a short while ago. In this weirdest of years, the wee man has been a constant ray of sunshine. Love ye, Rood!</p>
<figure>
<img src="https://res.cloudinary.com/fuzzylogic/image/upload/v1605553950/125435883_1615067328665123_36529131671022288_n_xtgozx.jpg" alt="Rudy smiling for the camera while out walking with his puppy pals, Autumn 2020" loading="lazy" width="664" height="960" />
</figure>
Small Axe - Series 1: Red, White and Blue (on BBC iPlayer)2020-12-04T18:23:45Zhttps://fuzzylogic.me/posts/2020-12-04-small-axe-series-1-red-white-and-blue-on-bbc-iplayer/<p>One of several fantastic films from Oscar-winning director Steve McQueen (<em>12 Years a Slave</em>) described as “Love letters to black resilience and triumph in London's West Indian community. Vivid stories of hard-won victories in the face of racism.”</p>
<p>This one tells the story of Leroy Logan, a young black man who joins the police in an attempt to effect change “from the inside” as a consequence of seeing his father assaulted by police officers. He is faced with both his father’s disapproval and institutional racism within the police ranks.</p>
<p>A brilliant and powerful film which left its mark on me.</p>
<p>The others in the series – especially <a href="https://www.bbc.co.uk/iplayer/episode/m000qfb1/small-axe-series-1-education">Education</a>, <a href="https://www.bbc.co.uk/iplayer/episode/m000prjp/small-axe-series-1-lovers-rock">Lovers Rock</a> (don’t miss if you love reggae) and <a href="https://www.bbc.co.uk/iplayer/episode/p08vy19b/small-axe-series-1-mangrove">Mangrove</a> are also highly recommended. Wonderful soundtracks, too.</p>
<p>via <a href="https://twitter.com/mrtomchurchill">@mrtomchurchill</a></p>
Creating websites with prefers-reduced-data (on polypane.app)2020-12-03T08:57:41Zhttps://fuzzylogic.me/posts/2020-12-03-creating-websites-with-prefersreduceddata-on-polypane/<blockquote>
<p>Even though more and more people get access to the internet every day, not all of them have fast gigabit connections or unlimited data. Using the media query prefers-reduced-data we can keep our sites accessible to everyone.</p>
</blockquote>
<p>I’ve long wondered if there could be a way to tailor content to a user based on the speed of their internet connection, especially when considering features like responsive images. This looks like it might be the way to do that (although browser support is currently non-existent). It also allows us to respect the user’s wishes on how much data / battery life etc they’re willing to spare for your website.</p>
<p>(via <a href="https://twitter.com/adactio">@adactio</a>)</p>
My Screen Reader Cheatsheet2020-12-02T15:58:08Zhttps://fuzzylogic.me/posts/my-screen-reader-cheatsheet/<p>Here’s a list of useful Screen Reader commands and tips for my reference and yours. This is a work in progress and I’ll update it as I go.</p>
<h2 id="voiceover-(mac)" tabindex="-1">VoiceOver (Mac) <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#voiceover-(mac)" aria-hidden="true">#</a></h2>
<h3 id="initial-setup%3A" tabindex="-1">Initial setup: <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#initial-setup%3A" aria-hidden="true">#</a></h3>
<ol>
<li>Open Safari > Preferences > Advanced; then</li>
<li>check the checkbox “Press tab to highlight each item on a webpage”.</li>
</ol>
<h3 id="usage" tabindex="-1">Usage <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#usage" aria-hidden="true">#</a></h3>
<ul>
<li>Open the page you want to test in your web browser (you might favour Safari for VoiceOver).</li>
<li><kbd>Cmd-F5</kbd> to turn VoiceOver on.</li>
<li><kbd>Cmd-F5</kbd> (again) to turn VoiceOver off.</li>
</ul>
<p>Get <kbd>Cmd-F5</kbd> for “toggling on and off” into your muscle memory!</p>
<p>Then:</p>
<ul>
<li><kbd>Ctrl-Option-A</kbd> to have VoiceOver read the entire page.</li>
<li><kbd>Ctrl</kbd> to pause VoiceOver, and <kbd>Ctrl</kbd> again to resume.</li>
<li>Find any unexpected issues by</li>
</ul>
<h4 id="tabbing" tabindex="-1">Tabbing <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#tabbing" aria-hidden="true">#</a></h4>
<p>Tab through items on the page using the tab key. This will move to the next focusable item (button, link, input). You can verify all interactive elements have a focus style, all interactive elements are reachable by keyboard, all off-screen or hidden elements don’t get focused when they shouldn’t and that the spoken label for each interactive element has sufficient context to understand it (“click here” and “menu” isn’t sufficient).</p>
<h4 id="navigating-with-the-right-pointing-arrow-key" tabindex="-1">Navigating with the right-pointing arrow key <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#navigating-with-the-right-pointing-arrow-key" aria-hidden="true">#</a></h4>
<p>Navigate through all the content using <kbd>Ctrl-Option-→</kbd>. While this is not how most screen reader users will read the page, it doesn’t take long and lets you confirm that everything VoiceOver announces makes sense.</p>
<h4 id="using-rotor-to-scan-and-jump-to-specific-elements" tabindex="-1">Using Rotor to scan and jump to specific elements <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#using-rotor-to-scan-and-jump-to-specific-elements" aria-hidden="true">#</a></h4>
<ul>
<li><kbd>Ctrl-Option-U</kbd> to open Rotor</li>
<li>Browse categories using left and right arrows. This includes the <em>Landmarks</em> menu.</li>
<li>Down arrow to browse within the categories</li>
<li>press Return to select an item</li>
</ul>
<p>This is a great way to check if your content structure makes sense to a screen reader. Checking the headings illustrates the outline of the page. Viewing the links helps ensure they all have a name that makes sense without visual context. Checking landmarks helps ensure that the proper ARIA roles have been applied. You might find that a list of articles is not titled appropriately or that headings are not properly nested.</p>
<h3 id="tables" tabindex="-1">Tables <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#tables" aria-hidden="true">#</a></h3>
<ul>
<li>Navigate to a table using <kbd>Ctrl-Option-Cmd-T<kbd></kbd></kbd></li>
<li>It should read a caption and give you info about the size of the table</li>
<li><kbd>Ctrl-Cmd-{arrowkey}</kbd> to navigate inside the table.</li>
</ul>
<h3 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/my-screen-reader-cheatsheet/#references" aria-hidden="true">#</a></h3>
<ul>
<li><a href="https://thegymnasium.com/take5/introduction-to-screen-readers-using-voiceover">Ethan Marcotte’s Introduction to Screen Readers Using VoiceOver</a></li>
<li><a href="https://cloudfour.com/thinks/mac-voiceover-testing-the-simple-way/">Mac VoiceOver testing the simple way</a> on Cloud Four’s blog</li>
<li><a href="https://inclusive-components.design/data-tables/">Data Tables on Inclusive Components</a></li>
</ul>
Note 2020-10-25T16:00:58: The Left Hand of Darkness2020-12-01T21:41:04Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-the-left-hand-of-darkness/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9781473225947"><em>The Left Hand of Darkness</em></a> by Ursula K. Le Guin.</p>
Autumn 2020 Records Round-up2020-11-27T22:00:00Zhttps://fuzzylogic.me/posts/autumn-2020-music-purchases/<figure>
<img class="u-full-parent-width" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_414/v1609971455/facefacts_1300_qzkqwh.jpg 414w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_480/v1609971455/facefacts_1300_qzkqwh.jpg 480w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_646/v1609971455/facefacts_1300_qzkqwh.jpg 646w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_828/v1609971455/facefacts_1300_qzkqwh.jpg 828w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1609971455/facefacts_1300_qzkqwh.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1292/v1609971455/facefacts_1300_qzkqwh.jpg 1292w" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_646/v1609971455/facefacts_1300_qzkqwh.jpg" alt="Laurence’s record purchases in Autumn 2020" width="480" height="251" loading="lazy" decoding="async" />
</figure>
<!-- 646 338-->
<p style="margin-top: 3rem;">As the leaves fell and the nights drew in, I chose to fall forward by blowing all my hard-earned on a lovely mixed bag of dub, ambient, soul, house and electro records. Now, if I could just find some puppy-free time to actually listen to them…</p>
<p>One wee thought before we dig in: I’m finding that I’m buying from Bandcamp more and more now that many (most?) of the records I want seem to appear there first. That’s great for the artists (they get most of the profit minus Bandcamp’s cut) so it’s a positive thing, but what about physical record shops? This got me thinking: now that we have <a href="https://uk.bookshop.org/">Bookshop</a> supporting independent, <em>bricks and mortar</em> book shops by spreading profits among them, could a similar online enterprise maybe exist for record shops?</p>
<p>OK, enough pontificating – here’s the music.</p>
<h2 id="nat-birchall-meets-al-breadwinner---upright-living" tabindex="-1">Nat Birchall meets Al Breadwinner - Upright Living <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#nat-birchall-meets-al-breadwinner---upright-living" aria-hidden="true">#</a></h2>
<p>Real nice roots reggae and dub instrumentals from sunny Manchester. Mr Birchall is, by all accounts, an amazing musician, and in Al Breadwinner on drums and Vin Gordon on trumpet he’s assembled a stellar band. When I first heard this I thought it was some vintage Augustus Pablo so it was funny to find out that it was in fact made in 2020 in Stockport.</p>
<p><b>Favourite track(s):</b> African Village Dance / Village Dub.</p>
<div class="l-frame">
<iframe title="Nat Birchall meets Al Breadwinner – African Village Dance" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oo35Duhy-8c" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://natbirchallmusic.bandcamp.com/album/upright-living-nat-birchall-meets-al-breadwinner">Grab a copy on Bandcamp</a></p>
<h2 id="om-unit-meets-seekers-international-%E2%80%93-secret-location" tabindex="-1">Om Unit meets Seekers International – Secret Location <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#om-unit-meets-seekers-international-%E2%80%93-secret-location" aria-hidden="true">#</a></h2>
<p>As a big fan of Om Unit’s ouput around 2011 and Seekers’ 2017 <a href="https://www.discogs.com/Seekers-International-RunComeTest-EP/release/11161848">RunComeTest EP</a> I was pretty excited to hear about this collab… and it doesn’t disappoint. 7 dollops of deep, digi-dub bass, grainy atmospheres and dancehall samples, on a lovely pressing which sounds amazing.</p>
<p><b>Favourite Track:</b> Nu Killa</p>
<div class="l-frame">
<iframe title="Om Unit meets Seekers International – Nu Killa" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/MXfv_QEwhR4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://berceuseheroique.bandcamp.com/album/bh-063-om-unit-meets-seekers-international-secret-location">Grab a copy on Bandcamp</a></p>
<h2 id="linkwood-%26-other-lands-%E2%80%93-face-the-facts" tabindex="-1">Linkwood & Other Lands – Face the Facts <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#linkwood-%26-other-lands-%E2%80%93-face-the-facts" aria-hidden="true">#</a></h2>
<p>Lovely gatefold double-vinyl LP that sees two of Auld Reekie’s finest join forces on the excellent Athens of the North label. Breezy laid-back jams with smooth keys lead into rougher, Theo Parrish -esque joints then spacey textures, making for a really well-rounded listen.</p>
<p><b>Favourite Track:</b> Shapes</p>
<div class="l-frame">
<iframe title="Linkwood & Other Lands – Shapes" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oCdHPH77b5c" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://aotns.bandcamp.com/album/face-the-facts">Grab a copy on Bandcamp</a></p>
<h2 id="satoshi-%26-makoto---cz-5000-sounds-%26-sequences-vol.-ii" tabindex="-1">Satoshi & Makoto - CZ-5000 Sounds & Sequences Vol. II <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#satoshi-%26-makoto---cz-5000-sounds-%26-sequences-vol.-ii" aria-hidden="true">#</a></h2>
<p>Beautiful ambient textures and downtempo electronics with that typically quirky Japanese flavour. If you like Ryuichi Sakamoto or <a href="https://www.discogs.com/%E3%82%A2%E3%83%9D%E3%82%B8%E3%83%BC-%E3%83%9A%E3%83%AA%E3%82%B8%E3%83%BC-%E8%B6%85%E6%99%82%E7%A9%BA%E3%82%B3%E3%83%AD%E3%83%80%E3%82%B9%E3%82%BF%E3%83%B3%E6%97%85%E8%A1%8C%E8%A8%98/master/436802">Apogee & Perigee</a>, you’ll love this.</p>
<p><b>Favourite track:</b> Correndor.</p>
<div class="l-frame"><iframe title="Satoshi & Makoto – Correndor" width="560" height="315" src="https://www.youtube-nocookie.com/embed/qBJBzwbFQFg" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<p><a href="https://nemutai.bandcamp.com/album/cz-5000-sounds-sequences-vol-ii">Grab a copy on Bandcamp</a></p>
<h2 id="various---buena-onda-balearic-beats" tabindex="-1">Various - Buena Onda Balearic Beats <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#various---buena-onda-balearic-beats" aria-hidden="true">#</a></h2>
<p>Lovely four-tracker of slow and atmospheric late-night grooves from Italy and elsewhere, first heard on <a href="https://dublab.de/broadcasts/watching-like-nobodys-dancing-din-daa-daa-october-2020/">Denise’s radio show</a>.</p>
<p><b>Favourite track:</b> Lucas Croon – Japon.</p>
<div class="l-frame">
<iframe title="Lucas Croon – Japon" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/QVt99311d4A" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://hellyeahrec.bandcamp.com/album/buena-onda-balearic-beats">Grab a copy on Bandcamp</a></p>
<h2 id="str4ta---aspects" tabindex="-1">STR4TA - Aspects <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#str4ta---aspects" aria-hidden="true">#</a></h2>
<p>A nice surprise from Gilles Peterson’s label, this is a brand new, authentic jazz-funk / disco hybrid with immaculate live playing and production, and drum fills that tip a hat to Atmosfear’s 1979 staple <em>Dancing in Outer Space</em>.</p>
<p><b>Favourite track:</b> Aspects</p>
<div class="l-frame">
<iframe title="Linkwood & Other Lands – Shapes" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/wxtnkyaF5ug" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://str4ta.bandcamp.com/album/aspects">Grab a copy on Bandcamp</a></p>
<h2 id="midnight-tenderness---digi-modes" tabindex="-1">Midnight Tenderness - Digi Modes <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#midnight-tenderness---digi-modes" aria-hidden="true">#</a></h2>
<p>Another beauty from Melbourne-based Ryan Hunter whose previous releases – whether under this alias for the <a href="https://www.discogs.com/Midnight-Tenderness-Refresco-/release/11909269">Refresco EP</a>, or as Turner Street Sound for 2018’s amazing <a href="https://www.discogs.com/Turner-Street-Sound-Bunsens-Vol-1/release/11577583">Bunsens</a> – have been much appreciated ‘round these parts. This one, on lovely transparent golden 7″, offers a speedy, skanking and soulful update to the traditional dub techno blueprint.</p>
<div class="l-frame">
<iframe title="Sansibar – Technology" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/hEnv0MTYB64" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://buttersessions.bandcamp.com/album/digi-modes">Grab a copy on Bandcamp</a></p>
<h2 id="sansibar---targeted-individuals" tabindex="-1">Sansibar - Targeted Individuals <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#sansibar---targeted-individuals" aria-hidden="true">#</a></h2>
<p>No-messin’, pacey, but cinematic electro which sounds like it’s from Detroit but is actually from the hand of one Sunny Seppa of Helsinki. Nothing ground-breaking on display here but what it does, it does really well. If you dig ERP or classic Dopplereffekt you’ll love this.</p>
<p><b>Favourite track:</b> Technology</p>
<div class="l-frame">
<iframe title="Sansibar – Technology" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/xIqqBlIysN4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.rubadub.co.uk/records/targeted-individuals">Grab a copy from Rubadub</a></p>
<h2 id="art-crime---distanced" tabindex="-1">Art Crime - Distanced <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#art-crime---distanced" aria-hidden="true">#</a></h2>
<p>Limited edition moody drone/ambient 7″ from Russia, with accompanying <a href="https://www.youtube.com/watch?v=BfJQfn4pcNU">drone movie</a>.</p>
<p><b>Favourite track:</b> Blocks</p>
<div class="l-frame">
<iframe title="Art Crime – Blocks" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/SDzs-BPplP0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://dawnrecords.bandcamp.com/album/distanced-dawn011">Grab a copy on Bandcamp</a></p>
<h2 id="jon-hassell---seeing-through-sound-(pentimento-volume-two)" tabindex="-1">Jon Hassell - Seeing Through Sound (Pentimento Volume Two) <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#jon-hassell---seeing-through-sound-(pentimento-volume-two)" aria-hidden="true">#</a></h2>
<p>Fairly amazing leftfield ambient sounds, and even moreso given that the producer is 83 (yes, 83) years old. This is a real trip and deserves the kind of attention which I’ve not generally been able to give it just yet, but the first track alone is worth the admission. The vinyl also sounds amazing. Stunning!</p>
<p><b>Favourite track:</b> Fearless</p>
<div class="l-frame">
<iframe title="Linkwood & Other Lands – Shapes" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/V56TYz3gBBc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://jonhassell.bandcamp.com/album/seeing-through-sound-pentimento-volume-two">Grab a copy on Bandcamp</a></p>
<h2 id="rance-allen-group---reason-to-survive" tabindex="-1">Rance Allen Group - Reason To Survive <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#rance-allen-group---reason-to-survive" aria-hidden="true">#</a></h2>
<p>Shout out to <a href="https://linktr.ee/0ther_Lands">Gav</a> who played this wonderful 1977 Mizell Brothers production (amongst other great music) on his <a href="https://www.ehfm.live/residents/other-lands">Other Lands radio show</a>, as an ode to Mr Allen who recently passed away. Perhaps embarassingly I didn’t know of his music until hearing this, but after grabbing this lovely 2018 reissue on Expansions with its soaring strings and stirring vocals, I’m definitely a convert.</p>
<p><b>Favourite track:</b> Name</p>
<div class="l-frame">
<iframe title="Linkwood & Other Lands – Shapes" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/l7VDC6_KJm4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.juno.co.uk/products/rance-allen-group-reason-to-survive/696650-01/">Grab a copy on Juno</a></p>
<h2 id="deenamic---out-of-my-mind" tabindex="-1">Deenamic - Out Of My Mind <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#deenamic---out-of-my-mind" aria-hidden="true">#</a></h2>
<p>Another cracker heard on Gav’s show, this is new from Italian label Neroli who’ve always ploughed a nice furrow in soulful electronic sounds. This one features a tasty combination of house, broken beat and downtempo flavours.</p>
<p><b>Favourite track:</b> Sambu</p>
<iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=1014917879/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/track=3128915588/transparent=true/" seamless=""><a href="https://nerolirecords.bandcamp.com/album/deenamic-ep-vinyl-only-no-digital-download">Deenamic EP [Vinyl only - no digital download] by NEROLI</a></iframe>
<p><a href="https://www.juno.co.uk/products/deenamic-out-of-my-mind/790619-01/">Grab a copy on Juno</a></p>
<h2 id="tasha-larae-%26-jihad-muhammad---till-you-get-there" tabindex="-1">Tasha Larae & Jihad Muhammad - Till You Get There <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#tasha-larae-%26-jihad-muhammad---till-you-get-there" aria-hidden="true">#</a></h2>
<p>Proper New Jersey style garage from Baltimore’s DJ Spen (ably assisted on remix duties by Bristol’s Sean McCabe) that I could imagine raising the roof at Shelter in NYC or even closer to home at Glasgow’s Melting Pot. It just has that magic formula of slamming beats, gospel chords and a soaring, life-affirming vocal which will never fail to push my buttons. One that if you hear at the right time will make your night, and which makes me long for clubs to reopen.</p>
<p><b>Favourite track:</b> Till You Get There (DJ Spen and Sean McCabe remix)</p>
<div class="l-frame">
<iframe title="Linkwood & Other Lands – Shapes" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/PvXmr-0qIXU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://quantizerecordings.bandcamp.com/album/till-you-get-there-1">Buy (digital-only) from Bandcamp</a></p>
<h2 id="das-ding---your-content-will-arrive-shortly" tabindex="-1">Das Ding - Your Content Will Arrive Shortly <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#das-ding---your-content-will-arrive-shortly" aria-hidden="true">#</a></h2>
<p>My first encounter with Das Ding was his track <a href="https://www.youtube.com/watch?v=HeLUoCSNu_k">H.S.T.A.</a> on the excellent 2012 Stones Throw comp <a href="https://www.discogs.com/Various-The-Minimal-Wave-Tapes-Volume-Two/master/417585">The Minimal Wave Tapes Volume Two</a>. That comp was focused on tracks from the eighties so it’s cool to see that Mr Ding is still releasing music today. These four tracks are electro-based and retain that eighties character with New Beat and EBM influences, but updated with 2020 sounds and production.</p>
<p><b>Favourite track:</b> Category Collapse (Heap Remix)</p>
<div class="l-frame">
<iframe title="Das Ding – Category Collapse (Heap Remix)" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/_3v1SZwgEaY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://mechatronica.bandcamp.com/album/your-content-will-arrive-shortly">Grab a copy on Bandcamp</a></p>
<h2 id="sad-city---images-nov-20" tabindex="-1">Sad City - images-nov-20 <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#sad-city---images-nov-20" aria-hidden="true">#</a></h2>
<p>Two long, atmospheric ambient tracks, self-released (digital-only) by Gary Caruth who I believe resides in Edinburgh (or Glasow; I’m not quite sure). I remember really enjoying his release <a href="https://www.discogs.com/Sad-City-You-Will-Soon-Find-That-Life-Is-Wonderful/release/4483895">You Will Soon Find That Life Is Wonderful</a> in 2013. Anyway – these are very nice, so much so that I listened to them as I feel asleep the other night and I can report that it was quite pleasant!</p>
<p><b>Favourite track:</b> image1</p>
<iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=2086072243/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/transparent=true/" seamless=""><a href="https://musicbysadcity.bandcamp.com/album/images-nov-20">images-nov-20 by Sad City</a></iframe>
<p><a href="https://musicbysadcity.bandcamp.com/">Grab a copy on Bandcamp</a></p>
<h2 id="ando-laj---dog-insight" tabindex="-1">Ando Laj - Dog Insight <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#ando-laj---dog-insight" aria-hidden="true">#</a></h2>
<p>A quirky long-player from a Toronto-based artist who is new to me but seems to have been around since at least 2014. This veers from the grungy ‘n’ glitchy to the ethereal and beautiful and if I’m honest, quality-wise it’s a bit of a mixed bag. However in its best moments, it calls to mind classic IDM from FUSE, The Aphex Twin and The Black Dog… which is never a bad thing.</p>
<p><b>Favourite track:</b> Yukon</p>
<iframe style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=1727123950/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/track=2678063031/transparent=true/" seamless=""><a href="https://andolaj.com/album/dog-insight">Dog Insight by Ando Laj</a></iframe>
<p><a href="https://andolaj.com/album/dog-insight">Grab a copy on Bandcamp</a></p>
<h2 id="linton-kwesi-johnson---bass-culture-%2F-lkj-in-dub" tabindex="-1">Linton Kwesi Johnson - Bass Culture / LKJ In Dub <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#linton-kwesi-johnson---bass-culture-%2F-lkj-in-dub" aria-hidden="true">#</a></h2>
<p>Killer reggae reissue: beaut packaging, lovely red and green vinyl, and sounds tremendous.</p>
<p><b>Favourite track:</b> Inglan is a Bitch</p>
<div class="l-frame">
<iframe title="Linton Kwesi Johnson – Inglan is a Bitch" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oJ4UBztigF0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://honestjons.com/shop/artist/Linton_Kwesi_Johnson/release/Bass_Culture_LKJ_In_Dub">Grab a copy at Honest Jon’s</a></p>
<h2 id="sedgwick---rhythm-and-isolation" tabindex="-1">Sedgwick - Rhythm And Isolation <a class="direct-link" href="https://fuzzylogic.me/posts/autumn-2020-music-purchases/#sedgwick---rhythm-and-isolation" aria-hidden="true">#</a></h2>
<p>Big up <a href="https://twitter.com/jamiethomsonno1">Jamie</a> who brought this one to my attention via a <a href="https://www.mixcloud.com/RadioMagnetic/saturday-manatee-ep-57-jamie-thomson/">great episode of his Saturday Manatee show</a>. There’s a lot of electro around at the moment, and perhaps also a few opportunistic producers and labels jumping on the bandwagon, but this is a good one.</p>
<p><b>Favourite track:</b> Exit</p>
<div class="l-frame">
<iframe title="Sedgwick – Exit" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/IlaY4H84ADg" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.redeyerecords.co.uk/vinyl/126711-phz004-sedgwick-rhythm-and-isolation">Grab a copy at Redeye Records</a></p>
Linkwood & Other Lands – Face the Facts2020-11-27T19:16:29Zhttps://fuzzylogic.me/posts/linkwood-other-lands-%E2%80%93-face-the-facts/<p>Lovely double-vinyl LP that sees three of Auld Reekie’s finest producers and labels join forces. Breezy laid-back jams with smooth keys rub up next to darker, Theo Parrish-eque moments to give it a fine balance. Favourite track: Shapes. <a href="https://aotns.bandcamp.com/album/face-the-facts">Grab a copy on Bandcamp</a> <a href="https://bit.ly/3feSzRP"></a></p>
<div class="l-frame"><iframe title="Linkwood & Other Lands – Shapes" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oCdHPH77b5c" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
Buying, listing and recommending books2020-11-26T21:08:49Zhttps://fuzzylogic.me/posts/buying-logging-and-recommending-books/<p>I currently buy books from a mix of physical and online stores including Waterstones, Hive, Blackwells and most recently, <a href="https://www.theoutwithagency.co.uk/">The Outwith Agency</a> – my new local shop.</p>
<p>I have a <a href="https://fuzzylogic.me/bookshelf/">Bookshelf</a> section of my website which lists a number of books I’ve read, including what I’m currently reading. The idea was very much inspired by <a href="https://daverupert.com/bookshelf/">Dave Rupert’s bookshelf</a>.</p>
<p>On my virtual bookshelf, each book links to a product details page on a third party website so that a visitor can easily buy that book if so inclined. This is a feature which I added without too much deeper thought.</p>
<p>On Dave Rupert’s bookshelf, each book links to its counterpart on Amazon. This is likely for two reasons: firstly, Amazon are likely to have it because they have <em>everything</em>; and secondly, he is enrolled in Amazon’s affiliate scheme, so can make a small commission from each recommendation that leads to a purchase. Makes sense!</p>
<p>Even though I’m not an Amazon affiliate I started by linking to Amazon almost by default, until a few months ago when I began linking to <a href="https://www.hive.co.uk/">Hive</a> instead. Upon hearing that Hive give a small percentage of each sale to an independent book shop I realised I’d rather support that effort than simply boost Amazon’s profits. (Also: Amazon don’t need my money, and I’m not a big fan of their attitude toward privacy).</p>
<p>Earlier this month <a href="https://fuzzylogic.me/posts/2020-11-02-bookshop-this-is-revolutionary-on-the-guardian/">I heard about Bookshop</a> and their MO is even more attractive than Hive’s. They provide “ready-made storefront” functionality for independent bookshops, and when a customer buys from a specific shop that shop is given the <em>full profits</em> of each sale. Alternately customers can buy from the generic Bookstore store too, in which case the profits are evenly distributed among a pool of independent shops.</p>
<p>I think when I buy books online in future, if I’m not buying direct from a shop then I’ll buy from Bookshop.</p>
<p>I’m also going to mention to The Outwith Agency about Bookshop. They don’t currently have an e-commerce store so this could be some low-hanging fruit.</p>
<p>I’ve also enrolled in Bookshop’s <a href="https://uk.bookshop.org/affiliates/profile/introduction">affiliate programme</a> because it’s an attractive proposition:</p>
<blockquote>
<p>We also support anyone who advocates for books through our affiliate programme, which pays a 10% commission on every sale, and gives a matching 10% to independent bookshops.</p>
</blockquote>
<p>Can’t argue with that! It feels like a pretty win-win way to recommend books.</p>
<p>As for my website: I’m now going to link any books I mention to the corresponding product on Bookshelf (I’ve already started with my note on <a href="https://fuzzylogic.me/posts/note-2020-10-25t16-00-58-barack-obama-a-promised-land/">A Promised Land</a>) and see if I can’t take advantage of that affilliate scheme. I’ll need to do a little work, however Bookshop helpfully use a consistent URL structure which includes each book’s ISBN so that should make it easier to template my links and thumbnails.</p>
<p>Footnote: a big thank-you to Adactio’s post <a href="https://adactio.com/journal/17596">Bookshop</a> which is full of great tips and insights on setting up with Bookshop.</p>
Om Unit meets Seekers International – Secret Location2020-11-25T13:05:34Zhttps://fuzzylogic.me/posts/om-unit-meets-seekers-international-%E2%80%93-secret-location/<p>Was excited to hear about this collab, and it doesn’t disappoint. 7 tracks of deep, digi-dub bass, hazy textures and dancehall samples and it sounds amazing. Favourite track: Krnch. <a href="https://bit.ly/33g6xOE">https://bit.ly/33g6xOE</a> </p><div class="l-frame"><iframe title="Om Unit meets Seekers International – Krnch" width="560" height="315" src="https://www.youtube-nocookie.com/embed/3Ys-dGm5Bu4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div><p></p>
New CSS for Styling Underlines on the Web - YouTube2020-11-25T10:30:18Zhttps://fuzzylogic.me/posts/2022-11-25-new-css-for-styling-underlines-on-the-web-youtube/<p>We have new properties in CSS for styling underlines, as explained here by Jen Simmons.</p>
<p>The relevant properties are:</p>
<ul>
<li><code>text-decoration-thickness</code></li>
<li><code>text-decoration-color</code></li>
<li><code>text-underline-offset</code></li>
<li><code>text-decoration-skip-ink</code></li>
</ul>
<p>The skip-ink concept becomes more interesting (to me at least) when you're also using the other properties (especially offset) in order to start the underline higher up the word causing it to appear <em>behind</em> it.</p>
<h2>Update 25th November 2022</h2>
<p><a href="https://caniuse.com/?search=text-underline-offset">Support for these properties looks healthy.</a></p>
Note 2020-10-25T16:00:58: Promised Land by Barack Obama2020-11-24T23:34:30Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-barack-obama-a-promised-land/<p>I’ve started reading <a href="https://uk.bookshop.org/a/4340/9780241491515"><em>A Promised Land</em></a> by Barack Obama.</p>
<figure>
<a href="https://uk.bookshop.org/a/4340/9780241491515">
<img src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1606339531/a-promised-land-barack-obama_t3klf4.png" alt="Charity run for FreeAgent" loading="lazy" width="640" />
</a>
</figure>Note 2020-10-25T16:00:58: Freak Zone on Not For Threes2020-11-22T14:07:37Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-freak-zone-on-not-for-threes/<p>Looking forward to Stuart Maconie’s Freak Zone show on 6Music tonight, talking about Plaid’s Not for Threes LP plus other experimental electronics. <a href="https://bbc.in/3nMeOS5">https://bbc.in/3nMeOS5</a>. <em>Headspin</em> is still killer!</p>
<div class="l-frame"><iframe title="Plaid – Headspin" width="560" height="315" src="https://www.youtube-nocookie.com/embed/72ZAMCzjxrk" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
Various – Buena Onda Balearic Beats2020-11-22T09:33:12Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-various-%E2%80%8E%E2%80%93-buena-onda-balearic-beats/<p>Lovely four-tracker of slow and atmospheric late-night grooves from Italy and elsewhere, as heard on <a href="https://dublab.de/broadcasts/watching-like-nobodys-dancing-din-daa-daa-october-2020/">Denise’s radio show</a>. Favourite track: Lucas Croon – Japon. <a href="https://hellyeahrec.bandcamp.com/album/buena-onda-balearic-beats">Grab a copy on Bandcamp</a></p>
<div class="l-frame"><iframe title="Lucas Croon – Japon" width="560" height="315" src="https://www.youtube-nocookie.com/embed/QVt99311d4A" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
Nat Birchall meets Al Breadwinner – Upright Living LP2020-11-19T20:53:18Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-nat-birchall-%E2%80%93-upright-living/<p>Real nice roots reggae and dub from sunny Manchester. Favourite track: African Village Dance / Village Dub. <a href="https://bit.ly/3feSzRP">https://bit.ly/3feSzRP</a></p>
<div class="l-frame">
<iframe title="Nat Birchall meets Al Breadwinner – Wise Man Style / Dub of the Prophet" width="560" height="315" src="https://www.youtube-nocookie.com/embed/oo35Duhy-8c" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
Choosing between online services2020-11-17T21:53:21Zhttps://fuzzylogic.me/posts/choosing-between-online-services/<p>A <a href="https://tinyletter.com/clearleft/letters/dconstruct-from-clearleft-musique-non-stop">recent issue of the dConstruct newsletter</a> about choosing more ethical online services really chimed with me at a time when I’ve been reflecting on my online habits.</p>
<p><a href="https://clearleft.com/">Clearleft</a> produce an excellent regular technology-based newsletter – <a href="https://tinyletter.com/clearleft">dConstruct</a> – to which I heartily recommend subscribing.</p>
<p>A recent issue compared online services in the <a href="https://www.bbc.co.uk/news/business-389300480">gig economy</a> – such as Uber, Deliveroo and AirBnB – plus music services Spotify and Bandcamp, and considered the relative ethics of each with respect to the extent they exploit the sellers in their “marketplace”. For example, which services let the seller set the price? AirBnB do, and so do Bandcamp. But not so Uber and Spotify.</p>
<p>The success of services like Bandcamp – which is far more profitable to lesser-known producers than the likes of Spotify – show that we don’t need to follow the crowd and can make better choices about the online services we use.</p>
<p>I’ve used Bandcamp more than usual in 2020 because I like the way they are actively supporting artists during a difficult period. I also like the convention that when you buy a vinyl release, the digital is also bundled free.</p>
<p>I’m currently typing this post in a Firefox tab and have been making an effort to switch (back) to it from Chrome, for a less invasive browsing experience.</p>
<p>I use DuckDuckGo rather than Google search when I remember, and have recently made it the default “address bar search” tool in Firefox which should help break old habits.</p>
<p>As for Facebook, Twitter and other time-draining, sometimes harmful social media platforms, well, I’m weaning myself off those and recently <a href="https://fuzzylogic.me/posts/how-i-consume-and-read-rss-feeds/">wrote about how I’m using Feedbin to aggregate news and updates</a>.</p>
<p>I don’t know about you, but I find it helpful to do a periodic health check on how I’m using the internet, and see where I can make better choices.</p>
Breaking Out With CSS Grid Layout (on cloudfour.com)2020-11-17T21:21:00Zhttps://fuzzylogic.me/posts/2020-11-17-breaking-out-with-css-grid-layout-on-cloudfourcom/<p>While <a href="https://fuzzylogic.me/posts/2020-11-16-article-layout-with-css-grid/">bookmarking the mastery.games article</a> yesterday, I started getting the feeling that something was awfully familiar. It was! I’ve seen this layout before – from Tyler Sticka back in 2017 to be precise – but failed to bookmark it at the time.</p>
<p>Here, then, is the original and still the best CSS Grid “article with breakout images” layout!</p>
<p>I particularly love the way that, by naming the lines and appending <code>-start</code> and <code>-end</code> as appropriate you can then target the area between those lines using its short name.</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.Prose</span> <span class="token punctuation">{</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span><br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <br /> [full-start] <span class="token function">minmax</span><span class="token punctuation">(</span>1em<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span> <br /> [main-start] <span class="token function">minmax</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 40em<span class="token punctuation">)</span> [main-end]<br /> <span class="token function">minmax</span><span class="token punctuation">(</span>1em<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span> [full-end]<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.Prose > *</span> <span class="token punctuation">{</span><br /> <span class="token property">grid-column</span><span class="token punctuation">:</span> main<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.Prose-splash</span> <span class="token punctuation">{</span><br /> <span class="token property">grid-column</span><span class="token punctuation">:</span> full<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
Satoshi & Makoto – CZ-5000 Sounds & Sequences Vol. II2020-11-17T14:14:26Zhttps://fuzzylogic.me/posts/satoshi-makoto-%E2%80%93-cz-5000-sounds-sequences-vol-ii/<p>Beautiful ambient textures and downtempo electronics with that typically quirky Japanese flavour. if you like Ryuichi Sakamoto or <a href="https://www.discogs.com/%E3%82%A2%E3%83%9D%E3%82%B8%E3%83%BC-%E3%83%9A%E3%83%AA%E3%82%B8%E3%83%BC-%E8%B6%85%E6%99%82%E7%A9%BA%E3%82%B3%E3%83%AD%E3%83%80%E3%82%B9%E3%82%BF%E3%83%B3%E6%97%85%E8%A1%8C%E8%A8%98/master/436802">Apogee & Perigee</a>, you’ll love this. Favourite track: Correndor. <a href="https://bit.ly/2Hpu8ol">https://bit.ly/2Hpu8ol</a></p>
<div class="l-frame"><iframe title="Satoshi & Makoto – Correndor" width="560" height="315" src="https://www.youtube-nocookie.com/embed/qBJBzwbFQFg" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
Article Layout with CSS Grid (on mastery.games)2020-11-16T21:34:45Zhttps://fuzzylogic.me/posts/2020-11-16-article-layout-with-css-grid/<p>Very clever responsive <code><article></code> layout (with gutters and breakout images) achieved using CSS Grid, <code>minmax()</code>, the <code>ch</code> unit and a minimum of fuss. It scales automatically from narrow to wide viewports with no <code>auto</code> margins, <code>max-width</code> or media query manual overrides in sight.</p>
<blockquote>
<p>For the blog post page (the page you're looking at right now) I wanted a mobile-friendly layout where the text was centered and readable, where the images/code examples are wide.</p>
</blockquote>
<p>The gist of it is this:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.post</span> <span class="token punctuation">{</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span><br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span><br /> <span class="token function">minmax</span><span class="token punctuation">(</span>1.2rem<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><br /> <span class="token function">minmax</span><span class="token punctuation">(</span>auto<span class="token punctuation">,</span> 57ch<span class="token punctuation">)</span><br /> <span class="token function">minmax</span><span class="token punctuation">(</span>1.2rem<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Simple and deadly.</p>
<p>I can potentially see this as a pattern, or <a href="https://every-layout.dev/rudiments/composition/">layout primitive</a>, rather than just as something you might use at the top-level of the page for overall layout. I’m looking forward to trying it out!</p>
<p>(via <a href="https://mastery.games/post/article-grid-layout/">Ahmad Shadeed</a>)</p>
Larry’s Garage2020-11-15T19:31:55Zhttps://fuzzylogic.me/posts/larry%E2%80%99s-garage/<p>I just watched “Larry’s Garage” – a film by Corrada Rizza about the visionary New York DJ, Larry Levan and the legendary nightclub he called home.</p>
<div class="l-frame">
<iframe title="Larry’s Garage – Larry Levan & The Paradise Garage" loading="lazy" width="640" height="360" src="https://player.vimeo.com/video/470933551" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p>Unfortunately there’s generally precious little footage of the infamous New York club and what they included I’d seen before, but there was some nice previously unseen interview footage with Larry Levan and overall, although I wasn’t blown away, I enjoyed it.</p>
Lothian No Borders – Ep 2 – Being & Firecracker Recordings2020-11-14T08:28:08Zhttps://fuzzylogic.me/posts/lothian-no-borders-%E2%80%93-ep-2-%E2%80%93-being-firecracker-recordings/<p>Lovely radio show including an interview with <a href="https://twitter.com/firecracker_rec">@firecracker_rec</a> and mix from <a href="https://twitter.com/WeeDjs">@WeeDjs</a>.</p>
<iframe width="100%" height="120" src="https://www.mixcloud.com/widget/iframe/?hide_cover=1&feed=%2FRadioMagnetic%2Flothian-no-borders-ep-2%2F" frameborder="0"></iframe>
Bookshop: “This is revolutionary” (on The Guardian)2020-11-02T14:24:53Zhttps://fuzzylogic.me/posts/2020-11-02-bookshop-this-is-revolutionary-on-the-guardian/<blockquote>
<p>Bookshop was dreamed up by the writer and co-founder of Literary Hub, Andy Hunter. It allows independent bookshops to create their own virtual shopfront on the site, with the stores receiving the full profit margin – 30% of the cover price – from each sale. All customer service and shipping are handled by Bookshop and its distributor partners, with titles offered at a small discount and delivered within two to three days.</p>
</blockquote>
<p>(via <a href="https://twitter.com/RyanSoulbhoy">@RyanSoulbhoy</a>)</p>
Hijack 003: Jamie Thomson2020-11-01T18:54:03Zhttps://fuzzylogic.me/posts/hijack-003-jamie-thomson/<p>Lovely house mix from my friend Jamie.</p>
<iframe width="100%" height="300" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/911664106&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
<p>Lots of good stuff in here, with plenty I don’t know plus a few classics from Crustation (Mood 11 Swing’s mix of <em>Flame</em>) and Chez ’n’ Trent.</p>
Sean Bean as baked beans can’t be unseen2020-10-25T22:18:39Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-sean-bean-can%E2%80%99t-be-unseen/<p>Genius!</p>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">This AI style transfer of sean bean and beans in tomato sauce killed me<br />(Source: <a href="https://t.co/dYufbtL2w1">https://t.co/dYufbtL2w1</a>) <a href="https://t.co/WBfOzuzP0L">pic.twitter.com/WBfOzuzP0L</a></p>— Age of Calamityville 🐱ri-Warui (@oleivarrudi) <a href="https://twitter.com/oleivarrudi/status/1319964618534637568?ref_src=twsrc%5Etfw">October 24, 2020</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure>
Note 2020-10-25T16:00:58: 6K run for FreeAgent’s Big Strides charity campaign2020-10-25T16:00:44Zhttps://fuzzylogic.me/posts/note-2020-10-25t16-00-58-6k-run-for-freeagent/<p>Just finished my 6K run for FreeAgent’s “Big Strides for Tiny Changes” charity campaign.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1604167985/Larry_sRun_oil4hj.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1604167985/Larry_sRun_oil4hj.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1604167985/Larry_sRun_oil4hj.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1604167985/Larry_sRun_oil4hj.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1604167985/Larry_sRun_oil4hj.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1604167985/Larry_sRun_oil4hj.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1604167985/Larry_sRun_oil4hj.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1604167985/Larry_sRun_oil4hj.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1604167985/Larry_sRun_oil4hj.jpg" width="320" height="240" alt="Charity run for FreeAgent" loading="lazy" decoding="async" />
<figcaption>Photo by Clair Irwin</figcaption>
</figure>
Minimalist Container Queries2020-10-24T21:05:05Zhttps://fuzzylogic.me/posts/2021-01-24-minimalist-container-queries/<p>Scott Jehl’s experimental take on a container/element query aimed at letting us set responsive styles for our elements based on their immediate context rather than that of the viewport.</p>
<blockquote>
<p>I made a quick and minimal take on approximating Container/Element Queries using a web component and basic CSS selectors.</p>
</blockquote>
<p>The idea is that for any given instance of the <code><c-q></code> custom element / web component you would define a scoped custom property which sets the pixel min-widths you’re interested in, like so:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">c-q</span> <span class="token punctuation">{</span><br /> <span class="token property">--breakpoints</span><span class="token punctuation">:</span> <span class="token string">"400 600 800"</span><span class="token punctuation">;</span><br /> <span class="token property">background</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Zero to many of those numeric <code>min-width</code> values will appear in the element’s <code>data-min-width</code> HTML attribute based on which (if any) of them the element’s width is equal to or greater than.</p>
<p>You can style the element based on their presence using the <code>~=</code> attribute selector, like this:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">c-q[data-min-width~="400"]</span> <span class="token punctuation">{</span> <br /> <span class="token property">background</span><span class="token punctuation">:</span> green<span class="token punctuation">;</span> <br /><span class="token punctuation">}</span><br /><span class="token selector">c-q[data-min-width~="600"]</span> <span class="token punctuation">{</span><br /> <span class="token property">background</span><span class="token punctuation">:</span> blue<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>See also <a href="https://twitter.com/scottjehl/status/1319724488339214336">Scott’s tweet announcing this</a> which contains some interesting contributions including <a href="https://github.com/Heydon/watched-box">Heydon’s watched-box</a>.</p>
<p>All of the various JavaScript approaches/experiments are summarised in CSS-Tricks’s article <a href="https://css-tricks.com/minimal-takes-on-faking-container-queries/"><em>Minimal Takes on Faking Container Queries</em></a>.</p>
<p>(via <a href="https://twitter.com/scottjehl">@scottjehl</a>)</p>
How-to: Create accessible forms - The A11Y Project2020-10-24T17:44:05Zhttps://fuzzylogic.me/posts/2021-01-24-howto-create-accessible-forms-the-a11y-project/<p>Here are five bite-sized and practical chunks of advice for creating accessible forms.</p>
<ol>
<li>Always label your inputs.</li>
<li>Highlight input elements on focus.</li>
<li>Break long forms into smaller sections/pages.</li>
<li>Provide error messages (rather than just colour-based indicators)</li>
<li>Avoid horizontal layout forms unless necessary.</li>
</ol>
<p>I already apply some of these principles, but even within those I found some interesting takeaways. For example, the article advises that when labelling your inputs it’s better not to nest the input within a <code><label></code> because some assistive technologies (such as Dragon NaturallySpeaking) don’t support it.</p>
<p>I particularly like the idea of using CSS to make the input which has focus more obvious than it would be by relying solely on the text cursor (or <em>caret</em>).</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">input:focus</span> <span class="token punctuation">{</span><br /> <span class="token property">outline</span><span class="token punctuation">:</span> 2px solid royalblue<span class="token punctuation">;</span><br /> <span class="token property">box-shadow</span><span class="token punctuation">:</span> 1px 1px 8px 1px royalblue<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>(via <a href="https://twitter.com/adactio">@adactio</a>)</p>
Sets in JavaScript2020-10-24T16:00:42Zhttps://fuzzylogic.me/posts/sets-in-javascript/<p>I don’t often store things in a <code>Set</code> in JavaScript, but maybe I should. The fact it will only store <em>unique values</em> makes it pretty handy.</p>
<p>One place I do currently use a <code>Set</code> is for the <code>TagList</code> in my 11ty-based personal website. I start by defining <code>TagList</code> as a new, empty <code>Set</code>. I then need to assemble all possible tags so iterate blog posts and for each add its associated tags to <code>TagList</code>. This means I can be sure that all duplicates will be removed automatically.</p>
<p>As you would imagine, <code>Set</code> has built-in methods for adding, deleting and iterating items. But if you need to do something beyond that, you can easily turn it into an array, for example by:</p>
<figure>
<pre><code>const myArray = [...mySet];
</code></pre>
</figure>
<p>Also, <a href="https://caniuse.com/?search=javascript%20set">browser support is pretty good</a>. So although to date I’ve been safely confining my use to Node scripts for building my static site, I could probably be using it client-side, too.</p>
Docsify – a magical Documentation Website generator2020-10-22T19:25:16Zhttps://fuzzylogic.me/posts/docsify-%E2%80%93-a-magical-documentation-site-generator/<blockquote>
<p>docsify generates your documentation website on the fly. Unlike GitBook, it does not generate static html files. Instead, it smartly loads and parses your Markdown files and displays them as a website.</p>
</blockquote>
<p>I just completed a training workshop where the course notes were provided in a website created using this software (and hosted on Netlify), and was really impressed.</p>
The Atkinson Hyperlegible Font (Braille Institute)2020-10-22T13:23:37Zhttps://fuzzylogic.me/posts/the-atkinson-hyperlegible-font-braille-institute/<p>Braille Institute launch a new, free typeface promising greater legibility and readability for low vision readers.</p>
<blockquote>
<p>What makes it different from traditional typography design is that it focuses on letterform distinction to increase character recognition, ultimately improving readability.</p>
</blockquote>
<p>via <a href="https://twitter.com/brucel">@brucel</a></p>
Cheating Entropy with Native Web Technologies (on Jim Nielsen’s Weblog)2020-10-15T18:09:51Zhttps://fuzzylogic.me/posts/2021-01-16-cheating-entropy-with-native-web-technologies-on-jim-nielsens-weblog/<blockquote>
<p>This is why, over years of building for the web, I have learned that I can significantly cut down on the entropy my future self will have to face by authoring web projects in vanilla HTML, CSS, and JS. I like to ask myself questions like:</p>
<ul>
<li>Could this be done with native ES modules instead of using a bundler?</li>
<li>Could I do this with DOM scripting instead of using a JS framework?</li>
<li>Could I author this in CSS instead of choosing a preprocessor?</li>
</ul>
</blockquote>
<p>Fantastic post from Jim Neilson about how your future self will thank you if you keep your technology stack simple now.</p>
<p>(via <a href="https://twitter.com/adactio">@adactio</a>)</p>
Northern Road Trip, September 20202020-10-10T07:30:00Zhttps://fuzzylogic.me/posts/northern-road-trip-2020/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1601734993/IMG_2723_wa3cmm.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1601734993/IMG_2723_wa3cmm.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1601734993/IMG_2723_wa3cmm.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1601734993/IMG_2723_wa3cmm.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1601734993/IMG_2723_wa3cmm.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1601734993/IMG_2723_wa3cmm.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1601734993/IMG_2723_wa3cmm.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1601734993/IMG_2723_wa3cmm.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1601734993/IMG_2723_wa3cmm.jpg" width="386" height="290" alt="Laurence, Clair and Rudy at the Cluanie Inn, Glenmoriston, in September 2020" loading="lazy" decoding="async" />
<figcaption>Laurence, Clair and Rudy at the Cluanie Inn, Glenmoriston, in September 2020</figcaption>
</figure>
<p><em>Note: as I type this three weeks later, we’re about to re-enter tighter Covid restrictions, so I feel grateful to have had the opportunity for a much-needed change of scenery when we did, as it wouldn’t be possible now. I’m also thankful to everywhere we stayed for their care in taking appropriate precautions for their guests and generally for keeping going under trying circumstances.</em></p>
<p>In 2020 it's been pretty difficult to holiday abroad for two reasons: firstly, the small matter of a global pandemic; and secondly, the arrival of our Border Terrier puppy, Rudy. So we decided to make the most of our beautiful homeland, Scotland, and go on a road trip.</p>
<p>The plan was straightforward: we’d head primarily up the west coast, taking in new places and familiar favourites; we’d enjoy some “first holiday” fun with our furry pal; and over five nights we’d eat ourselves into a seafood-induced coma.</p>
<p>In reality, organising this holiday was trickier than we were used to, due to it being our first time searching for pet-friendly accommodation, a challenge which was compounded by many venues running at lower capacity due to covid considerations. However with the help of some great recommendations from friends, we found a handful of suitable spots.</p>
<p>In the end it worked out perfectly, and was a lovely way for us to celebrate our fourth wedding anniversary. Here’s the lowdown.</p>
<h2 id="monday" tabindex="-1">Monday <a class="direct-link" href="https://fuzzylogic.me/posts/northern-road-trip-2020/#monday" aria-hidden="true">#</a></h2>
<p>Following a quick stop to collect our hire car, we set off for Connel, near Oban.</p>
<p>The weather was decent, and there were early signs that Rudy would be a happy traveller. In fact we needed only one brief stop during the two and a half hour drive; at lovely Luss for a breath of fresh air and some shits and giggles (mainly shits).</p>
<p>By mid-afternoon we had arrived at our destination, <a href="http://www.oysterinn.co.uk/">The Oyster Inn</a>, taken a moment to admire the view over Loch Etive, then donned our Covid masks to check-in and ditch our bags.</p>
<p>We made the 10 minute drive into Oban then enjoyed a saunter around the shops overlooking the bay, stopping to eat scallops at the harbourside <a href="https://www.tripadvisor.co.uk/Restaurant_Review-g186501-d2091037-Reviews-Oban_Seafood_Hut-Oban_Argyll_and_Bute_Scotland.html">Green Shack Seafood Hut</a>. Aside from Rudy trying to eat <em>everything</em> on the ground around us, this was magic.</p>
<p>Later that night we ate dinner in <a href="http://www.oysterinn.co.uk/glue-pot.html">The Glue Pot</a>, our hotel bar-restaurant – Fish Pie and a beer for me, Scampi and a glass of wine for Clair. Good pub fare all round. The holiday was off to a fine start!</p>
<h2 id="tuesday" tabindex="-1">Tuesday <a class="direct-link" href="https://fuzzylogic.me/posts/northern-road-trip-2020/#tuesday" aria-hidden="true">#</a></h2>
<p>We started the day with breakfast in the hotel and it was a good’un: Clair opted for a “full Scottish”, and I had Eggs Royal (poached eggs, salmon, spinach, hollandaise sauce). With black clouds gathering ominously outside, this was exactly the kind of tasty fuel we needed.</p>
<p>We headed for <a href="https://www.visitscotland.com/info/towns-villages/ganavan-sands-p315601">Ganavan Sands</a> and on arrival it was raining pretty heavily. However every cloud has a silver lining as this gave Rudy a chance to strut his stuff in his new Hi-Vis, waterproof jacket. We played fetch for a wee while and he had his first experience of paddling in the sea.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1601818757/IMG_1288_zrcnox.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1601818757/IMG_1288_zrcnox.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1601818757/IMG_1288_zrcnox.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1601818757/IMG_1288_zrcnox.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1601818757/IMG_1288_zrcnox.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1601818757/IMG_1288_zrcnox.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1601818757/IMG_1288_zrcnox.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1601818757/IMG_1288_zrcnox.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1601818757/IMG_1288_zrcnox.jpg" width="320" height="240" alt="Rudy on Ganavan Sands" loading="lazy" decoding="async" />
<figcaption>Rudy on Ganavan Sands, Oban</figcaption>
</figure>
<p>With our drookit dug in tow, we left for local historic attraction <a href="https://www.visitscotland.com/info/see-do/mccaigs-tower-p255141">McCaig’s Tower</a>, although when it became apparent that the final climb would be on foot in the rain we axed that plan, like the amateur adventurers we are. Instead we parked up in Oban and began hunting for lunch, while the rain continued unabated.</p>
<p>Frustratingly it was slim pickings for pet-friendly eateries and we endured a couple of knock-backs. Finally, after some frozen-fingered Googling, we found <a href="https://markiedans.co.uk/">Markie Dan’s</a>, like a pooch-friendly oasis in the desert. Clair ate fish and chips (which was dynamite) while I had chicken and rice soup and a smoked haddock and mozarella fish cake, washed down with a tasty local beer. Big up Markie Dan’s for saving the day! (And shout out to their toilets for unexpected X-rated vending machine weirdness.)</p>
<p>Sidenote: this wee lunchtime challenge prompted me to consider restarting a side-project I’d previously put on ice. The idea is an online directory of quality child and pet-friendly bars, restaurants and accommodation which – if you give it your current location – would list the places nearest to you. That would’ve been handy that day. Maybe someday I’ll get around to it.</p>
<p>With happy bellies we retired to the hotel for a rest, before it was time to head to Port Appin for dinner at the <a href="https://www.pierhousehotel.co.uk/about/hotel/whos-who">Pierhouse Hotel</a>. Our pal <a href="https://twitter.com/missfionamclean">Fiona</a> is General Manager there and it had been on our visit-list for ages.</p>
<p>Despite bringing a canine companion we were graciously accommodated (thanks, David), although as it became clear how posh our surroundings were, we secretly began praying that the tiny terrier would be on his best behaviour.</p>
<p>The Pierhouse is beautifully located and the restaurant certainly lived up to its reputation.</p>
<p>For starters and mains we had:</p>
<ul>
<li>smoked salmon on cripy salmon skin;</li>
<li>breaded oysters with squid ink mayo;</li>
<li>a seafood platter;</li>
<li>lemon sole; and on the side…</li>
<li>samphire; and</li>
<li>chips (obvs)</li>
</ul>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1602318006/IMG_1299_uqvmoc.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1602318006/IMG_1299_uqvmoc.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1602318006/IMG_1299_uqvmoc.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1602318006/IMG_1299_uqvmoc.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1602318006/IMG_1299_uqvmoc.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1602318006/IMG_1299_uqvmoc.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1602318006/IMG_1299_uqvmoc.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1602318006/IMG_1299_uqvmoc.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1602318006/IMG_1299_uqvmoc.jpg" width="320" height="240" alt="Seafood Platter at The Pierhouse Hotel" loading="lazy" decoding="async" />
<figcaption>Seafood Platter at The Pierhouse Hotel</figcaption>
</figure>
<p>For dessert, Clair had the burnt cream, while I had their signature orange chocolate cremeux with buckthorn sorbet. (NB: despite the cast of other amazing dishes I’ve still to mention, as I look back on the overall trip I’m moved to award this dessert “Dish of the Holiday” – it really was off-the-scale!)</p>
<p>While dining, Rudy (who was stashed away under our table) was a bit of handful. In COVID-times, Scottish venues have no background music and are sparser than usual, so we were on high alert to catch any unacceptable doggy behaviours before they happened and marked us out as “the pain in the ass couple with the dog”. Fortunately, aside from a bit of potted plant nibbling and numerous escape attempts he didn’t do anything too visibly embarassing, although keeping one hand on him while trying to eat a plate of seafood was a bit like The Krypton Factor.</p>
<p>As we finished our meal, Fiona arrived to greet us and ushered us into “The Snug” for a whisky to cap the night (a Balvenie Port cask, and it fairly warmed the cockles.)</p>
<p>Fiona and crew are doing great things at The Pierhouse. It was lovely to catch up and a brilliant night overall.</p>
<h2 id="wednesday" tabindex="-1">Wednesday <a class="direct-link" href="https://fuzzylogic.me/posts/northern-road-trip-2020/#wednesday" aria-hidden="true">#</a></h2>
<p>We had time for one more breakfast at The Oyster Inn before leaving, and once again it hit the target. Clair went for the veggie scottish breakfast, while I had scrambled eggs and smoked salmon.</p>
<p>Our next stop was Glenmoriston, but before leaving Oban we had important matters to address. Following last night’s challenges with Rudy we resolved to find some superior chew-chews to keep him occupied during the remaining meal-times, so stopped in at a wee Pet Shop we’d noticed in town the previous day.</p>
<p>Enter <em>Dynorod</em> (not real name) – a stick of “Himilayan Yak Milk” that would usher in a zen-like mealtime peace we had hitherto thought impossible.</p>
<p>Tooled up and ready, we embarked on the most amazing sunshine drive from Oban to Kentallen (stopping at the <a href="https://hollytreehotel.co.uk/">Holly Tree Hotel</a> for a great burger and walk along the pier) then through Ballachulish to Fort William. We’d travelled this route many times before, but this time the scenery looked even more incredible (especially just around Ballachulish). It was Scotland at its bonniest.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1602318984/IMG_1297_cvb6ze.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1602318984/IMG_1297_cvb6ze.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1602318984/IMG_1297_cvb6ze.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1602318984/IMG_1297_cvb6ze.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1602318984/IMG_1297_cvb6ze.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1602318984/IMG_1297_cvb6ze.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1602318984/IMG_1297_cvb6ze.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1602318984/IMG_1297_cvb6ze.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1602318984/IMG_1297_cvb6ze.jpg" width="320" height="240" alt="Scenery on the drive from Oban to Ullapool" loading="lazy" decoding="async" />
<figcaption>Scenery on the drive from Oban to Ullapool</figcaption>
</figure>
<p>We then climbed over 1200 feet through the hills before settling at our destination, <a href="https://www.blacksheephotels.com/cluanie-inn-home/">The Cluanie Inn</a>. I can’t over-emphasise this: this location is stunning. You are literally right in the middle of the hills, with deer roaming free around you.</p>
<p>Spotting trestle tables behind the hotel we decided to check-in quickly then enjoy the last of the day’s sunshine with an al fresco beer. Unfortunately by the time I had returned with said beers, Clair was engaged in a battle of wills with the wee fella, who was going stir-crazy with all the space he found himself in. By relentlessly eating deer jobbies he kinda shattered our picture-perfect “beer in the hills” moment, but still, the thought was there…</p>
<p>That night we enjoyed a lovely dinner: I went for South Indian Garlic Chicken (the owners are Indian, so it seemed like a good time to change tack from seafood) while Clair had a roast pork stir fry. For desert we shared a Rhubarb and Apple Crumble with ice cream. Before bed we had a whisky and a game of Connect 4 in the lounge, while Rudy munched on <em>Dynorod</em>. Bliss.</p>
<h2 id="thursday" tabindex="-1">Thursday <a class="direct-link" href="https://fuzzylogic.me/posts/northern-road-trip-2020/#thursday" aria-hidden="true">#</a></h2>
<p>Breakfast at the Cluanie was great. Clair scratched a nostalgia itch with a bowl of Coco Pops, followed by a full Scottish. I had yogurt and muesli then scrambled eggs on toast.</p>
<p>Our next stop was Ullapool, way up north beyond Skye. Clair was really excited about this leg of the trip because she’d be reunited with <a href="https://www.seafoodshack.co.uk/">The Seafood Shack</a> and its owners, having enjoyed visiting earlier in the year as food photographer for <a href="https://www.kitchenpress.co.uk/portfolio-item/the-seafood-shack-food-tales-from-ullapool/">their forthcoming recipe book</a>.</p>
<p>The drive from Glenmoriston to Ullapool was beautiful, too, and sountracked perfectly by Clair’s “Alternative 80s” mixtape (taking in Television, Echo and The Bunnymen, Cocteau Twins) followed by our friend Andy’s excellent <a href="https://open.spotify.com/playlist/1cR2YZGpu7ZdDDf6Y5y8qh?si=GASKD91gQJyNwBMrpL5fsg"><em>Go mild in the country</em> playlist</a>. Good times!</p>
<p>Arriving in Ullapool we made a beeline for The Seafood Shack and on arrival ordered 2 × Haddock Wrap (which Clair had been raving about for months). They were delicious. This gave us the necessary fuel to walk the Ullapool Hill Path which on a clear day such as it was offers fantastic views over the village, Loch Broom and the mountains beyond.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1602318308/IMG_1305_oy3f7h.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1602318308/IMG_1305_oy3f7h.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1602318308/IMG_1305_oy3f7h.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1602318308/IMG_1305_oy3f7h.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1602318308/IMG_1305_oy3f7h.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1602318308/IMG_1305_oy3f7h.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1602318308/IMG_1305_oy3f7h.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1602318308/IMG_1305_oy3f7h.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1602318308/IMG_1305_oy3f7h.jpg" width="320" height="240" alt="Haddock Wrap at The Seafood Shack, Ullapool" loading="lazy" decoding="async" />
<figcaption>Haddock Wrap at The Seafood Shack, Ullapool</figcaption>
</figure>
<p>Back in the village we stopped back in at The Seafood Shack for Cullen Skink and Langoustines before it was time to check in to our home for the night, <a href="https://www.theceilidhplace.com/">The Ceilidh Place</a>. This hotel had been recommended by three separate friends and from the warm welcome (for both us and Rudy) and the lovely, cosy vibe, we could see straight away why people love it.</p>
<p>After check-in we had just enough time for a drink in their beer garden and a quick rummage around their bookshop before it was a time for a nap (this holiday business is pretty tiring…)</p>
<p>Later we headed to the hotel bar for a lovely dinner of Venison Stew (for me) and Fish and Chips (for Clair), sharing home-made baked cheesecake with berries for dessert. We chatted about some of our all-time favourite “long tracks” – Clair offering The Doors’ <em>Riders on the Storm</em> (no arguments from me) while I chipped in The Temptations’ classic <em>Papa was a Rolling Stone</em>.</p>
<p>Today was our wedding anniversary, and it had been nigh-on perfect.</p>
<h2 id="friday" tabindex="-1">Friday <a class="direct-link" href="https://fuzzylogic.me/posts/northern-road-trip-2020/#friday" aria-hidden="true">#</a></h2>
<p>Following a hearty breakfast (porridge for me; cooked breakfast for Clair) we had a wander around Ullapool. This was my first time visiting and I really liked the place. It’s a lovely, picturesque harbour village and, although fairly small, has plenty of good shops, great local food and drink, and friendly people of all ages.</p>
<p>Although you might think that visiting The Seafood Shack for a third time within twenty hours was bordering on the ridiculous, we popped our head in yet again for a farewell lunch. Clair had spineys (squat lobster) while I had mackeral paté with oatcakes. It was fantastic, yet again. What can I say – these folks really know their fish.</p>
<p>After vowing to come back to Ullapool again soon, we set off for Craigellachie, the final stop on our tour.</p>
<p>This was another enjoyable drive, alternating between countryside and busier roads and taking in not one but two football stadia: The Tulloch Stadium, home of Inverness Caley Thistle; and Mosset Park, home of the mighty Forres Mechanics. Sean Keveney’s 6 Music show was on the radio, and by pure coincidence the <em>Uncle Frank’s Friday Floor Fillers</em> section featured “Papa was a Rolling Stone” – which was every bit as good (and long) as I remembered it.</p>
<p>As we entered Moray Speyside we were deep within Malt Whisky country, and as fans of a dram it was exciting to pass one well-known distillery after another: Aberlour, Glenlivet, Cragganmore, Balvenie, Macallan, and more.</p>
<p>By 4:00 <abbr class="time" title="post meridiem">pm</abbr> we arrived at our destination, <a href="http://www.craigellachiehotel.co.uk/">The Craigellachie Hotel</a>.</p>
<p>This place is great! It was definitely the poshest of our trip. It’s in a beautiful countryside location, has a lovely reception area and comfortable rooms, and an amazing bar-restaurant, <em>The Copper Dog</em>.</p>
<p>That night we had probably our favourite dinner of the holiday. For starter, Clair chose scallops with cauliflower pureé while I had haggis bon-bons in a home-made brown sauce. For our mains, Clair had their fish special: cod with sweetcorn and crab, with a side of mac and cheese. I dediced to push the boat out for our last night and had a ribeye steak. Every dish was amazing and unsurprisingly we had zero room for dessert.</p>
<p>To wash it down I had a <a href="http://www.speyvalleybrewery.co.uk/beers/1814-lager/index.html">Spey Valley 1814</a> lager then a <a href="https://windsweptbrewing.com/beer/apa/">Windswept APA</a>. Both local and great. Clair had an Edinburgh gin.</p>
<p>A special shout out to the staff in the Copper Dog; they were all super-friendly and great with Rudy, including director Kevin who came over to chat before finding us a wee post-dinner table at The Quaich, their upstairs whisky bar. It would have been rude not to, so we retired there for a wee dram. With over 900 whiskies from around the world on offer it was tough to choose, but with Rudy getting tired and threatening to drag the family name through the mud in such a plush environment, we made it quick and I grabbed an Aberlour 12 (which I love) while Clair had a Glenrothes. This is a room you could definitely spend some time in, though!</p>
<h2 id="saturday" tabindex="-1">Saturday <a class="direct-link" href="https://fuzzylogic.me/posts/northern-road-trip-2020/#saturday" aria-hidden="true">#</a></h2>
<p>It was time to head home.</p>
<p>After a lovely breakfast at The Craigellachie, we made a brief stop at the nearby Aberlour distillery where I nipped into the shop to pick up a bottle of the same drop I’d had the previous night, with a wee branded glass as a souvenir.</p>
<p>We arrived home happy. It’s great to know you can have such an amazing holiday on your doorstep.</p>
<p>Thanks again to all the friends who provided recommendations.</p>
How to hide elements on a web page2020-10-08T10:58:00Zhttps://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/<p>In order to code modern component designs we often need to hide then reveal elements. At other times we want to provide content to one type of user but hide it from another because it’s not relevant to their mode of browsing. In all cases accessibility should be front and centre in our thoughts. Here’s my approach, heavily inspired by Scott O’Hara’s definitive guide <a href="https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html">Inclusively Hidden</a>.</p>
<p>Firstly, <em>avoid</em> the need to hide stuff. With a bit more thought and by using existing fit-for-purpose HTML tools, we can perhaps create a single user interface and experience that works for all. That approach not only feels like a more equal experience for everyone but also removes margin for error and code maintenance overhead.</p>
<p>With that said, hiding is sometimes necessary and here are the most common categories:</p>
<ol>
<li>Hide from everyone</li>
<li>Hide visually (i.e. from sighted people)</li>
<li>Hide from Assistive Technologies (such as screen readers)</li>
</ol>
<h2 id="hide-from-everyone" tabindex="-1">Hide from everyone <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/#hide-from-everyone" aria-hidden="true">#</a></h2>
<p>We usually hide an element from everyone because the hidden element forms part of a component’s interface design. Typical examples are tab panels, off-screen navigation, and modal dialogues that are initially hidden until an event occurs which should bring them into view. Initially these elements should be <em>inaccessible</em> to everyone but after the trigger event, they become accessible to everyone.</p>
<p>Implementation involves using JavaScript to toggle an HTML attribute or class on the relevant element.</p>
<p>For basic, non-animated show-and-hide interactions you can either:</p>
<ol>
<li>toggle a class which applies <code>display: none</code> in CSS; or</li>
<li>toggle the boolean <code>hidden</code> attribute, which has the same effect but is native to HTML5.</li>
</ol>
<p>Both options work well but for me using the <code>hidden</code> attribute feels a little simpler and more purposeful. My approach is to ensure resilience by making the content available in the first instance in case JavaScript should fail. Then, per <a href="https://inclusive-components.design/tabbed-interfaces/">Inclusive Components’ Tabs example</a>, JavaScript applies both the “first hide” and all subsequent toggling.</p>
<p>Here’s some CSS that supports both methods. (The <code>hidden</code> attribute doesn’t strictly need this but it’s handy to regard both options as high-specifity, “trump-everything-else” overrides.)</p>
<figure>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.u-hidden-from-everyone, <br />[hidden] </span><span class="token punctuation">{</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> none <span class="token important">!important</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>For cases where you are animating or sliding the hidden content into view, toggle the application of CSS <code>visibility: hidden</code> because this also removes the element from the accessibility tree but unlike <code>display</code>, can be animated. Note that with <code>visibility: hidden</code> the physical space occupied by the element is still retained, therefore it’s best to pair it with <code>position: absolute</code> or <code>max-height: 0px; overflow: hidden</code> to prevent that “empty space while hidden” effect. For example:</p>
<figure>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.off-canvas-menu </span><span class="token punctuation">{</span><br /> <span class="token property">visibility</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translateX</span><span class="token punctuation">(</span>-8em<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">transition</span><span class="token punctuation">:</span> 250ms ease-in<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token selector">[aria-expanded="true"] + off-canvas-menu </span><span class="token punctuation">{</span><br /> <span class="token property">visibility</span><span class="token punctuation">:</span> visible<span class="token punctuation">;</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translateX</span><span class="token punctuation">(</span>0<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">transition</span><span class="token punctuation">:</span> visibility 50ms<span class="token punctuation">,</span> transform 250ms ease-out<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<h2 id="hide-visually-(i.e.-from-sighted-people)" tabindex="-1">Hide visually (i.e. from sighted people) <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/#hide-visually-(i.e.-from-sighted-people)" aria-hidden="true">#</a></h2>
<p>We’ll usually want to hide something visually (only) when its purpose is solely to provide extra context to Assistive Technologies. An example would be appending additional, visually-hidden text to a “Read more” link such as “about Joe Biden” since that would be beneficial to screen reader users.</p>
<p>We can achieve this with a <code>visually-hidden</code> class in CSS and by applying that class to our element.</p>
<figure>
<pre class="language-scss"><code class="language-scss">.<span class="token property">visually-hidden</span><span class="token punctuation">:</span><span class="token function">not</span><span class="token punctuation">(</span><span class="token punctuation">:</span>focus<span class="token punctuation">)</span><span class="token punctuation">:</span><span class="token function">not</span><span class="token punctuation">(</span><span class="token punctuation">:</span>active<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token property">clip</span><span class="token punctuation">:</span> <span class="token function">rect</span><span class="token punctuation">(</span>0 0 0 0<span class="token punctuation">)</span><span class="token punctuation">;</span> <br /> <span class="token property">clip-path</span><span class="token punctuation">:</span> <span class="token function">inset</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span><br /> <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span><br /> <span class="token property">white-space</span><span class="token punctuation">:</span> nowrap<span class="token punctuation">;</span> <br /> <span class="token property">width</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Essentially this hides whatever it’s applied to unless it’s a focusable element currently being focused by screen reader controls or the tab key, in which case it is revealed.</p>
<p>Note that if adding to link text to make it more accessible, always <em>append</em> rather than inserting words into the middle of the existing text. That way, you avoid solving an accessibility for one group but creating another for another group (Dragon speech recognition software users).</p>
<h3 id="visually-hidden-until-focused" tabindex="-1">Visually hidden until focused <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/#visually-hidden-until-focused" aria-hidden="true">#</a></h3>
<p>There are other CSS approaches to hiding visually. One approach is to not only add <code>position: absolute</code> (removing the element from the document flow) but also position it off-screen with <code>left: -100vw</code> or similar. The use case for this approach might be when you want your visually hidden element to support being revealed and for that reveal to occur via a transition/animation from off-screen into the viewport. See <a href="https://codepen.io/scottohara/pen/QKmWJG">Scott O’Hara’s off screen skip-links example</a>.</p>
<h2 id="hide-from-assistive-technologies-(such-as-screen-readers)" tabindex="-1">Hide from Assistive Technologies (such as screen readers) <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/#hide-from-assistive-technologies-(such-as-screen-readers)" aria-hidden="true">#</a></h2>
<p>We sometimes hide <em>visual elements</em> from Assistive Technologies because they are decorative and have accompanying text, for example a “warning” icon with the text “warning” alongside. If we did not intervene then Assistive Technologies would read out “warning” twice which is redundant.</p>
<p>To achieve this we can apply <code>aria-hidden="true"</code> to our element so that screen readers know to ignore it. In the following examples we hide the SVG icons within buttons and links, safe in the knowledge that the included “Search” text is providing each interactive element with its <em>accessible name</em>.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!--...--></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /> Search<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!--...--></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /> Search<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>Reference: <a href="https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html">Contextually Marking up accessible images and SVGs</a></p>
How I read the web2020-10-06T20:40:00Zhttps://fuzzylogic.me/posts/how-i-consume-and-read-rss-feeds/<p>I’m currently interested in how to spend less time on social media platforms so as to be less exposed to ads, algorithms and general ill-effects. One approach I’m trialling is going back to the old school and using <a href="https://en.wikipedia.org/wiki/RSS">RSS</a> to receive and aggregate updates from the people I follow, allowing me to read them in a central, noise-free place and not have to use social platform websites and apps.</p>
<p>I use the free, open source Mac and iOS app <a href="https://ranchero.com/netnewswire/">NetNewsWire</a> on my MacBook. This is where I tend to add and organise my RSS feeds as it has a good UI, for example for arranging feeds into suitable folders.</p>
<p>If I want to read new items away from my Mac (on my phone, or on another computer), I use <a href="https://feedbin.com/">Feedbin</a> – either the website or the iOS app. NewsNetWire and Feedbin sync pretty seemlessly so any organisation I’ve done in NetNewsWire is visible in Feedbin.</p>
<p>Feedbin is paid (I currently pay 5 USD per month). It has a slick UI and, since it’s a website accessible from anywhere, could be treated as your “central hub” for reading.</p>
<p>Feedbin also offers a few very interesting features.</p>
<ul>
<li>You can use it to subscribe to email newsletters, because it provides you with an email address for that purpose. This means you can have your newsletters arrive into the same central place as your RSS feeds;</li>
<li>You can subscribe to Twitter accounts, and choose to filter tweets by only those with links or media attached (in theory the “more interesting” tweets);</li>
<li>there’s a “Send to Feedbin” bookmarklet that essentially provides a one-click “Read later” function for use when browsing the web. This is a really handy feature because sometimes when I’m browsing I want to mark an article as “read later” rather than bookmarking it on my website, because until I’ve read it I won’t know if it’s bookmark-worthy. Having this feature destresses online life a little by stopping me leaving lots of browser tabs open at articles I “need to read”! I previously used Instapaper (and their bookmarklet) for this function, but again, it makes sense for me to bring everything into one place (Feedbin);</li>
<li>You can “star” (i.e. save) items you’ve read but want to revisit, which is handy when browsing your “Unread” list on the move; and</li>
<li>You can “share” items to well-known services (Twitter, Facebook etc) but interestingly also to a “custom service” by providing a URL. I could see me using this in future to bookmark an article on my own website.</li>
</ul>
<p>I’m also currently trialling <a href="https://rss.app/">RSS.app</a> for its ability to let me type in an Instagram user profile URL then give me back an RSS feed URL which I can add into Feedbin, and that’s working well so far, too.</p>
<p>Note: many thanks to Chris Coyier whose post <a href="https://css-tricks.com/netnewswire-and-feedbin/">NetNewsWire and Feedbin</a> pointed me toward these excellent RSS clients.</p>
A Guide To The State Of Print Stylesheets In 2018 - Smashing Magazine2020-10-02T13:49:48Zhttps://fuzzylogic.me/posts/2020-10-02-a-guide-to-the-state-of-print-stylesheets-in-2018-smashing-magazine/<p>Rachel Andrew explains how to write CSS for a nicely optimised printed page that uses a minimum of ink and paper and ensures that content is easy to read.</p>
<p>I really like the section on Workflow that compares the options of</p>
<ol>
<li>organising your print styles as a separate stylesheet loaded via a <code><link></code> in the <code><head></code> (this is the “traditional” approach); versus</li>
<li>using <code>@media print {}</code> in your main styles, which opens up the opportunity to locate each component’s print styles beside its main styles.</li>
</ol>
<p>As Rachel notes, the first option might feel tidy (and keeping print styles separate reduces the size of your main stylesheet) however on larger sites this approach can lead to print styles being “out of sight, out of mind” and poorly maintained.</p>
<p>I think there will always be a need for 80% global print styles, supplemented by a sprinkling of component-specific print styles (and <em>maybe</em> even the odd utility class). It’s just a case of how you organise this.</p>
<p>I had an idea that you could maybe put the <em>global</em> print styles in a separate sheet and locate the <em>component styles</em> beside components in the main stylesheet however because we tend to want global print styles to <em>add to</em> and override main styles you’d want the print_globals file coming after the main styles, but that then screws up the order of the component-specific print styles. When <a href="https://css-tricks.com/css-cascade-layers/#aa-layering-entire-stylesheets-with-import-or-link"><code>@layers</code> with <code><link></code> is supported</a> perhaps this could all work! Until then, the future of print CSS for large design systems is perhaps Option 2: colocate print styles with screen styles.</p>
Better Alt Text2020-09-28T19:22:00Zhttps://fuzzylogic.me/posts/better-alt-text/<p>I’ve just read <a href="https://www.a11yproject.com/posts/2013-01-14-alt-text/">The A11Y Project’s page on <code>alt</code> text</a>.</p>
<p>As most of us know, the HTML <code>alt</code> attribute is for providing “alternate text” descriptions of images to help ensure people do not miss out on information conveyed by graphics. This can help people using assistive technology such as screen readers, and in situations where images are slow or fail to load.</p>
<p>The article made some interesting points and even though I’ve been using the <code>alt</code> attribute for years I found three common cases where I could improve how I do things.</p>
<h2 id="avoid-starting-with-%E2%80%9Cphoto-of%E2%80%A6%E2%80%9D" tabindex="-1">Avoid starting with “photo of…” <a class="direct-link" href="https://fuzzylogic.me/posts/better-alt-text/#avoid-starting-with-%E2%80%9Cphoto-of%E2%80%A6%E2%80%9D" aria-hidden="true">#</a></h2>
<p>Don’t begin alternative text with “photo of…” or “picture of…”. Assistive technologies already indicate the role of the element as an “image” or “graphic”. Redundancy makes for a poor user experience.</p>
<h2 id="avoid-including-the-word-%E2%80%9Clogo%E2%80%9D-in-logo-images" tabindex="-1">Avoid including the word “logo” in logo images <a class="direct-link" href="https://fuzzylogic.me/posts/better-alt-text/#avoid-including-the-word-%E2%80%9Clogo%E2%80%9D-in-logo-images" aria-hidden="true">#</a></h2>
<p>If the image is a company’s logo, the <code>alt</code> should be the company’s name. Adding the word “logo” as part of the alternative text is neither necessary nor useful. (One thing I found helpful here is to think of the way I, as a sighted person, perceive Apple’s logo. I just think “Apple”, not “Apple’s logo”, so I guess the same principle applies.)</p>
<h2 id="if-using-an-image-multiple-times-on-the-page%2C-tailor-the-alt-text" tabindex="-1">If using an image multiple times on the page, tailor the <code>alt</code> text <a class="direct-link" href="https://fuzzylogic.me/posts/better-alt-text/#if-using-an-image-multiple-times-on-the-page%2C-tailor-the-alt-text" aria-hidden="true">#</a></h2>
<p>Using an image several times in a website doesn't necessarily mean the alt attribute should be the same for each instance. For example, when using a logo in the website’s header this often doubles as a link back to the home page. In this example, the <code>alt</code> would be most useful as “Apple - Homepage”. If that same logo were used in the footer of the site alongside the text “Apple, copyright 20XX”, then the logo should have an empty alt (alt="") so as to avoid creating a redundant announcement of the company’s name.</p>
Ledger of Harms2020-09-28T17:07:07Zhttps://fuzzylogic.me/posts/2020-09-28-ledger-of-harms/<p>Here’s a list of factoids describing societal harms caused by technology platforms, each supported by a citation.</p>
<blockquote>
<p>Under immense pressure to prioritize engagement and growth, technology platforms have created a race for human attention that’s unleashed invisible harms to society. Here are some of the costs that aren’t showing up on their balance sheets.<br />
(via <a href="https://twitter.com/adactio">@adactio</a>)</p>
</blockquote>
Setting an accessibility standard for a UK-based commercial website2020-09-20T16:58:08Zhttps://fuzzylogic.me/posts/how-to-choose-an-appropriate-accessibility-standard-for-your-website-and-test-against-it/<p>When advocating accessible web practices for a commercial website, the question of “what does the law require us to do?” invariably arises.</p>
<p>The appropriate answer to that question should really be that it doesn’t matter. Regardless of the law there is a moral imperative to do the right thing unless you are OK with excluding people, making their web experiences unnecessarily painful, and generally flouting the web’s founding principles.</p>
<p>However as Web Usability’s article <a href="https://info.webusability.co.uk/blog/what-is-the-law-on-accessibility">What is the law on accessibility?</a> helpfully advises, in the UK the legal situation is as follows:</p>
<p>“The accessibility of a UK web site is covered by the Equality Act 2010” (which states that) “Site owners are required to make ‘reasonable adjustments’ to make their sites accessible to people with disabilities”. While “there is no legal precedent about what would constitute a ‘reasonable adjustment’”, “given that the Government has adopted the WCAG 2.1 level AA as a suitable standard for public sector sites and it is more broadly recognised as a ‘good’ approach, any site which met these guidelines would have a very strong defence against any legal action.”</p>
<p>So, WCAG 2.1 Level AA is the sensible accessibility standard for your commercial UK-based website to aim for.</p>
<p>While not aimed specifically at the UK market, <a href="http://deque.com/">deque.com</a>’s article <a href="https://www.deque.com/blog/what-to-look-for-in-an-accessibility-audit/">What to look for in an accessibility audit</a> offers similar advice:</p>
<blockquote>
<p>The most common and widely-accepted standard to test against is WCAG, a.k.a. Web Content Accessibility Guidelines. This standard created by the World Wide Web Consortium (W3C) defines technical guidelines for creating accessible web-based content.</p>
</blockquote>
<blockquote>
<p>WCAG Success Criteria are broken down into different “levels of conformance”: A (basic conformance), AA (intermediate conformance), and AAA (advanced conformance). The current standard for compliance is both WCAG 2.1 Level A and AA.</p>
</blockquote>
<blockquote>
<p>If you don’t have specific accessibility regulations that apply to your organization but want to avoid legal risk, WCAG 2.1 A and AA compliance is a reasonable standard to adopt.</p>
</blockquote>
<h2 id="additional-references" tabindex="-1">Additional references <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-choose-an-appropriate-accessibility-standard-for-your-website-and-test-against-it/#additional-references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.gov.uk/service-manual/helping-people-to-use-your-service/understanding-wcag">GOV.UK’s overview of WCAG 2.1</a></li>
<li><a href="https://www.w3.org/TR/WCAG21/">WCAG 2.1 Official Docs</a></li>
<li><a href="https://siteimprove.com/en-gb/accessibility/uk-accessibility-laws/">UK Accessibility Laws</a> on <a href="http://siteimprove.com/">siteimprove.com</a></li>
<li><a href="https://www.pinsentmasons.com/out-law/guides/disabled-access-to-websites-under-uk-law">Disabled access to websites under UK Law (from 2011)</a></li>
</ul>
itty.bitty2020-09-19T17:39:04Zhttps://fuzzylogic.me/posts/2020-09-19-ittybitty/<p>Here’s an interesting tool for creating and sharing small-ish web pages without having to build a website or organise hosting.</p>
<blockquote>
<p>itty.bitty takes html (or other data), compresses it into a URL fragment, and provides a link that can be shared. When it is opened, it inflates that data on the receiver’s side.</p>
</blockquote>
<p>While I find this idea interesting, I’m not yet 100% sure how or when I’ll use it! I’m sure it’ll come in handy at some point, though.</p>
<p>Here’s <a href="https://itty.bitty.site/#Laurence%E2%80%99s_Itty_Bitty_Test/?XQAAAALHAAAAAAAAAAAkGUpGZJK92rlB0uq9M5C9YTm8ebEX20zjXEyx64k6L8RNUeBvngn2kefaONOBLdlTPDzR98OUYoLzEh6XZKaOsHwrbTV04wugMNaLfhuP9wLEHusrHdgaop7+ChZgRm/q+9hCau/yoH//nAuAAA==">my first “itty bitty” page</a>, just for fun.</p>
<p>(via <a href="https://twitter.com/chriscoyier">@chriscoyier</a>)</p>
When there is no content between headings2020-09-19T15:27:13Zhttps://fuzzylogic.me/posts/2020-09-19-when-there-is-no-content-between-headings/<p>Hidde de Vries explains why an HTML heading should never be immediately followed by another.</p>
<blockquote>
<p>When you use a heading element, you set the expectation of content.</p>
</blockquote>
<p>I have always prided myself on using appropriate, semantic HTML, however it’s recently become clear to me that there’s one thing I occasionally do wrongly. Sometimes I follow a page’s title (usually an <code>h1</code> element) with a subtitle which I mark up as an <code>h2</code>. I considered this the right element for the job and my choice had nothing to do with aesthetics.</p>
<p>However <a href="https://fuzzylogic.me/posts/2020-08-02-how-to-create-accessible-subtitles-on-go-make-things/">a recent article on subtitles by Chris Ferdinandi</a> and now this article by Hidde have made me reconsider.</p>
<p>HTML headings are essentially ”names for content sections”. On screen readers they operate like a Table of Contents – one can use them to navigate to content.</p>
<p>Therefore I now reckon I should only use a <code>hx</code> heading when it will be immediately followed by (non-heading) content – paragraphs and so on – otherwise I should choose a different element.</p>
<p>I should probably mark up my subtitles as paragraphs.</p>
The Social Dilemma2020-09-19T09:48:00Zhttps://fuzzylogic.me/posts/the-social-dilemma/<p>I watched Netflix’s documentary <a href="https://www.netflix.com/gb/title/81254224">The Social Dilemma</a> the other night. It’s been generating a bit of a buzz, and its subject matter – the effects of social media – is one I’m generally interested in. However, I wasn’t a fan.</p>
<p>While I totally agree with the sentiment that Facebook and Google (amongst others) don’t act in our best interests, there were more than a few aspects of this film that didn’t sit quite right.</p>
<p>Firstly, Netflix themselves are no angels (their CEO once said “sleep is our main competitor”) so for them to suddenly dress this up as “breaking news”, act as heroic whistleblower then make it all sexy with that typically shiny Netflix aesthetic, felt really disingenuous and nasty.</p>
<p>Secondly, why is it all former employees of Google and Facebook (with the exception of <a href="https://www.goodreads.com/book/show/26195941-the-age-of-surveillance-capitalism">proper commentators like Shoshana Zuboff</a>) that are “breaking the news” to us? It stinks of “I took the big pay cheque from a company doing bad things, now I’m taking Netflix’s pay cheque to rat on my former employee, even though Netflix do bad things too”. I trust some of these guys, and Netflix, about as far as I could throw them.</p>
<p>I like the social connection aspects of Facebook and it’s been handy over the years, but (lovely birthday messages and event planning aside) I wish I could bite the bullet and get off. I’d also love to see more people have their own websites/blogs – their own home on the web – and for there to be modern means of cross-communication between those. I reckon too many people have come to think that Facebook and Google <em>are</em> the web. They’re not.</p>
<p>You can have your own home on the web where the content you publish is not fodder for an algorithm that pushes you stuff and sells your data to the highest bidder.</p>
Under the Cloud (on BBC Radio 4)2020-09-10T18:49:42Zhttps://fuzzylogic.me/posts/2021-01-24-bbc-radio-4-under-the-cloud/<p>An interesting BBC podcast on the history and true nature of the cloud.</p>
<blockquote>
<p>We connect to the cloud, think of it as place-less, a digital “elsewhere” for storing and retrieving our data, content and memories. But far from being immaterial, the cloud is a vast, physical network made up of concrete, silicon and steel, of earthbound server farms, subterranean data centres and cables beneath the sea. It is not a publicly owned space or digital 'commons'. It is a multi-billion dollar, private infrastructure dominated by some of the world’s most powerful companies—principally Amazon, Microsoft and Google. The cloud exists within the same geography that we do: a patchwork of national and legal jurisdictions, which determine—most of the time—what it can and cannot do.</p>
</blockquote>
The difference between aria-label and aria-labelledby (Tink - Léonie Watson)2020-09-05T08:52:36Zhttps://fuzzylogic.me/posts/2020-09-05-the-difference-between-arialabel-and-arialabelledby-tink-leonie-watson/<blockquote>
<p>The <code>aria-label</code> and <code>aria-labelledby</code> attributes do the same thing but in different ways. Sometimes the two attributes are confused and this has unintended results. This post describes the differences between them and how to choose the right one.</p>
</blockquote>
<p>The key takeaways for me were:</p>
<ul>
<li>Many HTML elements have an <em>accessible name</em> (which we can think of as its “label”) and this can be derived from the element’s content, an attribute, or from an associated element;</li>
<li>for <code>aria-labelledby</code>, use the <code>id</code> of another element and that will then use that element’s text as your first element’s accessible name;</li>
<li>use native HTML over ARIA where possible, but when you need ARIA it’s better to reuse than duplicate so if an appropriate label already exists in the document use <code>aria-labelledby</code>; otherwise use <code>aria-label</code>;</li>
<li>an ARIA attribute will trump any other accessible name (such as the element’s content)</li>
<li>there are some elements on which these ARIA attributes <a href="https://developer.paciellogroup.com/blog/2017/07/short-note-on-aria-label-aria-labelledby-and-aria-describedby/">do not work consistently</a> so check these before using.</li>
</ul>
Tenet, revisited2020-09-04T08:31:00Zhttps://fuzzylogic.me/posts/tenet-revisited/<p>I watched <a href="https://www.imdb.com/title/tt6723592/">Tenet</a> again last night (in IMAX with <a href="https://fuzzylogic.me/posts/tenet-revisited/@jamiethomsonno1">Jamie</a>) and second time round it all made sense.</p>
<p>My initial viewing was good but really confusing; but this time I knew what was going on and loved it! Based on the plot, it actually makes sense that you need to see it twice, too.</p>
<p>This film has its flaws, no doubt, but for sheer invention, visuals you’ve genuinely never seen before, combined with the overall look, sound and mood, Mr Nolan has me hook, line and sinker and TBH I will likely never tire of watching his films. I expect to revisit this one roughly another ten times in the next year!</p>
<p>Footnote: I’ve been enjoying some internet rabbit-holing to squeeze out every last nuance of the plot I might have missed. Here are some great articles and resources which have helped (with the usual “heavy spoilers” caveat):</p>
<ul>
<li><a href="https://adactio.com/journal/17379">Adactio’s fantastic review</a> and insights</li>
<li><a href="https://www.vulture.com/2020/09/tenet-explained-whats-going-on-in-the-plot-of-this-movie.html">Vulture’s humorous plot appraisal</a></li>
<li><a href="https://scrapsfromtheloft.com/2020/09/05/tenet-transcript/">Transcript on Scraps from the Loft</a>. It’s neither official nor 100% accurate but does a job.</li>
</ul>
Super Turbo Logo Service™ (on SimpleBits)2020-09-01T20:11:44Zhttps://fuzzylogic.me/posts/2021-01-24-super-turbo-logo-servicetm-on-simplebits/<blockquote>
<p>I’m available for limited logo design projects. Just the logo. Limited back-and-forth. Reasonable price. With a particular focus on elevating small businesses that can’t or don’t want to hire a full-blown agency. Let’s keep this simple.</p>
</blockquote>
<p>I’m a long-time fan of Dan Cederholm and his work. If I wanted a new logo, this is where I’d go!</p>
Introducing Rome2020-08-23T15:06:10Zhttps://fuzzylogic.me/posts/2020-08-23-introducing-rome/<blockquote>
<p>We’re excited to announce the first beta release and general availability of the Rome linter for JavaScript and TypeScript. This is the beginning of an entire suite of tools. Rome is not only a linter, but also a compiler, bundler, test runner, and more, for JavaScript, TypeScript, HTML, JSON, Markdown, and CSS. We aim to unify the entire frontend development toolchain.</p>
</blockquote>
<p>A very ambitious project from the creator of Babel.</p>
Create a line break while maintaining inline status (on Piccalilli)2020-08-23T11:17:11Zhttps://fuzzylogic.me/posts/2020-08-23-create-a-line-break-while-maintaining-inline-status-on-piccalilli/<blockquote>
<p>Sometimes you want to create a line break after an inline element, while retaining that inline element’s inline status.</p>
</blockquote>
<p>A lovely trick from Andy Bell for breaking after an inline element (such as a form label) using a pseudo-element and the <code>white-space</code> property, so that we can avoid setting the element to <code>display: block</code> (thereby becoming full-width etc) when we don’t want that.</p>
<p><a href="https://codepen.io/fuzzylogicx/pen/BaKpLPE">Here’s my own codepen for posterity</a>.</p>
Jakarta Sans Typeface2020-08-16T18:23:52Zhttps://fuzzylogic.me/posts/2020-08-16-jakarta-sans-typeface/<p>Jakarta Sans is a nice-looking Open Source (so free to use) typeface which I reckon I could use at some point.</p>
<p>(via <a href="https://twitter.com/css">@css</a>)</p>
Joshua Hughes / Senior Product Designer2020-08-16T17:00:03Zhttps://fuzzylogic.me/posts/2021-01-16-joshua-hughes-senior-product-designer/<p>The lovely new portfolio website of my colleague, Josh, featuring some lovely articles and design touches.</p>
2020-08-14T22:15:21Zhttps://fuzzylogic.me/posts/1597443368-purgecss-optimisation-for-eleventy/<p><a href="https://twitter.com/danielpost/status/1293286796604956673">Daniel Post shared</a> a really cool performance-optimisation trick for Eleventy on Twitter the other day. When statically generating your site you can loop through your pages and, for each, use PurgeCSS to find the required CSS, then inline that into the <code><head></code>. This way, each page contains only the CSS it needs and no more!</p>
<p><a href="https://t.co/LaF3ACB07n">Check out the code.</a></p>
<p>I’ve just installed this on my personal site. I was already inlining my CSS into the <code><head></code> but the promise of only including the minimum CSS that each specific page needs was too good to resist.</p>
<p>Turned out it was a breeze to get working, a nice introduction to Eleventy transforms, and so far it’s working great!</p>
Thoughts on inline JavaScript event handlers in the <head>2020-08-10T21:16:21Zhttps://fuzzylogic.me/posts/1597093543-inline-javascript-event-handlers-are-resilient/<p>I’ve been thinking about <a href="https://fuzzylogic.me/posts/2020-08-08-simplest-way-to-load-css-async/">Scott Jehl’s “simplest way to load external CSS asynchronously” technique</a>. I’m interested in its use of an inline (<code>onload</code>) event handler for running JavaScript-based enhancements in the <code><head></code>, in the context of some broader ruminations on how best to progressively enhance UI elements with JavaScript (for example adding toggle show/hide) without causing layout jank.</p>
<p>One really interesting aspect of using inline event handlers to apply enhancements was <a href="https://gomakethings.com/progressive-enhancement-graceful-degradation-and-asynchronously-loading-css/">highlighted by Chris Ferdinandi today</a>: as JavaScript goes, it’s pretty <em>resilient</em>.</p>
<p>Because we’re dealing with an HTML element directly in the document, and because the relevant JS is inline on that element and not dependent on any external files, the only case where the JS won’t run is if someone has JS completely turned off – a sub-1% proportion. The other <a href="https://kryogenix.org/code/browser/everyonehasjs.html">typical JavaScript resilience pitfalls</a> – such as network connections timing out, CDN failure and JS errors elsewhere blocking your code from running – simply don’t apply here.</p>
“Doing It Right” Podcast, with Dotty Charles2020-08-10T13:21:54Zhttps://fuzzylogic.me/posts/2020-08-10-doing-it-right-podcast-with-dotty-charles/<p>An interview with Ashley ‘Dotty’ Charles, a writer and broadcaster, on the topic of online outrage.</p>
<blockquote>
<p>By shouting about the little things, are we neglecting to talk about the bigger issues in modern society? We discuss performative outrage, the role of the social media provocateur and the strange case of Rachel Dolezal.</p>
</blockquote>
<p>I really enjoyed this. It totally chimed with how I currently feel about the state of online discourse, and Dotty has some great ideas and insights. I’ve already bought <a href="https://www.waterstones.com/book/outraged/ashley-dotty-charles/9781526605030">her book, Outraged</a> and am looking forward to reading that soon.</p>
<p>Thanks to Rita (Kelly) for the tip!</p>
Hero Patterns: Free repeatable SVG background patterns for your web projects2020-08-09T22:47:38Zhttps://fuzzylogic.me/posts/2020-08-09-hero-patterns-free-repeatable-svg-background-patterns-for-your-web-projects/<p>From Steve Schoger:</p>
<blockquote>
<p>A collection of repeatable SVG background patterns for you to use on your web projects.</p>
</blockquote>
<p>This was recommended by Chris Coyier in his post <a href="https://css-tricks.com/websites-generate-svg-patterns/">Websites to Generate SVG Patterns</a>.</p>
Inclusive Datepicker (by Tommy Feldt)2020-08-09T22:37:34Zhttps://fuzzylogic.me/posts/2020-08-09-inclusive-datepicker-by-tommy-feldt/<blockquote>
<p>A human-friendly datepicker. Supports natural language manual input through Chrono.js. Fully accessible with keyboard and screen reader.</p>
</blockquote>
Sign-in form best practices (on web.dev)2020-08-09T22:29:09Zhttps://fuzzylogic.me/posts/2020-08-09-signin-form-best-practices-on-webdev/<p>Sam Dutton advises how to use cross-platform browser features to build sign-in forms that are secure, accessible and easy to use.</p>
<p>The tips of greatest interest to me were:</p>
<ul>
<li>on using <code>autocomplete="new-password"</code> on registration forms and <code>autocomplete="current-password"</code> on sign-in forms to tap into browser password suggestion and password manager features;</li>
<li>on how best to provide “Show Password” functionality; and</li>
<li>on using <code>aria-describedby</code> when providing guidance on password rules.</li>
</ul>
Rodney P’s Jazz Funk (on BBC Four)2020-08-09T12:17:56Zhttps://fuzzylogic.me/posts/2020-08-09-rodney-ps-jazz-funk-on-bbc-four/<p>UK rap legend Rodney P reveals how the first generation of British-born black kids was inspired by the avant-garde musical fusions of black America in the 70s to lay the foundations of modern-day multiculturalism by creating the first black British music culture with the jazz-funk movement.</p>
<p>A brilliant documentary featuring great music from Pharoah Sanders, War, Hi-Tension, Ronnie Laws and more.</p>
Three CSS Alternatives to JavaScript Navigation (on CSS-Tricks)2020-08-08T19:24:39Zhttps://fuzzylogic.me/posts/2020-08-08-three-css-alternatives-to-javascript-navigation-on-csstricks/<p>In general this is a decent article on non-JavaScript-based mobile navigation options, but what I found most interesting is the idea of having a separate <em>page</em> for your navigation menu (at the URL /menu, for example).</p>
<blockquote>
<p>Who said navigation has to be in the header of every page? If your front end is extremely lightweight or if you have a long list of menu items to display in your navigation, the most practical method might be to create a separate page to list them all.</p>
</blockquote>
<p>I also noted that the article describes a method where you can “spoof” a slide-in <em>hamburger</em> menu without JS by using the checkbox hack. I once coded a similar “HTML and CSS -only” hamburger menu, but opted instead to use the <code>:target</code> pseudo-class in combination with the adjacent sibling selector, <a href="https://css-tricks.com/off-canvas-menu-with-css-target/">as described by Chris Coyier back in 2012</a>.</p>
The Simplest Way to Load CSS Asynchronously (Filament Group)2020-08-08T12:01:21Zhttps://fuzzylogic.me/posts/2020-08-08-simplest-way-to-load-css-async/<p>Scott Jehl of Filament Group demonstrates a one-liner technique for loading external CSS files without them delaying page rendering.</p>
<p>While this isn’t really necessary in situations where your (minified and compressed) CSS is small, say 14k or below, it could be useful when working with large CSS files and want to deliver critical CSS separately and the rest asynchronously.</p>
<blockquote>
<p>Today, armed with a little knowledge of how the browser handles various link element attributes, we can achieve the effect of loading CSS asynchronously with a short line of HTML. Here it is, the simplest way to load a stylesheet asynchronously:</p>
</blockquote>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my.css<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>print<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">onload</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token keyword">this</span><span class="token punctuation">.</span>media<span class="token operator">=</span><span class="token string">'all'</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>Note that if JavaScript is disabled or otherwise not available your stylesheet will only load for print and not for screen, so you’ll want to follow up with <a href="https://twitter.com/nhoizey/status/1152330563082227712">a “normal” (non-print-specific) stylesheet within <code><noscript></code> tags</a>.</p>
Color Theme Switcher (on mxb.dev)2020-08-08T09:01:21Zhttps://fuzzylogic.me/posts/2020-08-08-color-theme-switcher-on-mxbdev/<p>Max shows us how to build a colour theme switcher to let users customise your website. He uses a combination of Eleventy, JSON, Nunjucks with macros, a data attribute on the html element, CSS custom properties and a JavaScript based switcher.</p>
<p>Thanks, <a href="https://twitter.com/mxbck">Max</a>!</p>
3 Popular Website Heroes Created With CSS Grid Layout (on Modern CSS Solutions)2020-08-07T18:04:40Zhttps://fuzzylogic.me/posts/2020-08-07-3-popular-website-heroes-created-with-css-grid-layout-on-modern-css-solutions/<p>Some serious CSS Grid positioning, image manipulation and alpha transparency ninjitsu on display here from Stephanie Eckles!</p>
<blockquote>
<p>This episode explores creating website heroes - aka “headers” - with one of my favorite ways to use CSS grid layout: by turning it into a canvas.</p>
</blockquote>
Sass and clamp (on Adactio: Journal)2020-08-07T16:47:58Zhttps://fuzzylogic.me/posts/2020-08-07-sass-and-clamp-on-adactio-journal/<p>Given what we can now do with CSS, do we still need Sass?</p>
<blockquote>
<p>Sass was the hare. CSS is the tortoise. Sass blazed the trail, but now native CSS can achieve much the same result.</p>
</blockquote>
<p>Jeremy’s post starts by talking about the new CSS <code>clamp</code> function and how it can be used for scalable type, then veers into a question of whether we still need Sass or if modern CSS now covers our needs.</p>
<p>This is really interesting and definitely gives me pause to consider whether I can simplify my development stack by removing a tool.</p>
<p>However I guess one reason (not mentioned in Jeremy’s post) you might want Sass is that many of the CSS functions which provide similar effects to mixins, variables etc are currently only supported in the most modern, standards-compliant browsers. Sass can pre-process its variables and mixins into older, more broadly-supported CSS. So choosing the pure CSS, processor-free option within a progressive enhancement oriented approach <em>might</em> mean that your broadly-supported baseline is more basic than it would be by using Sass. That’s the sort of decision I could take fairly lightly for my personal website, but I could see it being less palatable for stakeholders working on larger sites.</p>
<p>For example, if your site needs to support IE11 and theming which includes custom colour schemes, unfortunately you don’t have the luxury of putting all your eggs in the native CSS <a href="https://caniuse.com/#search=custom%20properties">custom properties</a> basket.</p>
Best practice techniques for SVG Icons2020-08-07T09:30:00Zhttps://fuzzylogic.me/posts/accessible-scalable-icons/<p>Here’s how I’d handle various common SVG icon scenarios with accessibility in mind.</p>
<h2 id="just-an-icon" tabindex="-1">Just an icon <a class="direct-link" href="https://fuzzylogic.me/posts/accessible-scalable-icons/#just-an-icon" aria-hidden="true">#</a></h2>
<p>So this is an icon that’s not within a link or button and has no adjacent text. This might be, for example, an upward-pointing arrow icon in a <code><td></code> in a “league table” where the arrow is intended to indicate a trend such as “The figure has increased” or “Moving up the table”.</p>
<p>The point here is that in this scenario the SVG is content rather than decoration.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <br /> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>img<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>arrow-title<span class="token punctuation">"</span></span><br /><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>arrow-title<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Balance has increased<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>path</span> <span class="token attr-name">…</span><span class="token punctuation">></span></span>…</path<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>Note: Fizz Studio’s article <a href="https://fizz.studio/blog/reliable-valid-svg-accessibility/">Reliable valid SVG accessibility</a> suggests that the addition of <code>aria-labelledby</code> pointing to an id for the <code><title></code> (as Léonie originally recommended) is no longer necessary. That’s encouraging, but as it does no harm to keep it I think I’ll continue to include it for the moment.</p>
<p>The same article also offers that maybe we should not use the SVG <code><title></code> element (and use <code>aria-label</code> to provide an accessible name instead) due to the fact that it leads to a potentially undesirable tooltip, much like the HTML <code>title</code> attribute does. To be honest I’m OK with this and don’t see it as a problem, and as I mention later have heard probably even more problematic things about <code>aria-label</code> so will stick with <code><title></code>.</p>
<h2 id="button-(or-link)-with-icon-plus-text" tabindex="-1">Button (or link) with icon plus text <a class="direct-link" href="https://fuzzylogic.me/posts/accessible-scalable-icons/#button-(or-link)-with-icon-plus-text" aria-hidden="true">#</a></h2>
<p>This is easy. Hide the icon from Assistive Technology using <code>aria-hidden</code> to avoid unnecessary repetition and rely on the text as the accessible name for the button or link.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token punctuation">></span></span><span class="token comment"><!--...--></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /> Search<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!--...--></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /> Search<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
</figure>
<h2 id="button-(or-link)-with-icon-alone" tabindex="-1">Button (or link) with icon alone <a class="direct-link" href="https://fuzzylogic.me/posts/accessible-scalable-icons/#button-(or-link)-with-icon-alone" aria-hidden="true">#</a></h2>
<p>In this case the design spec is for a button with no accompanying text, therefore we must add the accessible name for Assistive Technologies ourselves.</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!--...--></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Search<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">focusable</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token comment"><!--...--></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Search<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>The reason I use text that’s <a href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/#hide-visually-(i.e.-from-sighted-people)">visually-hidden using CSS</a> for the accessible name rather than adding <code>aria-label</code> on the button or link is because I’ve heard that the former option is more reliable. In greater detail: <a href="https://gomakethings.com/revisting-aria-label-versus-a-visually-hidden-class/">aria-label is announced inconsistently and not always translated</a>.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/accessible-scalable-icons/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://css-tricks.com/accessible-svg-icons/">Accessible SVG Icons</a>, by Chris Coyier;</li>
<li><a href="https://www.sitepoint.com/tips-accessible-svg/">Tips for accessible SVG</a>, by Léonie Watson;</li>
<li><a href="https://fizz.studio/blog/reliable-valid-svg-accessibility/">Reliable, valid SVG accessibility</a>, by Fizz Studio;</li>
<li><a href="https://www.sarasoueidan.com/blog/accessible-icon-buttons/">Accessible icon buttons</a>, by Sara Soueidan;</li>
<li><a href="https://absolutely.every-layout.dev/layouts/icon/">Every Layout’s Icon component</a>; and</li>
<li><a href="https://fuzzylogic.me/posts/how-to-hide-elements-for-different-browsing-contexts/">How to hide elements on a web page</a>, by my bad self.</li>
</ul>
Jack McDade’s personal website2020-08-03T08:50:24Zhttps://fuzzylogic.me/posts/2020-08-03-im-jack-mcdade-and-im-tired-of-boring-websites/<blockquote>
<p>I’m Jack McDade and I’m tired of boring websites.</p>
</blockquote>
<p>So many fun touches in the design for Jack’s personal website! It gave me plenty of chuckles while browsing over the weekend.</p>
<p>My favourite bits were the “Email Deposit Box” on the <a href="https://radicaldesigncourse.com/">Radical Design Course section</a> (make sure to have sound turned on) and the entire <a href="https://jackmcdade.com/design">Design Work</a> page (keep scrolling)!</p>
How to create accessible subtitles (on Go Make Things)2020-08-02T13:18:52Zhttps://fuzzylogic.me/posts/2020-08-02-how-to-create-accessible-subtitles-on-go-make-things/<p>Here’s Chris Ferdinandi, introducing the ARIA <code>doc-subtitle</code> role.</p>
<p>He sets the scene by describing the popular design pattern where we have a title with a subtitle directly underneath, and that subtitle is set to be visually distinct via its font size being larger than the body text while remaining smaller than the main heading. Developers have typically marked up the subtitle using either another heading element, or a dedicated class. He suggests that the former is bad because headings in HTML are for conveying structure (with the inference that a subtitle is not structural) while the latter is suboptimal because it provides sighted users with additional information that visually impaired users don’t get.</p>
<p>A better approach is coming; the new <code>role=doc-subtitle</code> will convey to screen readers that the element is a subheading.</p>
<p>I’m going to hold off using it for a little bit <a href="https://twitter.com/stevefaulkner/status/1286367526105026560">until screen reader support improves</a>, but generally this feels like a good move.</p>
Bustle2020-08-02T11:58:51Zhttps://fuzzylogic.me/posts/2020-08-02-bustle/<p>Here’s a beautiful, magazine style website design for digital publication <em>Bustle</em>. The typography, use of whitespace, responsive layout, menu pattern, colour palette and imagery are all on point!</p>
SVG Backgrounds – Create Customizable, Hi-Def, and Scalable Backgrounds.2020-07-25T11:03:10Zhttps://fuzzylogic.me/posts/2020-07-25-create-customizable-hidef-and-scalable-backgrounds/<blockquote>
<p>SVGs enable full-screen hi-res visuals with a file-size near 5KB and<br />
are well-supported by all modern browsers. What's not to love?<br />
A neat tool for selecting, customising and applying SVG backgrounds.</p>
</blockquote>
<p>(via <a href="https://twitter.com/css">@css</a>)</p>
Accessibility (on adactio.com)2020-07-25T10:44:04Zhttps://fuzzylogic.me/posts/2020-07-25-adactio-journalaccessibility/<p>Here’s <a href="https://adactio.com/">Jeremy Keith</a>, making the moral case for accessible websites and why we shouldn’t use “you can make more money by not turning people away” as an argument:</p>
<blockquote>
<p>I understand how it’s useful to have the stats and numbers to hand should you need to convince a sociopath in your organisation, but when numbers are used as the justification, you’re playing the numbers game from then on. You’ll probably have to field questions like ”Well, how many screen reader users are visiting our site anyway?” (To which the correct answer is “I don’t know and I don’t care” – even if the number is 1, the website should still be accessible because <em>it’s the right thing to do</em>.)</p>
</blockquote>
<p>(via @adactio)</p>
Font Match2020-07-25T10:37:20Zhttps://fuzzylogic.me/posts/2020-07-25-font-match/<p>A font pairing app that helps you match fonts – useful for pairing a webfont with a suitable fallback. You can place the fonts on top of each other, side by side, or in the same line. You can adjust your fallback font’s size and position to get a great match.</p>
Font style matcher2020-07-25T10:11:16Zhttps://fuzzylogic.me/posts/2020-07-25-font-style-matcher/<blockquote>
<p>If you’re using a web font, you're bound to see a flash of unstyled text (or FOUC), between the initial render of your websafe font and the webfont that you’ve chosen. This usually results in a jarring shift in layout, due to sizing discrepancies between the two fonts. To minimize this discrepancy, you can try to match the fallback font and the intended webfont’s x-heights and widths. This tool helps you do exactly that.</p>
</blockquote>
Debouncing vs. throttling with vanilla JS (on Go Make Things)2020-07-14T13:03:29Zhttps://fuzzylogic.me/posts/2020-07-14-debouncing-vs-throttling-with-vanilla-js-on-go-make-things/<p>Chris explains how debouncing and throttling are two related but different techniques for improving performance and user experience when working with frequently invoked JavaScript event handlers.</p>
<p>With throttling, you run a function immediately, then wait a specified amount of time before running it again. Any additional attempts to run it before that time period is over are ignored.</p>
<p>With debouncing, after the relevant event fires a specified time period must pass <em>uninterrupted</em> in order for your function to run. When the time period has passed uninterrupted, that last attempt to run the function is the one that runs, with any previous attempts ignored.</p>
<p>You might <em>debounce</em> code in event handlers for <em>scroll</em> events to run when the user is completely done scrolling so as not to negatively affect browser performance and user experience.</p>
<p>For interactions that update the UI, <em>throttling</em> might make more sense, so that the updates run at predictable intervals.</p>
<p>NB I’ve previously found <a href="https://levelup.gitconnected.com/debounce-in-javascript-improve-your-applications-performance-5b01855e086">Trey Huffine’s debounce tutorial and example function</a> really useful, too.</p>
BLOKK - The new and better wireframing font2020-06-30T08:20:46Zhttps://fuzzylogic.me/posts/2020-06-30-blokk-the-new-and-better-wireframing-font/<blockquote>
<p>BLOKK is a font for quick mock-ups and wireframing for clients who do not understand latin.</p>
</blockquote>
<p>A cool idea here, which gives you “block” versions of the words in your <em>lorem ipsum</em> text, at the same width.</p>
<p>However at this point I do need to remind myself that designing and wireframing with <em>real content</em> is always better.</p>
Striking a Balance Between Native and Custom Select Elements (on CSS-Tricks)2020-06-28T19:06:42Zhttps://fuzzylogic.me/posts/2020-06-28-striking-a-balance-between-native-and-custom-select-elements-on-csstricks/<blockquote>
<p>We’re not going to try to replicate everything that the browser does by default with a native select element. We’re going to literally use a select element when any assistive tech is used. But when a mouse is being used, we’ll show the styled version and make it function as a select element.</p>
</blockquote>
<p>This custom-styled select solution satisfies those who insist on a custom component but retains all the built-in accessibility we get from native form controls. I also really like the use of a <code>@media (hover: hover)</code> media query to detect an environment with hover (such as a computer with a mouse rather than a mobile browser on a handheld device).</p>
Cassie Evans’s Blog2020-06-25T13:52:07Zhttps://fuzzylogic.me/posts/2020-08-02-cassie-evanss-blog/<p>I love Cassie Evans’s new website design! It’s so full of personality while loaded with technical goodies too. Amazing work!</p>
<p>(via <a href="https://twitter.com/stugoo">@stugoo</a>)</p>
How to use npm as a build tool2020-06-08T11:45:23Zhttps://fuzzylogic.me/posts/how-to-use-npm-as-a-build-tool/<p>Kieth Cirkel explains how using npm to run the <code>scripts</code> field of <code>package.json</code> is a great, simple alternative to more complex build tools. The article is now quite old but because it contains so many goodies, and since I’ve been using the approach more and more (for example to easily compile CSS on my personal website), it’s definitely worth bookmarking and sharing.</p>
<blockquote>
<p>npm’s scripts directive can do everything that these build tools can, more succinctly, more elegantly, with less package dependencies and less maintenance overhead.</p>
</blockquote>
<p>It’s also worth mentioning that (as far as I can tell so far) Yarn also provides the same facility.</p>
<h2 id="related-references%3A" tabindex="-1">Related references: <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-use-npm-as-a-build-tool/#related-references%3A" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://docs.npmjs.com/cli/v7/using-npm/scripts">Using scripts, on the npm cli docs</a></li>
<li><a href="https://classic.yarnpkg.com/en/docs/package-json#toc-scripts">Yarn package.json docs</a></li>
</ul>
JavaScript Arrow Functions2020-06-03T16:17:00Zhttps://fuzzylogic.me/posts/javascript-arrow-functions/<p>JavaScript arrow functions are one of those bits of syntax about which I occasionally have a brain freeze. Here’s a quick refresher for those moments.</p>
<details>
<summary>Differences between arrow functions and traditional functions</summary>
<div>
<p>Arrow functions are shorter than traditional function syntax.</p>
<p>They don’t bind their own <code>this</code> value. Instead, the <code>this</code> value of the scope in which the function was defined is accessible. That makes them poor candidates for <em>methods</em> since <code>this</code> won’t be a reference to the object the method is defined on. However it makes them good candidates for everything else, including use <em>within</em> methods, where—unlike standard functions—they can refer to (for example) <code>this.name</code> just like their parent method because the arrow function has no overriding <code>this</code> binding of its own.</p>
</div>
</details>
<h2 id="tl%3Bdr%3A-typical-usage" tabindex="-1">TL;DR: typical usage <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-arrow-functions/#tl%3Bdr%3A-typical-usage" aria-hidden="true">#</a></h2>
<figure>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">doStuff</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">foo</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// stuff that spans multiple lines</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// short functions</span><br /><span class="token keyword">const</span> <span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">num1<span class="token punctuation">,</span> num2</span><span class="token punctuation">)</span> <span class="token operator">=></span> num1 <span class="token operator">+</span> num2<span class="token punctuation">;</span><br /></code></pre>
</figure>
<h2 id="explainer" tabindex="-1">Explainer <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-arrow-functions/#explainer" aria-hidden="true">#</a></h2>
<figure>
<pre class="language-js"><code class="language-js"><span class="token comment">// Traditional Function</span><br /><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">a</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> a <span class="token operator">+</span> <span class="token number">100</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// Arrow Function Breakdown</span><br /><br /><span class="token comment">// 1. Remove "function", place => between argument and opening curly</span><br /><span class="token punctuation">(</span><span class="token parameter">a</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> a <span class="token operator">+</span> <span class="token number">100</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// 2. Remove braces and word "return". The return is implied.</span><br /><span class="token punctuation">(</span><span class="token parameter">a</span><span class="token punctuation">)</span> <span class="token operator">=></span> a <span class="token operator">+</span> <span class="token number">100</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// 3. Remove the argument parentheses</span><br /><span class="token parameter">a</span> <span class="token operator">=></span> a <span class="token operator">+</span> <span class="token number">100</span><span class="token punctuation">;</span><br /></code></pre>
</figure>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-arrow-functions/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Arrow function expressions on MDN</a></li>
<li><a href="https://gomakethings.com/arrow-functions-in-vanilla-js/">Arrow functions in Vanilla JS on gomakethings.com</a></li>
</ul>
How to optimise performance when using Google-hosted fonts (on CSS Wizardry)2020-05-26T22:17:59Zhttps://fuzzylogic.me/posts/2020-05-26-how-to-optimise-performance-when-using-googlehosted-fonts-on-css-wizardry/<blockquote>
<p>A combination of asynchronously loading CSS, asynchronously loading font files, opting into FOFT, fast-fetching asynchronous CSS files, and warming up external domains makes for an experience several seconds faster than the baseline.</p>
</blockquote>
<p>Harry Roberts suggests that, while self-hosting your web fonts is likely to be the overall best solution to performance and availability problems, we’re able to design some fairly resilient measures to help mitigate a lot of these issues when using Google Fonts.</p>
<p>Harry then kindly provides a code snippet that we can use in the <code><head></code> of our document to apply these measures.</p>
Modern CSS Solutions2020-05-24T22:06:40Zhttps://fuzzylogic.me/posts/2020-05-24-modern-css-solutions/<blockquote>
<p>Modern CSS Solutions for Old CSS Problems</p>
</blockquote>
<p>Stephanie Eckles with a beautifully presented series of articles on how to use modern CSS to tackle some of the enduring challenges of web development including dropdown navigation, centring and styling buttons.</p>
CSS Section Separator Generator (on wweb.dev)2020-05-03T08:03:00Zhttps://fuzzylogic.me/posts/2020-05-03-css-section-separator-generator-on-wwebdev/<p>A handy tool that generates the required HTML and CSS for various section separator effects (including diagonal lines, spikes, and waves) by cleverly manipulating backgrounds and generated content.</p>
An ebook boilerplate (on Go Make Things)2020-04-26T09:06:00Zhttps://fuzzylogic.me/posts/2020-04-26-an-ebook-boilerplate-or-go-make-things/<blockquote>
<p>My ebook boilerplate is a command-line script that uses Pandoc, wkhtmltopdf, and Calibre to compile all of the files, syntax highlight code snippets, and automatically generate all of the file formats.</p>
</blockquote>
<p>I’ve recently been discussing with <a href="https://www.clairirwinphotography.com/">Clair</a> some options for publishing an ebook, which reminded me of this.</p>
<p>This is Chris Ferdinandi’s set-up for creating an ebook in multiple formats (PDF, EPUB, MOBI, HTML) from a collection of markdown files.</p>
<p>Also useful, on the same subject: Heydon Pickering’s <a href="https://heydonworks.com/article/every-layout-is-released:-some-facts/">Every Layout is Released: Some Facts</a> and Andy Bell’s <a href="https://hankchizljaw.com/wrote/every-layout-how-it-works/">Every Layout: How it works</a></p>
Isolated Moments: March 2020 Records2020-04-20T09:30:00Zhttps://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1587511766/Mar_2020_Record_Shopping_v2_lyvlu2.jpg" width="320" height="320" alt="Laurence’s record purchases in March 2020" loading="lazy" decoding="async" />
</figure>
<figure style="margin-top: 3rem;">
<blockquote>
<p>What would you do without your music?</p>
</blockquote>
</figure>
<p>So sang D-Train on <em>Music</em> and never has the sentiment resonated more than during the current Coronavirus situation.</p>
<p>Cooped up at home and deprived of face-to-face contact with friends and family, I’ve found that music can really lift the spirits.</p>
<p>Fortunately, the supply of great records hasn’t stopped and there are a number of trusty online stores to keep us connected.</p>
<p>Let’s dive into the stack of wax that has been keeping me (mostly) sane during lockdown.</p>
<h2 id="the-stance-brothers---minor-minor" tabindex="-1">The Stance Brothers - Minor Minor <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#the-stance-brothers---minor-minor" aria-hidden="true">#</a></h2>
<p>Here’s a pair of jazzy hip hop instrumentals from Finland, both riffing on the bassline from Bob James’ classic Nautilus. This 7″ was introduced to me by <a href="https://nothinbutmagic.com/">Tom</a> a couple of years back and has just had a welcome repress. Fans of Marc Mac’s Visioneers project, Kenny Dope and BadBadNotGood won’t go wrong here.</p>
<p><b>Favourite Track:</b> Minor Minor</p>
<div class="l-frame">
<iframe title="The Stance Brothers – Minor Minor" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/Ec4d5NdsOGg" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://wejazzrecords.bandcamp.com/album/minor-minor">Grab a copy on Bandcamp</a></p>
<h2 id="golden-ivy---kl%C3%A4ppen-(lp)" tabindex="-1">Golden Ivy - Kläppen (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#golden-ivy---kl%C3%A4ppen-(lp)" aria-hidden="true">#</a></h2>
<p>Beautiful sounds from Malmo that straddle the organic and the electronic, settling on something vaguely oriental. I was relieved to snap up a copy before it disappeared, given that their previous LP – <em>Monika</em> - is as rare as hen’s teeth and still eludes me. Alas the parcel is currently languishing, unloved, on my desk at work, having arrived there from Gothenburg just a day after the office shut for the lockdown. Damn it! Good things come to those who wait…</p>
<p><b>Favourite Track:</b> Klappen 11</p>
<div class="l-frame">
<iframe title="Golden Ivy - Kläppen 11" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/SuzpuUFznHU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.discogs.com/sell/release/14328979?ev=rb">Grab a copy on Discogs</a></p>
<h2 id="d.k.---live-at-the-edge-(lp)" tabindex="-1">D.K. - Live at the Edge (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#d.k.---live-at-the-edge-(lp)" aria-hidden="true">#</a></h2>
<p>My favourite release to date from Parisian producer D.K. was <a href="https://www.discogs.com/DK-10-SK-DK-SK/release/11022398">his stellar collaboration with Suzanne Kraft</a> on Melody as Truth in 2017. This LP ploughs a similar sensous, ambient furrough and would have been a pretty tasty live gig (if you happened to be in Seoul at the time). Yet another great release from Glaswegian label 12th Isle, with beautiful artwork to boot.</p>
<p><b>Favourite Track:</b> Untitled 11 (not yet on YouTube)</p>
<div class="l-frame">
<iframe title="D.K. – Untitled 1" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/LDBIwyOP-7Y" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.rubadub.co.uk/live-at-the-edge">Grab a copy at Rubadub</a></p>
<h2 id="datassette-%E2%80%93-existenzmaximum" tabindex="-1">Datassette – Existenzmaximum <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#datassette-%E2%80%93-existenzmaximum" aria-hidden="true">#</a></h2>
<p>I’ve loved Datassette since <a href="https://www.youtube.com/watch?v=gbXGyV4twsM">his first outing on Ai records</a> back in 2005. He’s got such a great sound – simultanesouly futuristic, funky, musical and heartfelt in a way that few electronic producers can match. This EP (from November last year but just repressed) is typically brilliant.</p>
<p><b>Favourite Track:</b> Shooz Who</p>
<div class="l-frame">
<iframe title="Datassette – Shooz Who" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/kG_p6SlLFq4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://futuremassive.bandcamp.com/album/existenzmaximum-ep">Grab a copy on Bandcamp</a></p>
<h2 id="various---gazillions" tabindex="-1">Various - Gazillions <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#various---gazillions" aria-hidden="true">#</a></h2>
<p>These days I try not to buy records for just one track, but this is something special. Top cut <em>Lotus Turbo</em> by Russian duo Formally Unknown is a hard-hitting blend of electro and bass that sounds pretty fresh to these ears. This one is screaming to be played loud.</p>
<p><b>Favourite Track:</b> Formally Unknown – Lotus Turbo</p>
<div class="l-frame">
<iframe title="Formally Unknown – Lotus Turbo" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/PIJJ-sYeI_A" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://wejazzrecords.bandcamp.com/album/minor-minor">Grab a copy on Bandcamp</a></p>
<h2 id="various---bubble-chamber-(lp)" tabindex="-1">Various - Bubble Chamber (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#various---bubble-chamber-(lp)" aria-hidden="true">#</a></h2>
<p>I’d urge any fans of serious electro to get on this tout suite – you won’t be disappointed. It boasts a formidable line-up, featuring tracks by Gerald Donald, The Exaltics and Plant43 to name but three. The music comes from a variety of locations and eras; we get Montreal-based Iko’s 1983 track <em>Approach on Tokyo</em> nestling alongside new music from Detroit. Kuldaboli from Reykjavík is a new name on me but offers up the pick of the bunch. Oh, and the vinyl also comes with a 56-page booklet containing previously unseen Drexciyan art by Abdul Haqq… which is nice.</p>
<p><b>Favourite Track:</b> Kuldaboli – Draumur inní heilann þinn</p>
<div class="l-frame">
<iframe loading="lazy" width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/708251818&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
</div>
<p><a href="http://www.vinylunderground.co.uk/bubble-chamber-lp.html">Grab a copy at Vinyl Underground</a></p>
<h2 id="max-d---many-any-(lp)" tabindex="-1">Max D - Many Any (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/mar-2020-record-purchases-isolated-moments/#max-d---many-any-(lp)" aria-hidden="true">#</a></h2>
<p>Solid LP from one half of Beautiful Swimmers, taking in house/techno cuts that evoke vintage Morgan Geist and Ferox, interspersed with hip hop influences. Big up my man Gav aka Other Lands at <a href="https://www.undergroundsolushn.com/">Underground Solu’shn</a> for the hot tip!</p>
<p><b>Favourite Track:</b> Shoutout Seefeel</p>
<div class="l-frame">
<iframe title="Formally Unknown – Lotus Turbo" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/h_HpCpaY1J0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.rubadub.co.uk/records/many-any">Grab a copy at Rubadub</a></p>
Online Résumé (maxboeck on Github)2020-04-19T13:16:41Zhttps://fuzzylogic.me/posts/2020-04-19-maxboeckresume-an-online-resume/<p>A beautiful, responsive, print-friendly résumé template from <a href="https://mxb.dev/">Max</a>.</p>
<p>Some points of note:</p>
<ul>
<li>Accessible (WCAG AA)</li>
<li>uses the h-resume Microformat</li>
<li>uses a Spellcheck Linter</li>
<li>Search Engine Optimized (meta, JSON-LD, etc...)</li>
<li>Built with Eleventy</li>
<li>Netlify-ready (although hosting choice is up to you)</li>
<li>Critical CSS Inlined</li>
<li>Print Styles</li>
</ul>
We’ve ruined the Web. Here’s how we fix it. (This is HCD podcast)2020-04-17T08:54:40Zhttps://fuzzylogic.me/posts/2020-04-17-jeremy-keith-weve-ruined-the-web-heres-how-we-fix-it-this-is-hcd/<p>During the COVID situation, people have an urgent need to access critical information online. But in 2020, the average webpage is rammed full of large JavaScript files, huge images etc, and as a result is slow to load. This problem is likely to be most keenly felt by those who don’t have the luxury of fast internet – potentially the same people who need access to that critical information the most.</p>
<p>Here’s a brilliant discussion between <a href="https://gerrymcgovern.com/">Gerry McGovern</a> and <a href="https://adactio.com/">Jeremy Keith</a> on that problem, suggesting tactics to help fix things such as performance budgets, introducing tactics at the design stage to mimic slow connections and other access constraints, optimising for return visits, progressive enhancement and more.</p>
<p>Loved this!</p>
<p>(via <a href="https://twitter.com/adactio">@adactio</a>)</p>
2020-04-13T10:10:21Zhttps://fuzzylogic.me/posts/1586776200-title-frontend-developer-is-obsolete/<p>I have to reluctanctly agree on this one. I’ve interviewed quite a few candidates for “front-end developer” (or similarly named) positions over recent years and the recurring pattern is that they are strong on JavaScript (though not necessarily the right time to use it) and weak on HTML, CSS and the “bigger picture”.</p>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">🧵 It's time for our industry to realize the title "frontend developer" is obsolete. The vast majority of these profiles are actually "JS engineers", and they're usually quite good at it, but they're not as good at all the other things contributing to great frontend experiences.</p>— Benjamin De Cock (@bdc) <a href="https://twitter.com/bdc/status/1249597086007345157?ref_src=twsrc%5Etfw">April 13, 2020</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure>
2020-04-12T11:50:21Zhttps://fuzzylogic.me/posts/1586692200-use-emoji-as-favicon/<p>Here’s a neat trick. You can use an emoji as a favicon! I’ve written previously about how to do favicons properly, but for a short-lived hack project you tend to just need something quick and dirty. Chris Coyier has also shared <a href="https://000458870.codepen.website/">a nice lil’ Codepen website</a> showing the technique in action.</p>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Now that all modern browsers support SVG favicons, here's how to turn any emoji into a favicon.svg:<br /><br /><svg xmlns="<a href="https://t.co/TJalgdayix">https://t.co/TJalgdayix</a>" viewBox="0 0 100 100"><br /><text y=".9em" font-size="90">💩</text><br /></svg><br /><br />Useful for quick apps when you can't be bothered to design a favicon! <a href="https://t.co/S2F8IQXaZU">pic.twitter.com/S2F8IQXaZU</a></p>— Lea Verou (@LeaVerou) <a href="https://twitter.com/LeaVerou/status/1241619866475474946?ref_src=twsrc%5Etfw">March 22, 2020</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure>
Tooled Up: A brief history of SaaS tools we've loved (and lost) (FreeAgent Grinding Gears Blog)2020-04-12T11:26:38Zhttps://fuzzylogic.me/posts/2020-04-12-tooled-up-a-brief-history-of-saas-tools-weve-loved-and-lost-freeagent-grinding-gears-blog/<blockquote>
<p>I thought it might be interesting to look back through the years at how the tools in Engineering have changed as our company has grown from 3 to over 240 (and engineering to over 100), and to give a shout out to (some of!) those tools that we consider crucial to our workflow today – especially in these most unusual times where most of the world is working remotely.</p>
</blockquote>
<p>A great insight from FreeAgent CTO, Olly Heady, describing how the engineering team have benefitted from tools such as G Suite (Google Apps), Github, Trello, Datadog, Humio and Notion.</p>
grep.app2020-04-11T18:51:17Zhttps://fuzzylogic.me/posts/2020-04-11-grepapp/<blockquote>
<p>grep.app searches code from over a half million public repositories on GitHub.</p>
</blockquote>
<p>This could be useful when you’re struggling to use a certain new CSS property, or npm package, and want to see how other programmers are using it.</p>
Multiplayer Crosswords (chriszetter.com)2020-04-10T15:50:43Zhttps://fuzzylogic.me/posts/2020-04-10-several-people-are-solving-chriszettercom/<blockquote>
<p>I wanted there to be an easy way to complete crosswords together that didn’t need people to pass a phone back and forth or for a copy of the crossword to be made in a shared Google Spreadsheet.</p>
</blockquote>
<p><em>Several People are Solving</em> is a lovely <a href="https://github.com/zetter/react-crossword">React app</a> which started as a fork of The Guardian’s <em>Frontend</em> repo in order to further develop their crossword component.</p>
<p>See author <a href="https://chriszetter.com/blog/2018/12/02/multiplayer-crosswords/">Chris Zetter’s article</a> on how he then introduced WebSockets (within a Rails application) to facilitate real-time collaboration.</p>
<p>The crosswords are updated regularly so what are you waiting for? <a href="https://multicrosser.chriszetter.com/">Get solving!</a></p>
BEM Naming Cheat Sheet by 9elements2020-04-07T20:20:59Zhttps://fuzzylogic.me/posts/2020-04-07-bem-naming-cheat-sheet-by-9elements/<p>Here’s a handy resource providing BEM-based naming suggestions for some of the most common web components.</p>
<p>It includes sensible BEM naming for such common components as:</p>
<ul>
<li>Breadcrumb;</li>
<li>Button;</li>
<li>Card;</li>
<li>Navigation;</li>
<li>Tabs; and</li>
<li>Stack.</li>
</ul>
Finding participants for user research - Service Manual (GOV.UK)2020-04-07T08:10:44Zhttps://fuzzylogic.me/posts/2020-04-07-finding-participants-for-user-research-service-manual-govuk/<blockquote>
<p>It’s also important to do research with all the different kinds of people who may need your service, including those who: have disabilities or use assistive technologies; have limited digital skills or poor literacy; and may need help to use your service.</p>
</blockquote>
<p>Useful advice regarding user research from <a href="http://gov.uk/">GOV.uk</a> covering how to define participant criteria, find participants for research and handle incentives.</p>
<p>(via <a href="https://twitter.com/paddyduke">@paddyduke</a>)</p>
BEM Methodology2020-04-06T10:03:00Zhttps://fuzzylogic.me/posts/bem-methodology/<p>Documentation for the BEM component and CSS class-naming notation</p>
<blockquote>
<p>methodology BEM was invented at Yandex to develop sites which should be launched fast and supported for a long time. It helps to create extendable and reusable interface components.</p>
</blockquote>
How to get started with web development (Go Make Things)2020-04-04T14:27:53Zhttps://fuzzylogic.me/posts/2020-04-04-how-to-get-started-with-web-development-go-make-things/<p>Here’s <a href="https://gomakethings.com/">Chris Ferdinandi</a> with a list of resources to help those who are new to web development get started. I’m keeping this one handy so I can share it with any friends who’re thinking of getting into this game.</p>
Emergency Website Kit (Max Böck)2020-04-01T21:46:31Zhttps://fuzzylogic.me/posts/2020-04-01-emergency-website-kit-max-bock/<blockquote>
<p>In cases of emergency, many organizations need a quick way to publish critical information. But existing (CMS) websites are often unable to handle sudden spikes in traffic.</p>
</blockquote>
<p>Fantastic effort by Max Böck here, stepping up during the COVID-19 pandemic to provide this Eleventy template for organisations to use to publish critical information as lean, resilient, static HTML pages.</p>
How to create an accordion hover effect with box-shadows (Sarah L. Fossheim)2020-04-01T18:04:33Zhttps://fuzzylogic.me/posts/2020-04-01-how-to-create-an-accordion-hover-effect-with-boxshadows-sarah-l-fossheim/<blockquote>
<p>In this tutorial we'll use the box-shadow property to create a layered card component, and animate it on hover.</p>
</blockquote>
<p>Beautiful effects expertly combining colour, clever box-shadow configurations and position-based animation.</p>
CSS Triggers2020-03-30T08:04:49Zhttps://fuzzylogic.me/posts/2020-03-30-css-triggers/<p>Check whether or not a CSS property is a good candidate for smooth animation based on whether updates to its value trigger expensive changes (to, for example, “element geometry”) causing layout updates and repaints.<br />
<code>width</code> and <code>height</code> are both poor candidates whereas <code>transform</code> is good.</p>
4 Ways to Animate the Color of a Text Link on Hover | CSS-Tricks2020-03-30T07:56:20Zhttps://fuzzylogic.me/posts/2020-03-30-4-ways-to-animate-the-color-of-a-text-link-on-hover-or-csstricks/<blockquote>
<p>Let’s create a pure CSS effect that changes the color of a text link on hover – but slide that new color in instead of simply swapping colors.</p>
</blockquote>
<p>Katherines post explores four different techniques to achieve the effect, and their comparative pros and cons with regard to accessibility, performance, and browser support.</p>
<p>Technique 4, which uses a CSS <code>transform</code> seems to be the most flexible, best-performing and has best cross-browser support, however because it requires adding a semantically redundant <code><span></code> into the anchor I would use it sparingly rather than on all links by default.</p>
HTML attributes to improve your users’ two factor authentication experience (Twilio2020-03-30T07:28:45Zhttps://fuzzylogic.me/posts/2020-03-30-html-attributes-to-improve-your-users-two-factor-authentication-experience-twilio/<blockquote>
<p>In this post we have seen that with just a sprinkling of HTML attributes we can improve the login experience for our users, particularly on mobile devices.</p>
</blockquote>
<p>By adding certain attributes to the HTML <code>input</code> element – such as <code>inputmode</code>, <code>pattern</code> and <code>autocomplete="current-password"</code> – we can improve the user experience when logging in.</p>
Screen - Work together like you're in the same room2020-03-24T17:56:22Zhttps://fuzzylogic.me/posts/2020-03-24-screen-work-together-like-youre-in-the-same-room/<blockquote>
<p>Fast screen sharing with multiplayer control, drawing & video.</p>
</blockquote>
<p>An application which allows collaborating (and drawing) on files and could be useful for pair programming. Free during the current COVID-19 situation.</p>
<p>(via <a href="https://twitter.com/lylo">@lylo</a>)</p>
Block Links: A tricky UI Problem2020-03-12T09:18:02Zhttps://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/<p>You have a “card” component which includes a heading, some text, an image, and a link to the full article, and it’s working great. Then along comes a UX requirement that the <em>full card</em> (not just the button or link) should be clickable. This is where things get complicated.</p>
<h2 id="tl%3Bdr" tabindex="-1">TL;DR <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#tl%3Bdr" aria-hidden="true">#</a></h2>
<p>I was recently faced with this challenge while building a component at work and opted to implement a tailored version of Heydon Pickering’s <em>Redundant Click Trick</em>. This felt like the best approach, or perhaps more accurately “the lesser of three evils”. I’ll be monitoring how that performs, but in light of the knowledge and experience gained carrying out this task I’m also starting to think that – <a href="https://css-tricks.com/block-links-are-a-pain-and-maybe-just-a-bad-idea/">like Chris Coyier recently suggested</a> – maybe full-card clickable regions are a bad idea.</p>
<h2 id="setting-the-scene" tabindex="-1">Setting the Scene <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#setting-the-scene" aria-hidden="true">#</a></h2>
<p>Let’s say our starting HTML is this:</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Card Title<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/path/to/img.jpg<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This is the body copy for the card. It it is comprised of a few sentences.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Read more<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>And the requirement we’ve been given is to make the whole card clickable rather than just the “Read more” link.</p>
<h2 id="option-1%3A-stuff-everything-inside-an-anchor" tabindex="-1">Option 1: Stuff everything inside an anchor <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#option-1%3A-stuff-everything-inside-an-anchor" aria-hidden="true">#</a></h2>
<p>Here’s the thing – since the dawn of HTML5 we’ve been able to wrap the inline anchor (<code><a></code>) element around block-level content such as headings, paragraphs, and <code><div></code>s… so isn’t the answer just to do that?</p>
<figure>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Card Title<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/path/to/img.jpg<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This is the body copy for the card. It it is comprised of a few sentences.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
</figure>
<p>Well, as with many HTML challenges, just because you <em>can</em> do something doesn’t mean you should. I always had a nagging doubt about stuffing all that disparate content inside a single anchor, and <a href="https://adrianroselli.com/2020/02/block-links-cards-clickable-regions-etc.html">Adrian Roselli has recently confirmed</a> that for screen reader users this approach is harmful.</p>
<blockquote>
<p>Perhaps the worst thing you can do for a block link is to wrap everything in the <code><a href></code>… for a screen reader user the entire string is read when tabbing through controls… taking about 25 seconds to read before announcing it as a link.</p>
</blockquote>
<p>Furthermore, images nested in this way are not clearly announced as they normally would be.</p>
<p>So if you care about the user experience for those people, this feels like a no-no.</p>
<h3 id="option-2%3A-stretch-a-standard-anchor-using-pseudo-content" tabindex="-1">Option 2: Stretch a standard anchor using pseudo-content <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#option-2%3A-stretch-a-standard-anchor-using-pseudo-content" aria-hidden="true">#</a></h3>
<p>An alternate approach that’s gained traction over the last couple of years involves leaving the anchor or button in its initial position <em>within</em> the card (thereby avoiding the above mentioned accessibility problem) and using pseudo-content to stretch it to cover the entire card. This CSS-only trick involves setting the card to <code>position:relative</code> then giving the anchor (or button) <code>:after</code> pseudo-content and absolutely positioning that to the card’s four corners. This makes the whole card clickable like a button.</p>
<p>The problem with this approach is that any text in the card is no longer selectable.</p>
<p>Some might say that this is OK. Personally I feel that it is a fundamental usability requirement that text on a web page be selectable. Not being able to do so calls to mind the bad old days before web fonts where we used images for headings, and I like to think we’ve evolved from those kind of practices. Also, I feel any statement by us developers and designers that “losing the ability to select text is OK” lacks validity because we are <em>biased</em>; happy to justify taking away something fundamental from our users because we’re more concerned with getting a (frankly non-essential) feature over the line.</p>
<p>If we don’t like this compromise but are still determined to make the full card clickable, there’s one further option.</p>
<h3 id="option-3%3A-the-redundant-click-trick" tabindex="-1">Option 3: The Redundant Click Trick <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#option-3%3A-the-redundant-click-trick" aria-hidden="true">#</a></h3>
<p>This technique, conceived by Heydon Pickering, uses JavaScript rather than CSS to make the card clickable.</p>
<p>Essentially we add an <code>EventListener</code> for a click on the Card and when one is detected, trigger a faux click on the inner anchor or button.</p>
<p>One challenge inherent in this approach is that a user attempting to select text would unintentionally trigger our faux link click. However we can again use JavaScript (using the <code>onmousedown</code> and <code>onmouseup</code> events) to detect the length of their press to infer whether they are selecting text or clicking, then take appropriate action.</p>
<p>The pros of this approach are that we avoid the screen reader problems and the inability to select text.</p>
<p>The cons are i) that it requires a more complicated, JavaScript-based approach; and ii) that the need for a “check how long the mouse has been pressed down” part isn’t ideal.</p>
<p>With this approach, if Analytics tracking is part of your mix I’d make sure to check that that works as expected across browsers and devices.</p>
<h2 id="summing-up" tabindex="-1">Summing up <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#summing-up" aria-hidden="true">#</a></h2>
<p>So there we go – three ways to achieve a “block link” or button. But given the compromises they involve, perhaps the question should be – is it worth it? And given the tools we currently have available, I lean towards “no”.</p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/block-links-a-tricky-ui-problem/#references" aria-hidden="true">#</a></h2>
<p><a href="https://adrianroselli.com/2020/02/block-links-cards-clickable-regions-etc.html">Block Links, Cards, Clickable Regions etc</a> by Adrian Roselli.</p>
<p><a href="https://inclusive-components.design/cards/">Cards</a> by Heydon Pickering (in <em>Inclusive Components</em>).</p>
<p><a href="https://css-tricks.com/block-links-are-a-pain-and-maybe-just-a-bad-idea/">Block Links are a pain and maybe just a bad idea</a> by Chris Coyier on CSS-Tricks.</p>
Storm Music: February 2020 Records2020-03-08T09:30:00Zhttps://fuzzylogic.me/posts/feb-2020-record-purchases/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1581756788/Feb_2020_Record_Shopping_v3_v5f3zh.jpg" width="320" height="320" alt="Laurence’s record purchases in February 2020" loading="lazy" decoding="async" />
</figure>
<p>February ‘20 proved to be a challenging month on a number of fronts. As if storms <a href="https://www.bbc.co.uk/news/uk-51436720">Ciara</a> and <a href="https://youtu.be/XoPiZEmttwg">Dennis</a> weren’t enough to contend with, life chucked in some additional turbulence just for good measure.</p>
<p>So with nothing else for it than to batten down the hatches, I reached for some immersive ambience, restorative reggae and mood-enhancing electronics to help weather the storm.</p>
<p>As it turns out, records <em>really are</em> good for the soul and the forecast now looks much brighter.</p>
<p>So without further ado, let’s dig into last month’s haul.</p>
<h2 id="shida-shahabi-%E2%80%93-shifts-(lp)" tabindex="-1">Shida Shahabi – Shifts (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#shida-shahabi-%E2%80%93-shifts-(lp)" aria-hidden="true">#</a></h2>
<p>Amidst the rocky parts, February also provided a couple of nice moments. On a visit to Edinburgh’s <a href="https://www.timberyard.co/">Timberyard</a> (Clair’s birthday present – thanks pals!) we were treated not only to amazing food but also this memorable musical accompaniment; the perfect antidote to the arctic conditions outside. Swedish-Iranian pianist Shida’s melodies are hauntingly beautiful in their own right but interestingly she also overlays sounds from the inner mechanics of the piano. Modern classical isn’t normally my bag, but I love this (and the cover art, too).</p>
<p><b>Current Favourite Track:</b> Futo</p>
<div class="l-frame">
<iframe title="Shida Shahabi – Futo" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/Ctxp1lQcL9s" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://shida-shahabi.bandcamp.com/album/shifts">Grab a copy on Bandcamp</a></p>
<h2 id="bibio-%E2%80%93-ribbons-(lp)" tabindex="-1">Bibio – Ribbons (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#bibio-%E2%80%93-ribbons-(lp)" aria-hidden="true">#</a></h2>
<p>Okay, I’m late with this one – it was released in April ‘19 – but who cares. <em>Ribbons</em> has been a Spotify staple of my morning commute for some time; its pastoral vibes setting the perfect laid-back mood before a day writing code. Eventually I had to own a physical copy. The vibe is pretty folky and in places you can imagine being at a live jam session in your favourite traditional pub. Stephen Wilkinson is a fantastic musician with a lovely voice but if all this is sounding too <em>nice</em> then rest assured that, being on Warp Records, it’s served with a generous side-helping of analogue synths and quirky electronics to steer things left of centre.</p>
<p><b>Current Favourite Track:</b> Curls</p>
<div class="l-frame">
<iframe title="Bibio – Curls" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/Vx9_FIIH-UM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://bleep.com/release/123827-bibio-ribbons">Grab a copy on Bleep</a></p>
<h2 id="al-charles-%E2%80%93-outstanding" tabindex="-1">Al Charles – Outstanding <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#al-charles-%E2%80%93-outstanding" aria-hidden="true">#</a></h2>
<p>Who knew there was a reggae version of The Gap Band’s early eighties classic, <em>Outstanding</em>? Not me, anyway. This has been lovingly reissued by Edinburgh’s Athens of the North and features a great squelchy bassline, shimmering synths, dub FX and that killer, hooky vocal. And now I’ll hand over to Discogs legend <a href="https://www.discogs.com/user/midnightrunner">midnightrunner</a> whose review puts it much better than I ever could:</p>
<blockquote>
<p>Quite simply, "outstanding" reggae funk fusion! My mam's toyboy, Gavin, likes to play this one after I have gone to bed, when he smokes his special pipe full of jazzy cabbage.</p>
</blockquote>
<p><b>Current Favourite Track:</b> Outstanding</p>
<div class="l-frame">
<iframe title="Al Charles – Outstanding" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/ZQIkpRWjREU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.rubadub.co.uk/records/outstanding">Grab a copy at Rubadub</a></p>
<h2 id="logic1000-%E2%80%93-logic1000" tabindex="-1">Logic1000 – Logic1000 <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#logic1000-%E2%80%93-logic1000" aria-hidden="true">#</a></h2>
<p>Sydney–born, Melbourne–based producer Samantha Poulter aka Logic1000 is a new name on me. Her sound is a spacey, percussive blend of hip-hop, Bass, Dancehall and House, with all sorts of other interesting samples and influences thrown into the pot. Lots of great stuff on here.</p>
<p><b>Current Favourite Track:</b> Na feat. DJ Plead</p>
<div class="l-frame">
<iframe title="Logic1000 – Na feat. DJ Plead" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/5hLmiSjflSg" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.juno.co.uk/products/logic1000/759051-01/">Grab a copy at Juno</a></p>
<h2 id="perko-%E2%80%93-the-city-rings" tabindex="-1">Perko – The City Rings <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#perko-%E2%80%93-the-city-rings" aria-hidden="true">#</a></h2>
<p>I loved Glaswegian Perko’s first release, <em>NV Auto</em>; its blend of dubbed out synth chords, deep sub-bass and tough broken-electro beats really hitting the spot. His latest release, also on <a href="http://nmbrs.net/">Numbers</a>, ploughs a similar furrow. It spans 8 tracks including moments when he ratchets up the BPMs into Drum ‘n’ Bass territory and others offering respite in the form of delicate ambient interludes.</p>
<p><b>Current Favourite Track:</b> Stutter</p>
<div class="l-frame">
<iframe title="Perko – Stutter" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/ZZ10HO1KAps" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.rubadub.co.uk/records/the-city-rings">Grab a copy at Rubadub</a></p>
<h2 id="khruangbin-%E2%80%8E%E2%80%93-hasta-el-cielo-(lp)" tabindex="-1">Khruangbin – Hasta El Cielo (LP) <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#khruangbin-%E2%80%8E%E2%80%93-hasta-el-cielo-(lp)" aria-hidden="true">#</a></h2>
<p>This is the dub remix version of the Texas band’s second LP, <em>Con Todo El Mondo</em>. Released in 2019, I don’t know why I didn’t pick it up sooner given that I love Khruangbin and I love dub, except perhaps that records ain’t cheap and I wasn’t sure a remix LP constituted an essential purchase. However, after a few months of blissful headphone listening I realised the error of my ways. The band’s sound lends itself perfectly to this treatment and the addition of two mixes by legendary engineer Scientist seals the deal. Also – check this band live if you ever get the chance. I did <a href="https://www.theskinny.co.uk/music/live-music/reviews/khruangbin-cca-glasgow-4-feb">a couple of years back</a> and they were amazing.</p>
<p><b>Current Favourite Track:</b> Four of Five</p>
<div class="l-frame">
<iframe title="Khruangbin – Four of Five" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/i2keZMh7x9w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://khruangbin.bandcamp.com/album/hasta-el-cielo-con-todo-el-mundo-in-dub-excluding-n-s-america">Grab a copy on Bandcamp</a></p>
<h2 id="lo-kindre-%E2%80%93-chlorophytum" tabindex="-1">Lo Kindre – Chlorophytum <a class="direct-link" href="https://fuzzylogic.me/posts/feb-2020-record-purchases/#lo-kindre-%E2%80%93-chlorophytum" aria-hidden="true">#</a></h2>
<p>This has been on my wants list for an age but every time I tried to get a copy last year, I couldn’t find one. I’m not sure if the original release was maybe delayed? Fortunately on a recent visit to Rubadub (all too infrequent these days which I mean to rectify) the guys hooked me up. This is on the slow, low and out-there electronic tip with little Kraftwerkian influences in amongst the haze of dub. Apparently it’s also from the south side of Glasgow so if I ever see this dude in the Allison Arms I should jolly well like to buy him a pint. Lovely sleeve art too.</p>
<p><b>Current Favourite Track:</b> I Don’t Really</p>
<div class="l-frame">
<iframe title="Lo Kindre – I Don’t Really" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/iN9I3TPG12w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.rubadub.co.uk/records/chlorophytum">Grab a copy at Rubadub</a></p>
HTML: The Inaccessible Parts (daverupert.com)2020-03-03T14:46:39Zhttps://fuzzylogic.me/posts/2020-03-03-html-the-inaccessible-parts-daverupertcom/<p>Here’s Dave Rupert, frustratedly rounding up the accessibility shortfalls in browser implementations of native HTML elements.</p>
<blockquote>
<p>I’ve always abided in the idea that “HTML is accessible by default and then we come along and mess it up”. But that’s not always the case. There are some cases where even using plain ol’ HTML causes accessibility problems.</p>
</blockquote>
<p>(via <a href="https://twitter.com/jamesmockett">@jamesmockett</a>)</p>
David Heinemeier Hansson, Software Contrarian (CoRecursive Podcast)2020-03-02T21:24:34Zhttps://fuzzylogic.me/posts/2020-03-02-david-heinemeier-hansson-software-contrarian-corecursive-podcast/<p>Since November 2019 my day job has involved working on a “Majestic Monolith” coded in Ruby on Rails. I loved this conversation with Rails’ creator <abbr title="David Heinemeier Hansson">DHH</abbr> in which he speaks with great passion and makes interesting points about finding a programming language that speaks to you; why single page apps and microservices are not for him; and how our working days have too many interruptions.</p>
Fixing Github Command Line Authentication Issues2020-03-02T09:04:56Zhttps://fuzzylogic.me/posts/fixing-github-command-line-authentication-issues/<p>On at least two ocassions I’ve found myself scratching my head when an attempted push to a newly-created Github repo is met with authentication failures, despite me being sure I’m using the correct credentials.</p>
<p>Here’s the lowdown on the issue and how to resolve it.</p>
<p>Essentially the problem relates to Github expecting a <em>personal access token</em> rather than a password (although it provides no helpful hints that this is the case).</p>
<p>This might be because your Github account has <abbr title="Two-Factor Authentication">2FA</abbr> enabled, and/or for security purposes because your account is part of an organisation that uses SAML single sign-on (SSO).</p>
<p>In my case, I had previously created a personal access token with the requisite privileges (in my Github account’s <a href="https://github.com/settings/tokens">Developer Settings > Tokens</a> section) for the purposes of API access, so I was able to just reuse that. However, if need be I could have created a new one.</p>
<p>Thanks to Ginny Fahs who had the same problem and <a href="https://medium.com/@ginnyfahs/github-error-authentication-failed-from-command-line-3a545bfd0ca8">documented her solution</a>.</p>
<p>Github’s Help page <a href="https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line">Creating a personal access token for the command line</a> is also useful.</p>
2020-03-01T14:11:21Zhttps://fuzzylogic.me/posts/1583071733-jake-archibaldserver-and-client-render-should-not-be-the-same/<p>In the same vein as Jeremy Keith’s recent blog post, <a href="https://adactio.com/journal/16404">Hydration</a>, which calls out some of the performance and user experience problems associated with current <em>Server Side Rendering</em> approaches, I think Jake Archibald is absolutely bang on the money here.</p>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">The server and client render should not be 1:1.<br /><br />Don't render buttons on the server that require JS to work.<br /><br />Don't ship code to the client that simply repeats what the server has already done.</p>— Jake Archibald (@jaffathecake) <a href="https://twitter.com/jaffathecake/status/1230388412806520833?ref_src=twsrc%5Etfw">February 20, 2020</a></blockquote> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure>
2020-02-29T22:32:00Zhttps://fuzzylogic.me/posts/1583015556-just-a-boys-game/<p>Every time I watch nostalgic TV documentaries about Scottish films I see <em>Just a Boys’ Game</em> and <em>Just Another Saturday</em> – both written by Peter McDougall – come up. I just watched <em>Just a Boys’ Game</em> (<a href="https://play.google.com/store/tv/show?id=_bzLqTe-WRBxrpWy_fmy_A&cdid=tvseason-qaN9iaVu8JDd3aM-jtghkg&gdid=tvepisode-1zSwUxBSlf8">available on Google Play</a>) and loved it. Set in 1979 Glasgow, this is a gritty story with refreshingly good acting that really captures the finer points of the social and economic mood of the time.</p>
<div class="l-frame">
<iframe title="Clip of TV programme “Just a Boys’ Game”" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/WsVYudrpriI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
Why the GOV.UK Design System team changed the input type for numbers (Technology in Government)2020-02-28T12:28:46Zhttps://fuzzylogic.me/posts/2020-02-28-why-the-govuk-design-system-team-changed-the-input-type-for-numbers-technology-in-government/<blockquote>
<p>Using <code><input type="text" inputmode="numeric" pattern="[0-9]*"></code> (instead of <code><input type="number"</code>) allows for a degree of separation between how the user enters data (“input mode”), what the browser expects the user input to contain (type equals number), and potentially how it tries to validate it.</p>
</blockquote>
<p>An interesting post from the UK Government listing a host of usability and accessibility problems arising from using <code><input type="number"></code>.</p>
<p>Now that browser support for the <code>inputmode</code> attribute is sufficient, they have moved to <code><input type="text" inputmode="numeric"></code>.</p>
<p>I trust <a href="http://gov.uk/">GOV.UK</a>’s opinion and think I’ll follow suit.</p>
Are My Colours Accessible?2020-02-28T11:11:30Zhttps://fuzzylogic.me/posts/2020-02-28-are-my-colours-accessible/<blockquote>
<p>Colour contrast and the use of colour is extremely important for certain groups of people with varying levels of visional impairment. Building upon the excellent Colorable, I wanted more context around the result. When you share the outcome with your colleagues, all the results, rules and what you’re aiming for, is easily understandable for when you have those awkward conversations with designers and marketers. Accessibility doesn’t have to be ugly.</p>
</blockquote>
<p>An excellent, easy to use tool for checking text-against-background contrast for accessibility and sharing your results with others.</p>
<p>(via <a href="https://twitter.com/paddyduke">@paddyduke</a>)</p>
The Contrast Triangle2020-02-27T12:26:39Zhttps://fuzzylogic.me/posts/2020-02-27-the-contrast-triangle/<blockquote>
<p>Removing underlines from links in HTML text presents an accessibility challenge. In order for a design to be considered accessible, there is now a three-sided design contraint - or what I call "The Contrast Triangle". Your text, links and background colors must now all have sufficient contrast from each other. Links must have a contrast ratio of 3:1 from their surrounding text. By not using underlines, a design has to rely on contrast alone to achieve this.</p>
</blockquote>
<p>It’s interesting that Chip says that this level of contrast is needed “when we don’t use underlines on links”.</p>
<blockquote>
<p>By not using underlines, a design has to rely on contrast alone to achieve this.</p>
</blockquote>
<p>So this seems to be yet another good reason to include underlines in links, i.e. if you underline your links then you don’t need to worry quite as much about a third level of contrast.</p>
<p>Indeed, when you toggle on the “Show underlines” option on this tool, it then removes the requirement to ensure additional contrast between hyperlinks and standard body text.</p>
<p>However, even if your links in flowing prose are underlined, there’s always likely to be places (Navigation, Footer, CTAs etc) where you’ve probably disabled underlines on links for design effect, so I reckon this is useful for most websites.</p>
<p>(via <a href="https://twitter.com/jamesmockett">https://twitter.com/jamesmockett</a>)</p>
BBC GEL Inclusive Components Technical Guide2020-02-24T22:09:18Zhttps://fuzzylogic.me/posts/2020-02-24-bbc-gel-inclusive-components-technical-guide/<blockquote>
<p>The BBC Global Experience Language (GEL) Technical Guides are a series of framework-agnostic, code-centric recommendations and examples for building GEL design patterns in websites. They illustrate how to create websites that comply with all BBC guidelines and industry best practice, giving special emphasis to accessibility.</p>
</blockquote>
<p>Heydon Pickering (author of <em>Inclusive Components</em> and co-creator of <em>Every Layout</em>) has implemented and documented over 25 of the BBC's design patterns. These are sure to be loaded with best practices and clever tricks for making resilient, accessible modern UI components. (via <a href="https://twitter.com/heydonworks">@heydonworks</a>)</p>
My Codepen Cheatsheet2020-02-24T20:52:08Zhttps://fuzzylogic.me/posts/my-codepen-cheatsheet/<p>I’m finding Codepen to be more and more valuable not only for testing out new code and ideas, but also – when working on large applications – as a time-saving rapid prototyping environment which sidesteps the overhead of back-end set-up. Here are some tips which I’ve found useful, for future reference.</p>
<h2 id="control-the-editor-view-layout" tabindex="-1">Control the Editor View layout <a class="direct-link" href="https://fuzzylogic.me/posts/my-codepen-cheatsheet/#control-the-editor-view-layout" aria-hidden="true">#</a></h2>
<p>Append <code>/left/</code>, <code>/right/</code>, or <code>/top/</code> to the URL to set the editor layout.</p>
<p>Append <code>?editors=1111</code> (change numbers as appropriate) to the URL to set which panels are maximised (in order of HTML, CSS, JavaScript, and console).</p>
<p>For example:</p>
<p><a href="https://codepen.io/fuzzylogicx/pen/BEEYQL/left/?editors=1100">https://codepen.io/fuzzylogicx/pen/BEEYQL/left/?editors=1100</a></p>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/my-codepen-cheatsheet/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://blog.codepen.io/documentation/url-extensions/">https://blog.codepen.io/documentation/url-extensions/</a></li>
<li><a href="https://blog.codepen.io/documentation/adding-external-resources/">Adding external resources to a pen</a></li>
<li><a href="https://blog.codepen.io/documentation/es-modules-on-codepen/">ES Modules on codepen</a></li>
<li><a href="https://www.hongkiat.com/blog/codepen-tips-beginners/">https://www.hongkiat.com/blog/codepen-tips-beginners/</a></li>
</ul>
My VS Code Cheatsheet2020-02-24T09:58:08Zhttps://fuzzylogic.me/posts/my-vscode-cheatsheet/<p>Here’s a list of useful (Mac-based) VS Code tips for my reference and yours.</p>
<h2 id="use-the-command-palette" tabindex="-1">Use the Command Palette <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#use-the-command-palette" aria-hidden="true">#</a></h2>
<p><kbd>Command-Shift-P</kbd></p>
<p>Then type your search term, for example “settings”.</p>
<h2 id="settings" tabindex="-1">Settings <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#settings" aria-hidden="true">#</a></h2>
<p>My preferences (in <code>settings.json</code> or via Preferences→Settings):</p>
<figure>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"workbench.editor.showTabs"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br /> <span class="token property">"editor.formatOnSave"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br /> <span class="token property">"explorer.confirmDragAndDrop"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"editor.minimap.enabled"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"extensions.ignoreRecommendations"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"explorer.compactFolders"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"explorer.autoReveal"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"editor.accessibilitySupport"</span><span class="token operator">:</span> <span class="token string">"off"</span><span class="token punctuation">,</span><br /> <span class="token property">"ruby.codeCompletion"</span><span class="token operator">:</span> <span class="token string">"rcodetools"</span><span class="token punctuation">,</span><br /> <span class="token property">"emmet.includeLanguages"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token property">"nunjucks"</span><span class="token operator">:</span> <span class="token string">"html"</span><span class="token punctuation">,</span><br /> <span class="token property">"erb"</span><span class="token operator">:</span> <span class="token string">"html"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token property">"emmet.triggerExpansionOnTab"</span><span class="token operator">:</span> <span class="token boolean">true</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Note: the Emmet ones are <em>really</em> useful for code autocompletion.</p>
<h2 id="additional-emmet-settings" tabindex="-1">Additional Emmet Settings <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#additional-emmet-settings" aria-hidden="true">#</a></h2>
<p>To add a keyboard shortcut for adding an arbitrary wrapper element (say, <code>div.wrap</code>) around some selected code:</p>
<p>Open the Command Palette then search “emmet wrap”. When you see the option “Emmet: wrap with abbreviation”, click the settings icon beside it. Enter your preferred keyboard shortcut. I currently use:</p>
<p><kbd>Command-Shift-A</kbd></p>
<h2 id="open-current-terminal-directory-in-vs-code" tabindex="-1">Open current terminal directory in VS Code <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#open-current-terminal-directory-in-vs-code" aria-hidden="true">#</a></h2>
<figure>
<pre class="language-bash"><code class="language-bash">code <span class="token builtin class-name">.</span></code></pre>
</figure>
<h2 id="toggle-terminal" tabindex="-1">Toggle Terminal <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#toggle-terminal" aria-hidden="true">#</a></h2>
<p><kbd>Ctrl-`</kbd></p>
<h2 id="toggle-sidebar-visibility" tabindex="-1">Toggle sidebar visibility <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#toggle-sidebar-visibility" aria-hidden="true">#</a></h2>
<p><kbd>Command-B</kbd></p>
<h2 id="edit-multiple-rows-simultaneously" tabindex="-1">Edit multiple rows simultaneously <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#edit-multiple-rows-simultaneously" aria-hidden="true">#</a></h2>
<p>Select one instance of the text that appears in multiple locations. Use <kbd>Command-D</kbd> to select all, then edit.</p>
<h2 id="open-file-to-side-(for-side-by-side-editing)" tabindex="-1">Open file to side (for side-by-side editing) <a class="direct-link" href="https://fuzzylogic.me/posts/my-vscode-cheatsheet/#open-file-to-side-(for-side-by-side-editing)" aria-hidden="true">#</a></h2>
<p><kbd>Option–click</kbd> on a file in the Explorer.</p>
Bobby Gillespie remembers Andrew Weatherall (The Guardian)2020-02-23T15:56:50Zhttps://fuzzylogic.me/posts/2020-02-23-bobby-gillespie-remembers-andrew-weatherall-he-was-a-true-bohemian-the-guardian/<blockquote>
<p>I think of him as a true bohemian; he made etchings, he wrote, he read a lot. Andrew always had a book on the go, maybe two. I remember he gave me his copy of Hunger by Knut Hamsun when I told him I hadn’t read it. There was this other side to him that was deep, curious, well-read. I guess he was a classic autodidact, hungry for knowledge.</p>
</blockquote>
<p>Over the last week, the UK music scene has been remembering Andrew Weatherall who sadly died aged only 56.</p>
<p>Bobby Gillespie’s tribute recalls how Weatherall was a fan of some of Primal Scream’s unfashionable songs before he transformed their fortunes with his production on <em>Loaded</em> and <em>Screamadelica</em>, and provides an insight into an outsider with a big heart. (via <a href="https://twitter.com/SoundClashVic">@SoundClashVic</a>)</p>
You Don't Need2020-02-23T11:09:51Zhttps://fuzzylogic.me/posts/2020-02-23-you-dont-need/<p>A nice list of tips and tools on how to use simpler browser standards and APIs to avoid the added weight of unnecessary JavaScript and libraries.</p>
<p>Lodash, Moment and other similar libraries are <em>expensive</em> and we don’t always need them. This Github repo contains a host of nice tips, snippets and code–analysing tools.</p>
<p>One cautionary note regarding the idea of replacing JS with CSS: although the idea of using CSS rather than JavaScript for components like tabs and modals seems nice at first, it doesn’t properly consider that we often <em>need</em> JS for reasons of accessibility, in order to apply the correct aria attributes when the state of a UI component is modified.</p>
<p>Via Will Matthewson at work (FreeAgent) during our group conversation on JavaScript strategy.</p>
Hydration (Adactio: Journal)2020-02-16T17:01:09Zhttps://fuzzylogic.me/posts/2020-02-16-adactio-journalhydration/<blockquote>
<p>The situation we have now is the worst of both worlds: server-side rendering followed by a tsunami of hydration. It has a whiff of progressive enhancement to it (because there’s a cosmetic separation of concerns) but it has none of the user benefits.</p>
</blockquote>
<p>Jeremy Keith notes that these days JavaScript frameworks like React can be used in different ways: not solely for creating an SPA or for complex client-site state management, but perhaps for JavaScript that is run on the server. A developer might choose React because they like the way it encourages modularity and componentisation. This could be a good thing if frameworks like Gatsby and <span class="nobreak">Next.js</span> were to use progressive enhancement properly.</p>
<p>In reality, the system of <em>server-side rendering</em> of non-interactive HTML that is reliant on a further payload of JavaScript for <em>hydration</em> leads to an initial loading experience that is “jagged and frustrating”.</p>
<p>Jeremy argues that this represents a worst-of-both-worlds situation and that its alleged “progressive enhancement via improved separation of concerns” is missing the point.</p>
<blockquote>
<p>Hope is on the horizon for React in the form of partial hydration. I sincerely hope that it will become the default way of balancing server-side rendering with just-in-time client-side interaction.</p>
</blockquote>
<p>(via <a href="https://twitter.com/adactio">@adactio</a>)</p>
Old CSS, new CSS (eev.ee)2020-02-10T22:39:43Zhttps://fuzzylogic.me/posts/2020-02-10-old-css-new-css-eevee/<blockquote>
<p>I first got into web design/development in the late 90s, and only as I type this sentence do I realize how long ago that was. Here’s a history of CSS and web design, as I remember it.</p>
</blockquote>
<p>A fantastic and amusing account of how we progressed from no CSS (the early days of font tags, inline styles and tables for layout), through bad browsers, untold hacks and browser prefixes, to the relative luxury of today’s tools such as Flexbox and CSS Grid.</p>
Record Shopping, January 20202020-02-08T10:30:00Zhttps://fuzzylogic.me/posts/jan-2020-record-purchases/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1581756788/jan_2020_record_shopping_v6_x7rfb5.jpg" width="320" height="180" alt="Laurence’s record purchases in January 2020" loading="lazy" decoding="async" />
</figure>
<p>Last month’s vinyl haul included brand new music, a couple of great releases I’d missed in 2019, and some killer reissues.</p>
<p>Let’s dive in.</p>
<h2 id="sleep-d-%E2%80%93-rebel-force" tabindex="-1">Sleep D – Rebel Force <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#sleep-d-%E2%80%93-rebel-force" aria-hidden="true">#</a></h2>
<p>I’ve noticed that a lot of my recent favourites are from Australia: artists like Ewan Jansen, Rings Around Saturn and Turner Street Sound; labels like Ken Oath Records. This LP from Sleep D – who contributed <em>Connexion Dub</em> on the excellent <a href="https://www.discogs.com/Various-Sweet-Echoes-Vol-1-/release/12873209">Sweet Echoes Vol 1</a> – was produced in Melbourne but released on Anthony Naples’ NY-based Incensio label toward the end of 2019. It’s on the deep, heady techno and electro tip (but also features a lush house remix from Kuniyuki) and has been getting some plays from Hessle Audio luminaries Ben UFO and Joe.</p>
<p><b>Current Favourite Track:</b> Twin Turbo</p>
<div class="l-frame">
<iframe title="Sleep D – Twin Turbo" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/IpvqnMpaV28" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.discogs.com/sell/release/14298261?ev=rb">Grab a copy on Discogs</a></p>
<h2 id="bella-vista-%E2%80%93-mister-wong" tabindex="-1">Bella Vista – Mister Wong <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#bella-vista-%E2%80%93-mister-wong" aria-hidden="true">#</a></h2>
<p>Originally released in 1982, this electronic pop oddity has been reissued by <span class="nobreak">Adelaide</span>-based label Isle of Jura. The original with its quirky vocals, synths and guitars is a bit like a French <em>Genius of Love</em>, while there’s also a lovely stripped-back and effects-laden dub version.</p>
<p><b>Current Favourite Track:</b> Disco Dub (Jura Soundsystem Extended Edit)</p>
<div class="l-frame">
<iframe title="Bella Vista – Mister Wong" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/b9zHwx-i7KM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://isleofjura.bandcamp.com/album/mister-wong-2">Grab a copy on Bandcamp</a></p>
<h2 id="roy-ayers-%E2%80%93-searching-%2F-one-sweet-love-to-remember" tabindex="-1">Roy Ayers – Searching / One Sweet Love To Remember <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#roy-ayers-%E2%80%93-searching-%2F-one-sweet-love-to-remember" aria-hidden="true">#</a></h2>
<p>Vibes legend Roy Ayers’ 1976 rare groove classic <em>Searching</em> gets a welcome 7″ reissue from UK label Dynamite Cuts. <em>One Sweet Love</em> on the flip – also from the Vibrations LP – sees Roy in more upbeat mode with great swinging, syncopated drums.</p>
<p><b>Current Favourite Track:</b> Searching</p>
<div class="l-frame">
<iframe title="Roy Ayers – Searching" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/vc48ITjETAk" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://dynamitecuts.bandcamp.com/album/searching-no-digital">Grab a copy on Bandcamp</a></p>
<h2 id="oscar-weathers-%E2%80%93-we're-running-out-of-time-%2F-countdown" tabindex="-1">Oscar Weathers – We're Running Out Of Time / Countdown <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#oscar-weathers-%E2%80%93-we're-running-out-of-time-%2F-countdown" aria-hidden="true">#</a></h2>
<p>A stellar slice of reissued eighties electrofunk which I heard while tuned in to 6Music. The original is a much-sought after rarity but fortunately it’s now available once again thanks to Fantasy Love Records. It features a cool vocal accompanied by Funkadelic-style synths, live bass and horns, resulting in something pretty unique.</p>
<p><b>Current Favourite Track:</b> We're Running Out Of Time</p>
<div class="l-frame">
<iframe title="Oscar Weathers – We're Running Out Of Time" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/7THzYjrjTbc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://fantasyloverecords.bandcamp.com/album/were-running-out-of-time-countdown">Grab a copy on Bandcamp</a></p>
<h2 id="skinshape-%E2%80%8E%E2%80%93-i-didn't-know" tabindex="-1">Skinshape – I Didn't Know <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#skinshape-%E2%80%8E%E2%80%93-i-didn't-know" aria-hidden="true">#</a></h2>
<p>A lovely 7″ slab of dubbed out, psychedelic soul from Will Dorey aka <em>Skinshape</em>, whose work I first encountered on the <a href="https://www.discogs.com/Stally-The-Breadwinners-Skinshape-Riddim-Box-Dub-Soul-Groove/release/4772794">Riddim Box Dub / Soul Groove</a> release on Horus back in 2013. The version of <em>I Didn’t Know</em> I heard first (on Gilles Peterson’s radio show) is the dub, however I’m warming to the vocal too. I’ve also noticed that he’s <a href="https://www.discogs.com/artist/3395378-Skinshape">released a few albums</a> which I plan to check out.</p>
<p><b>Current Favourite Track:</b> IDK Dub</p>
<div class="l-frame">
<iframe title="Skinshape – IDK Dub" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/AV26TeS1nfA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.discogs.com/sell/release/14263749?ev=rb">Grab a copy on Discogs</a></p>
<h2 id="benoit-b-%E2%80%93-caution-9%E2%80%B26%E2%80%B3-high" tabindex="-1">Benoit B – Caution 9′6″ High <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#benoit-b-%E2%80%93-caution-9%E2%80%B26%E2%80%B3-high" aria-hidden="true">#</a></h2>
<p>Another excellent release from Edinburgh’s Unthank (sister label of Firecracker) featuring four tracks ranging in style from oddball electronics to more dancefloor-oriented electro.</p>
<p><b>Current Favourite Track:</b> Coconut Groove</p>
<div class="l-frame">
<iframe title="Benoit B – Caution 9′6″ High" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/gjan4jxZgD8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://boomkat.com/products/unthank-13-caution-9-6-high">Grab a copy at Boomkat</a></p>
<h2 id="various-%E2%80%8E%E2%80%93-db12-002" tabindex="-1">Various – DB12 002 <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#various-%E2%80%8E%E2%80%93-db12-002" aria-hidden="true">#</a></h2>
<p>Obscure and limited various artists release from Rimini-based label Duca Bianco, featuring a variety of electronic sounds; some poppier than others. The track <em>Sequence Fiction</em> I bought it for is a 100 BPM chugging John Carpenter-esque instrumental that came to my attention via <a href="https://soundcloud.com/crackmagazine/2019-mix-joe">Joe’s excellent mix for Crack Magazine</a> (appearing at <a href="https://soundcloud.com/crackmagazine/2019-mix-joe#t=7:05">7:05</a>).</p>
<p><b>Current Favourite Track:</b> Guillaume De Bois – <em>Sequence Fiction</em></p>
<iframe loading="lazy" width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/731346844&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
<p><a href="https://www.juno.co.uk/products/indovina-key-guillaume-des-bois-db12-002/730858-01/">Grab a copy on Juno</a></p>
<h2 id="joy-o-%E2%80%93-slipping" tabindex="-1">Joy O – Slipping <a class="direct-link" href="https://fuzzylogic.me/posts/jan-2020-record-purchases/#joy-o-%E2%80%93-slipping" aria-hidden="true">#</a></h2>
<p>I’m really enjoying Joy Orbison’s journey as a producer and loved the 2018 7″ <em>Diamonds</em> under his Sin Falta pseudonym. This occupies a similar glitchy and heady space and showcases some really interesting sounds and ideas while still having enough oomph for DJs and dancefloors of taste.</p>
<div class="l-frame">
<iframe title="Joy O – Burn" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/dMRMZLqlVaw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://www.discogs.com/sell/release/14364496?ev=rb">Grab a copy on Discogs</a></p>
Testing Stimulus Controllers2020-02-06T23:47:51Zhttps://fuzzylogic.me/posts/testing-stimulus-controllers/<p>Stimulus JS is great but doesn’t provide any documentation for testing controllers, so here’s some of my own that I’ve picked up.</p>
<h2 id="required-3rd-party-libraries" tabindex="-1">Required 3rd-party libraries <a class="direct-link" href="https://fuzzylogic.me/posts/testing-stimulus-controllers/#required-3rd-party-libraries" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://jestjs.io/">jest</a></li>
<li><a href="https://github.com/testing-library/jest-dom">jest-dom</a></li>
</ul>
<h2 id="basic-test" tabindex="-1">Basic Test <a class="direct-link" href="https://fuzzylogic.me/posts/testing-stimulus-controllers/#basic-test" aria-hidden="true">#</a></h2>
<figure>
<pre class="language-js"><code class="language-js"><span class="token comment">// hello_controller.test.js</span><br /><span class="token keyword">import</span> <span class="token punctuation">{</span> Application <span class="token keyword">as</span> StimulusApp <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"stimulus"</span><span class="token punctuation">;</span><br /><span class="token keyword">import</span> HelloController <span class="token keyword">from</span> <span class="token string">"path/to/js/hello_controller"</span><span class="token punctuation">;</span><br /><br /><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">"HelloController"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// Insert the HTML and register the controller</span><br /> document<span class="token punctuation">.</span>body<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><br /> <div data-controller="hello"><br /> <input data-target="hello.name" type="text"><br /> <button data-action="click->hello#greet"><br /> Greet<br /> </button><br /> <span data-target="hello.output"><br /> </span><br /> </div><br /> </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /> StimulusApp<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token string">'hello'</span><span class="token punctuation">,</span> HelloController<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"inserts a greeting using the name given"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> helloOutput <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">"[data-target='hello.output']"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> nameInput <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">"[data-target='hello.name']"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> greetButton <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Change the input value and click the greet button</span><br /> nameInput<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token string">"Laurence"</span><span class="token punctuation">;</span><br /> greetButton<span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Check we have the correct greeting</span><br /> <span class="token function">expect</span><span class="token punctuation">(</span>helloOutput<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveTextContent</span><span class="token punctuation">(</span><span class="token string">"Hello, Laurence!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
</figure>A new technique for making responsive, JavaScript-free charts (DEV Community)2020-02-06T18:46:29Zhttps://fuzzylogic.me/posts/2020-02-06-a-new-technique-for-making-responsive-javascriptfree-charts-dev-community/<blockquote>
<p>I wanted to see if it was possible to create SVG charts that would work without JS. Well, it is. I've also created an experimental Svelte component library called Pancake to make these techniques easier to use.</p>
</blockquote>
<p>A lovely modern, progressively-enhanced approach to data visualisation that uses primarily SVG, HTML and CSS but can be enhanced with JavaScript for Node-based generation or client-side interactivity, if required. (via <a href="https://twitter.com/jamesmockett">@jamesmockett</a>)</p>
Let’s Learn Eleventy! (with Zach Leatherman) - Learn With Jason (YouTube)2020-02-02T10:44:27Zhttps://fuzzylogic.me/posts/2020-02-02-lets-learn-eleventy-with-zach-leatherman-learn-with-jason-youtube/<div class="l-frame">
<iframe title="Let’s Learn Eleventy with Jason Lengstorf" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/j8mJrhhdHWc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p>A great tutorial video on Eleventy by Jason Lengstorf with guest Zach Leatherman, creator of Eleventy.</p>
<p>I already know Eleventy pretty well – in fact this site is built with Eleventy. But you always pick up lots of great tips by watching the people who <em>really</em> know their way around the software.</p>
<p>(via <a href="https://twitter.com/jlengstorf">@jlengstorf</a>)</p>
RegExr: Learn, Build, and Test RegEx2020-01-29T21:20:06Zhttps://fuzzylogic.me/posts/2020-01-29-regexr-learn-build-and-test-regex/<blockquote>
<p>RegExr is an online tool to learn, build, & test Regular Expressions.</p>
</blockquote>
<p>This handy, interactive tool is a bit like <a href="https://www.getpostman.com/">Postman</a> but for RegEx. You can create RegEx patterns and save them for easy retrieval later.</p>
<p>I also like the way you can start by making a list of example text strings you want your pattern to i) match and ii) not match before starting work on your RegEx pattern, adopting a sort-of “Test Driven RegEx” approach.</p>
2020-01-18T22:00:00Zhttps://fuzzylogic.me/posts/1579384800-the-farewell/<p>Clair and I just watched <em>The Farewell</em>, a comedy-drama film written and directed by Lulu Wang starring Awkwafina and Zhao Shuzhen, and really enjoyed it. Interesting/difficult subject matter and really nicely done. If you need a break from grisly murder cases etc then I can heartily recommend it.</p>
<div class="l-frame">
<iframe title="Official Trailer for movie “The Farewell”" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/RofpAjqwMa8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
BBC Four - Primal Scream: The Lost Memphis Tapes2020-01-17T07:51:26Zhttps://fuzzylogic.me/posts/2020-01-17-bbc-four-primal-scream-the-lost-memphis-tapes/<blockquote>
<p>The sessions recorded by the band in Memphis with the legendary record producer Tom Dowd, along with the Muscle Shoals Rhythm Section musicians Roger Hawkins, drums, and David Hood, bass, did not make the light of day, because some of the mixes were not suitable in the musical climate at the time.</p>
</blockquote>
<p>A great watch telling an unlikely, touching and at times hilarious story of how the Glasgow band temporarily escaped the madness of the early 90’s scene for Memphis to record an album which was out of step with the time and only revealed its true quality with the benefit of hindsight and maturity.</p>
<p>The production on The Memphis Sessions sounded absolutely amazing and there are some great vinyl mastering scenes for those – like myself – who are into that kind of thing!</p>
<p>On the strength of this, I think Clair and I will grab a copy of the record.</p>
2020-01-16T18:26:58Zhttps://fuzzylogic.me/posts/1579199160-trio-of-bus-mishaps/<p>As I got on my usual bus from Stockwell St to Vic Rd this eve, I noticed it was the same driver whose bus I’d taken twice last week and both times it had broken down – that’s two days in a row – leaving me to walk home in the usual January post-apocalyptic shitstorm. I got on his bus today and no sooner was it 200 yards down the road than it crashed into a taxi, across from Marks and Sparks. Everybody out – again. That’s 3 times I’ve been on his bus, and three times it’s broken down for one reason or another. The shittest hat-trick ever 😂. I need to find out this guy’s name so I can never get on a plane with him.</p>
Not every Design System Pattern should be represented by a component (CSS-Tricks)2020-01-14T09:09:08Zhttps://fuzzylogic.me/posts/2020-01-14-not-every-design-pattern-in-a-design-system-should-be-represented-by-a-component/<blockquote>
<p>My point with all this is that it’s easy to see every problem or design as a new component or a mix of currently existing components. But instead, we should make components that can slot into each other neatly, rather just continue to make more components.</p>
</blockquote>
<p>An interesting observation from Robin Rendle who leads Gousto’s design system.</p>
<blockquote>
<p>Not every design pattern in a Design System should be represented by a code-based component.</p>
</blockquote>
<p>His example is of the common link-with-icon pattern (but the theory could be applied elsewhere).</p>
<p>Gousto already had <code><Link /></code> and <code><Icon /></code> components, each with their own relevant props (e.g <code>name</code> etc) but because the designs often featured links-with-icons they decided to build an <code><IconLink /></code> component too.</p>
<p>This new component introduced new, repetitious but slightly divergent prop/attribute names.</p>
<p>Robin’s point is that the new component essentially:</p>
<ul>
<li>just duplicated what the existing components did, and thus</li>
<li>created margin for divergence and error, and</li>
<li>added additional maintenance overhead.</li>
</ul>
<p>So Gousto eventually realised that an additional coded component didn’t make sense. Instead, just combine the existing components by nesting an <code><Icon /></code> inside a <code><Link /></code>, e.g.:</p>
<pre><code><Link>
<Icon />
<Link>
</code></pre>
<p>I like his thinking!</p>
<p>Basically there doesn’t need to be (and shouldn’t be, to avoid coding error and UX inconsistency) a 1:1 relationship between design patterns and coded components, so long as the pattern can be created by composition using existing components.</p>
<p>Note that I think it’s still key to document how to recreate the design pattern in code – for example we could have a section at the bottom of the component docs for the <code>Icon</code> component detailing how to create a link-with-icon by combining it with a <code>Link</code> component.</p>
<p>Basically I like the idea of reducing the amount of</p>
<ol>
<li>“which component do I use?” head-scratching; and</li>
<li>margin for divergence/inconsistency</li>
</ol>
<p>…by having less components.</p>
A Modern Typographic Scale (on 24 ways)2020-01-02T14:39:08Zhttps://fuzzylogic.me/posts/2020-01-02-a-modern-typographic-scale-on-24-ways/<p>Here’s <a href="https://robweychert.com/">Rob Weychert</a> advocating a combination of CSS custom properties, <code>calc()</code> and Sass to automate the construction of a flexible typographic scale in CSS.</p>
Awesome Stock Resources2020-01-02T14:09:08Zhttps://fuzzylogic.me/posts/2020-01-02-awesome-stock-resources/<blockquote>
<p>A collection of links for free stock photography, video and illustration websites</p>
</blockquote>
<p>In case I need more stock photography than I currently get from <a href="https://source.unsplash.com/">Unsplash</a>, this Github-hosted list could be useful.</p>
<p>Aside from photography it also lists resources for free illustrations, video, CSS background tiles and more.</p>
Responsive Type and Zoom (by Adrian Roselli)2019-12-26T17:30:24Zhttps://fuzzylogic.me/posts/2019-12-26-responsive-type-and-zoom-by-adrian-roselli/<blockquote>
<p>When people zoom a page, it is typically because they want the text to be bigger. When we anchor the text to the viewport size, even with a (fractional) multiplier, we can take away their ability to do that. It can be as much a barrier as disabling zoom. If a user cannot get the text to 200% of the original size, you may also be looking at a WCAG 1.4.4 Resize text (AA) problem.</p>
</blockquote>
<p>I already tend to avoid dynamic, viewport-width-based <a href="https://css-tricks.com/snippets/css/fluid-typography/">fluid typography</a> techniques in favour of making just one font-size adjustment – at a <em>desktop</em> breakpoint – based on the typographic theory that suggests we adjust type size according to <em>reading distance</em>. I learned this in Richard Rutter’s excellent book <a href="http://book.webtypography.net/">Web Typography</a>.</p>
<p>While the ideas and code behind the <em>fluid typography</em> approach are nice, Adrian’s discovery that it can hinder users who need to zoom text only strengthens my feeling that it’s not the best way to handle responsive type.</p>
The Man in the High Castle by Philip K. Dick2019-12-24T00:00:00Zhttps://fuzzylogic.me/posts/the-man-in-the-high-castle-by-philip-k-dick/<p>The second Phillp K Dick I’ve read this year is his alternative-history sci-fi classic.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1577820630/100188E6-836F-47C4-9A52-0C7DCEE33B08_pojazf.jpg" width="320" height="240" alt="A photo of the book “The Man in the High Castle” by Philip K. Dick" loading="lazy" decoding="async" />
<figcaption>The Man in the High Castle by Philip K. Dick</figcaption>
</figure>
<p>In this book, Dick protrays an alternate reality where the Axis powers have won the second world war and America is under the rule of Imperial Japan and Nazi Germany.</p>
<p>Interestingly, many of the characters use the ancient Chinese text the <em>I Ching</em> for guidance, and there’s also a clever “book within a book” subplot in which the novel <em>The Grasshopper Lies Heavy</em> depicts an alternate history in which the Allied forces prevailed.</p>
<p>Having now read a couple of Philip K. Dick books this year, I’m arriving at the conclusion that while I don’t love his writing style, this is counterbalanced by his creativity and the interesting ideas which stay with you long afterwards.</p>
Design Better Forms (UX Collective)2019-12-23T23:04:13Zhttps://fuzzylogic.me/posts/2019-12-23-design-better-forms-ux-collective/<p>As Andrew Coyle says, “Life is short. No one wants to fill out a form.”. Here, he presents a number of form design tips to make the user experience more bearable and increase completion rates.</p>
Layered, Smooth box-shadow generator (on brumm.af)2019-12-22T01:15:55Zhttps://fuzzylogic.me/posts/2019-12-22-layered-smooth-boxshadow-generator-on-brummaf/<blockquote>
<p>Inspired by Tobias Bjerrome’s blog post <a href="https://tobiasahlin.com/blog/layered-smooth-box-shadows">Smoother & sharper shadows with layered box-shadows</a></p>
</blockquote>
Making a Better Custom Select Element (24 ways)2019-12-21T16:59:57Zhttps://fuzzylogic.me/posts/2019-12-21-making-a-better-custom-select-element-24-ways/<blockquote>
<p>We want a way for someone to choose an item from a list of options, but it’s more complicated than just that. We want autocomplete options. We want to put images in there, not just text. The <code>optgroup</code> element is ugly, hard to style, and not announced by screen readers. I had high hopes for the <code>datalist</code> element, but it’s no good for people with low vision who zoom or use high contrast themes. <code>select</code> inputs are limited in a lot of ways. Let’s work out how to make our own while keeping all the accessibility features of the original.</p>
</blockquote>
<p>Julie Grundy argues here that despite us having <a href="https://fuzzylogic.me/posts/2019-12-21-styling-a-select-like-its-2019-or-filament-group-inc/">greater ability to style the standard <code>select</code></a> in 2019 there are times when that element doesn’t quite meet modern expectations.</p>
<p>This is a lovely, full-featured and fully accessible component. It could perhaps be improved by not showing the down-arrow icon until JavaScript is loaded, but otherwise it’s great.</p>
<p>Julie’s code currently exists solely as a Github repo, but for ease I’ve created <a href="https://codepen.io/fuzzylogicx/pen/rNamaYJ">this editable version on Codepen</a>.</p>
<p>Will I use this in place of the <code>select</code> element? Not if I can help it, because after years of experience working with form elements I still trust native elements to work better cross-platform than custom alternatives. However if a design requires dropdown options to employ custom patterns such as media objects, then I’ll definitely reach for this component.</p>
When should you add the defer attribute to the script element? (on Go Make Things)2019-12-21T13:37:50Zhttps://fuzzylogic.me/posts/2019-12-21-when-should-you-add-the-defer-attribute-to-the-script-element-on-go-make-things/<p>For many years I’ve placed script elements just before the closing <code>body</code> tag rather than in the <code><head></code>. Since a standard <code><script></code> element is render-blocking, the theory is that by putting it at the end of the document – after the main content of the page has loaded – it’s no longer blocking anything, and there’s no need to wrap it in a <code>DOMContentLoaded</code> event listener.</p>
<p>It turns out that my time-honoured default is OK, but there is a better approach.</p>
<p><a href="https://gomakethings.com/">Chris</a> has done the research for us and ascertained that placing the <code><script></code> in the <code><head></code> and adding the <code>defer</code> attribute has the same effect as putting that <code><script></code> just before the closing body tag but offers improved performance.</p>
<p>This treads fairly complex territory but my general understanding is this:</p>
<p>Using <code>defer</code> on a <code><script></code> in the <code><head></code> allows the browser to download the script <em>earlier</em>, in parallel, so that it is ready to be used as soon as the DOM is ready rather than having to be downloaded and parsed at that point.</p>
<p>Some additional points worth noting:</p>
<ul>
<li>Only use the <code>defer</code> attribute when the <code>src</code> attribute is present. Don’t use it on inline scripts because it will have no effect.</li>
<li>The <code>defer</code> attribute has no effect on module scripts (<code>script type="module"</code>). They defer by default.</li>
</ul>
Carbon2019-12-20T13:51:02Zhttps://fuzzylogic.me/posts/2019-12-21-carbon/<blockquote>
<p>Create and share beautiful images of your source code. Start typing or drop a file into the text area to get started.</p>
</blockquote>
<p>I’ve noticed <a href="https://hankchizljaw.com/">Andy Bell</a> using a really lovely format when sharing code snippets on Twitter. Turns out that it was using this great tool.</p>
<p>(via <a href="https://twitter.com/hankchizljaw">@hankchizljaw</a>)</p>
Async and Await2019-12-14T23:49:56Zhttps://fuzzylogic.me/posts/async-await/<p>My notes and reminders for handling promises with <code>async</code> and <code>await</code> In Real Life.</p>
<p>As I see it, the idea is to switch to using <code>await</code> when working with promise-returning, asynchronous operations (such as <code>fetch</code>) because it lends itself to more flexible and readable code.</p>
<h2 id="async-functions" tabindex="-1"><code>async</code> functions <a class="direct-link" href="https://fuzzylogic.me/posts/async-await/#async-functions" aria-hidden="true">#</a></h2>
<p>The <code>async</code> keyword, when used before a function declaration like so <code>async function f()</code>):</p>
<ul>
<li>defines an <em>asynchronous function</em> i.e. a function whose processes run after the main call stack and doesn’t block the main thread.</li>
<li>always returns a promise. (Its return value is implicitly wrapped in a resolved promise.)</li>
<li>allows us to use <code>await</code>.</li>
</ul>
<h2 id="the-await-operator" tabindex="-1">The <code>await</code> operator <a class="direct-link" href="https://fuzzylogic.me/posts/async-await/#the-await-operator" aria-hidden="true">#</a></h2>
<ul>
<li>use the <code>await</code> keyword within <code>async</code> functions to wait for a <a href="https://fuzzylogic.me/posts/javascript-promises-explained/">Promise</a>.</li>
<li>Example usage: <code>const users = await fetch('/users')</code>).</li>
<li>It makes the <code>async</code> function pause until that promise settles and returns its result.</li>
<li>It makes sense that it may only be used inside <code>async</code> functions so as to scope the “waiting” behaviour to that dedicated context.</li>
<li>It’s a more elegant syntax for getting a promise‘s result than <code>promise.then</code>.</li>
<li>If the promise resolves successfully, <code>await</code> returns the result.</li>
<li>If the promise rejects, <code>await</code> throws the error, just as if there were a <code>throw</code> statement at that line.</li>
<li>That <code>throw</code> causes execution of the current function to stop (so the next statements won't be executed), with control passed to the first <code>catch</code> block in the call stack. If no <code>catch</code> block exists among caller functions, the program will terminate.</li>
<li>Given this “continue or throw” behaviour, wrapping an <code>await</code> in a <code>try...catch</code> is a really nice and well-suited pattern for including error handling, providing flexibility and aiding readability.</li>
</ul>
<p>Here’s a <code>try...catch</code> -based example. (NB let’s assume that we have a list of blog articles and a “Load more articles” button which triggers the <code>loadMore()</code> function):</p>
<figure>
<pre class="language-js"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">class</span> <span class="token class-name">ArticleLoader</span> <span class="token punctuation">{</span><br /><br /> <span class="token keyword">async</span> <span class="token function">loadMore</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> fetchURL <span class="token operator">=</span> <span class="token string">"https://mysite.com/blog/"</span><span class="token punctuation">;</span><br /> <span class="token keyword">try</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> newItems <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">fetchItems</span><span class="token punctuation">(</span>fetchURL<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// If we’re here, we know our promise fulfilled.</span><br /> <span class="token comment">// We might add some additional `await`, or just…</span><br /> <span class="token comment">// Render our new HTML items into the DOM.</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">renderItems</span><span class="token punctuation">(</span>newItems<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">displayError</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <br /> <span class="token keyword">async</span> <span class="token function">fetchArticles</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">"GET"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>response<span class="token punctuation">.</span>ok<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">"Sorry, there was a problem fetching additional articles."</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><br /> <span class="token function">displayError</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> errorMsgContainer <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">"[data-target='error-msg']"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> errorMsgContainer<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><span class="error"></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>err<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"></span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Here’s another example. Let’s say that we needed to wait for multiple promises to resolve:</p>
<figure>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">allUsers</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">try</span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> results <span class="token operator">=</span> <span class="token keyword">await</span> Promise<span class="token punctuation">.</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token punctuation">[</span><br /> <span class="token function">fetch</span><span class="token punctuation">(</span>userUrl1<span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token function">fetch</span><span class="token punctuation">(</span>userUrl2<span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token function">fetch</span><span class="token punctuation">(</span>userUrl3<span class="token punctuation">)</span><br /> <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// we’ll get here if the promise returned by await</span><br /> <span class="token comment">// resolved successfully.</span><br /> <span class="token comment">// We can output a success message.</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">displayError</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Using <code>await</code> within a <code>try...catch</code> is my favourite approach but sometimes it’s not an option because we’re at the topmost level of the code therefore not in an <code>async</code> function. In these cases it’s good to remember that we can call an <code>async</code> function and work with its returned value like any promise, i.e. using <code>then</code> and <code>catch</code>.</p>
<p>For example:</p>
<figure>
<pre class="language-js"><code class="language-js"><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">loadUser</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>response<span class="token punctuation">.</span>status <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> json <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> json<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>status<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token function">loadUser</span><span class="token punctuation">(</span><span class="token string">'no-user-here.json'</span><span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">json</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// resolved promise, so do something with the json</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// then() returns a promise, so is chainable.</span><br /> <span class="token comment">// rejected promise, so do something with the json</span><br /> document<span class="token punctuation">.</span>body<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">"foo"</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</figure>
<p>References:</p>
<ul>
<li><a href="https://javascript.info/async-await">Explanation and patterns on javascript.info</a></li>
<li><a href="https://developers.google.com/web/fundamentals/primers/async-functions">Async functions – making promises friendly</a> by Jake Archibald</li>
</ul>
Modest JS Works2019-12-14T23:49:56Zhttps://fuzzylogic.me/posts/2019-12-14-modest-js-works/<p>Pascal Laliberté has written a short, free, web-based book which advocates a modest and layered approach to using JavaScript.</p>
<blockquote>
<p>I make the case for The JS Gradient, a principle whereby your app can have multiple coexisting modern JS approaches, starting from the global sprinkles to spot view-models to, yes, an SPA if that’s really necessary. At each point in the gradient, you’ll see when it’s a good idea to go a step further toward heavier JavaScript, or not.</p>
</blockquote>
<p>Pascal’s philosophy starts with the following ideals:</p>
<ul>
<li><strong>prefer server-generated HTML over JavaScript-generated HTML</strong>. If we need to add more complex JavaScript layers we may deviate from that ideal, but this should be the starting point;</li>
<li><strong>we should be able to swap and replace the HTML on a page on a whim</strong>. We can then support techniques like <em>pjax</em> (replacing the <em>whole body</em> of a page with new HTML such as with <a href="https://github.com/turbolinks/turbolinks">Turbolinks</a>) and <em>ahah</em> (asynchronous HTML over HTTP: replacing <em>parts</em> of a page with new HTML, so as to make our app feel really fast while still favouring server-generated HTML;</li>
<li><strong>favour native Browser APIs over proprietary libraries</strong>. Use the tools the browser gives us (History API, Custom Event handlers, native form elements, CSS and the cascade) and polyfill older browsers.</li>
</ul>
<p>He argues that a single application can <em>combine</em> the options along the JS Gradient, but also that we need only move to a new level if and when we reach the current level’s threshold.</p>
<p>He defines the levels as follows:</p>
<ul>
<li><strong>Global Sprinkles</strong>: general app-level enhancements that occur on most pages, achieved by adding event listeners at <code>document</code> level to catch user interactions and respond with small updates. Such updates might include dropdowns, fetching and inserting HTML fragments, and Ajax form submission. This might be achieved via a single, DIY script (or something like <a href="https://postlight.github.io/trimmings/">Trimmings</a>) that is available globally and provides reusable utilities via <code>data-</code> attributes;</li>
<li><strong>Component Sprinkles</strong>: specific page component behaviour defined in individual <code>.js</code> files, where event listeners are still ideally set on the <code>document</code>;</li>
<li><strong><a href="https://fuzzylogic.me/posts/2019-12-14-modest-js-works/%5BStimulus%5D(https://stimulusjs.org/)">Stimulus</a> components</strong>: where each component’s HTML holds its state and defines its behaviour, with a companion <em>controller</em> <code>.js</code> file which wires up event handlers to elements;</li>
<li><strong>Spot View-Models</strong>: using a framework such as Vue or React <em>only in specific spots</em>, for situations where our needs are more complex and generating the HTML on the server would be impractical. Rather than taking over the whole page, this just augments a specific page section with a data-reactive view-model.</li>
<li><strong>A single-page application (SPA)</strong>: typically an all-JavaScript affair, where whole pages are handled by Reactive View-Models like Vue and React and the browser’s handling of clicks and the back button are overriden to serve different JavaScript-generated views to the user. This is the least <em>modest</em> approach but there are times when it is necessary.</li>
</ul>
<p>One point to which Pascal regularly returns is that it’s better to add event listeners to the <code>document</code> (with a check to ensure the event occurred on the relevant element) rather than to the element itself. I already knew that <a href="https://gomakethings.com/event-delegation-and-multiple-selectors-with-vanilla-js/">Event Delegation is better for browser performance</a> however Pascal’s point is that in the context of wanting to support swapping and replacing HTML on a whim, if event listeners are directly on the <em>element</em> but that element is replaced (or a duplicate added) then we would need to keep adding more event listeners. By contrast, this is not necessary when the event listener is added to the <code>document</code>.</p>
<p>Note: Stimulus applies event handlers to elements rather than the <code>document</code>, however one of its USPs is that it’s set up so that as elements appear or disappear from the DOM, event handlers are automatically added and removed. This lets you swap and replace HTML as you need without having to manually define and redefine event handlers. He calls this <em>Automated Behaviour Orchestration</em> and notes that while adding event listeners to the <code>document</code> is the ideal approach, the Stimulus approach is the next best thing.</p>
<p>Also of particular interest to me was his Stimulus-based <a href="https://cart-stimulus.modestjs.works/">Shopping Cart page demo</a> where he employs some nice techniques including:</p>
<ul>
<li>multiple controllers within the same block of HTML;</li>
<li>multiple Stimulus actions on a single element;</li>
<li>controller action methods which use <code>document.dispatchEvent</code> to dispatch Custom Events as a means of communicating changes up to other components;</li>
<li>an element with an action which listens for the above custom event occurring on the <code>document</code> (as opposed to an event on the element itself).</li>
</ul>
<p>I’ve <a href="https://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/">written about Stimulus before</a> and noted a few potential cons when considering complex interfaces, however Pascal’s demo has opened my eyes to additional possibilities.</p>
Note 2019-12-13T16:00:58: Christmas Jumper Day2019-12-13T16:00:58Zhttps://fuzzylogic.me/posts/1531418045-christmas-jumper-day-at-work/<p>My first Christmas working at FreeAgent. Strong Christmas Jumper game!</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1577268847/FA_Xmas_mtddat.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1577268847/FA_Xmas_mtddat.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1577268847/FA_Xmas_mtddat.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1577268847/FA_Xmas_mtddat.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1577268847/FA_Xmas_mtddat.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1577268847/FA_Xmas_mtddat.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1577268847/FA_Xmas_mtddat.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1577268847/FA_Xmas_mtddat.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1577268847/FA_Xmas_mtddat.jpg" width="320" height="240" alt="Christmas Jumper Day 2019 at FreeAgent" loading="lazy" decoding="async" />
<figcaption>Christmas Jumper Day 2019 at FreeAgent</figcaption>
</figure>
My Ruby and Rails Cheatsheet2019-12-13T15:07:34Zhttps://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/<p>I’m no Ruby engineer however even as a front-end developer I’m sometimes called upon to work on <a href="https://rubyonrails.org/">Rails</a> applications that require me to know my way around. Here are my notes and reminders.</p>
<p>This is not intended to be an authoritative guide but merely my notes from various lessons. It’s also a work-in-progress and a living, changing document.</p>
<h2 id="table-of-contents" tabindex="-1">Table of contents <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#table-of-contents" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#the-rails-console">The Rails Console</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#rspec">Rspec</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#debugging">Debugging</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#helpers">Helpers</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#blank%3F-versus-empty%3F">blank? vs empty?</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#frozen_string_literal%3A-true">frozen_string_literal</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#class-level-methods">Class-level methods</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#constants">Constants</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#symbols">Symbols</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#viewcomponents">ViewComponent</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#instance-variables">Instance Variables</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#methods">Methods</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#check-if-thing-is-an-array-and-is-non-empty">Empty-checking arrays</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#the-shovel-operator">The Shovel Operator</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#require">Require</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#blocks">Blocks</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#rendering-html">Rendering HTML</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#random-ids-or-strings">Generating random IDs or strings</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#views">Views</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#policies">Policies</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#start-(local)-rails-server">Start local Rails server</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#miscellaneous">Miscellaneous</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#web-fonts%3A-where-to-put-them-in-the-rails-file-structure">Web fonts location</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#the-database">Working with the Database</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#routing">Routing</a></li>
<li><a href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#references">References</a></li>
</ul>
<h2 id="the-rails-console" tabindex="-1">The Rails Console <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#the-rails-console" aria-hidden="true">#</a></h2>
<p>The <code>console</code> command lets you interact with your Rails application from the command line.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># launch a console (short version)</span><br />rails c<br /><br /><span class="token comment"># long version</span><br />bundle <span class="token builtin class-name">exec</span> rails console</code></pre>
</figure>
<p>Quickly find where a method is located:</p>
<figure>
<pre class="language-bash"><code class="language-bash">Myobj.method<span class="token punctuation">(</span>:methodname<span class="token punctuation">)</span>.source_location<br /><br /><span class="token comment"># Returns a file and line which you can command-click</span><br /><span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token string">"/local/path/to/mymodelname/model.rb"</span>, <span class="token number">99</span><span class="token punctuation">]</span></code></pre>
</figure>
<p>See an object’s methods:</p>
<figure>
<pre class="language-bash"><code class="language-bash">Myobj.methods<br /><br /><span class="token comment"># Search for a method using a search string</span><br /><span class="token comment"># this returns all of the object methods containing string “/pay/“</span><br />Myobj.methods.grep<span class="token punctuation">(</span>/pay/<span class="token punctuation">)</span></code></pre>
</figure>
<h2 id="rspec" tabindex="-1">Rspec <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#rspec" aria-hidden="true">#</a></h2>
<p>Run it like so:</p>
<figure>
<pre class="language-bash"><code class="language-bash">bin/rspec spec/path/to/foo_spec.rb<br /><br /><span class="token comment"># Run a particular line/method</span><br />bin/rspec spec/path/to/foo_spec.rb:195</code></pre>
</figure>
<p>If adding data variables to use in tests, declare them in a let block so as to keep them isolated and avoid them leaking elsewhere.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby">let<span class="token punctuation">(</span><span class="token symbol">:example_data_obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token punctuation">{</span><br /> <span class="token symbol">foo</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"bar"</span></span><span class="token punctuation">,</span><br /> <span class="token symbol">baz</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"bat"</span></span><span class="token punctuation">,</span><br /> …<br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Note: if you need multiple data variables so as to handle different scenarios, it’s generally more readable to define the data being tested right next to the test.</p>
<h2 id="debugging" tabindex="-1">Debugging <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#debugging" aria-hidden="true">#</a></h2>
<p>I’ll cover debugging related to more specific file types later but here’s a simple tip. You can check the value of a variable or expression at a given line in a method by:</p>
<ol>
<li>add <code>byebug</code> on a line of its own at the relevant place in your file, then save file</li>
<li>switch to the browser and reload your page</li>
<li>in the terminal tab that’s running the Rails server (which should now be stopped at the debugging breakpoint), at the bottom type the variable name of interest. You won’t see any text but just trust that your typing is taking effect. Press <kbd>return</kbd></li>
<li>you’ll now see the value of that variable as it is at the debugging breakpoint</li>
<li>When you’re done, remove your <code>byebug</code>. You may need to type continue (or <code>c</code> for short) followed by <kbd>return</kbd> at the command prompt to get the server back on track.</li>
</ol>
<h2 id="helpers" tabindex="-1">Helpers <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#helpers" aria-hidden="true">#</a></h2>
<p>Helper methods are to there to support your views. They’re for extracting into methods little code routines or logic that don’t belong in a controller and are too complex or reusable to be coded literally into your view. They’re reusable across views because they become available to all your views automatically.</p>
<p>Don’t copy and reuse method names from other helpers. You’ll get conflicts because Helpers are leaky. Instead, start your helper methods with an appropriate namespace.</p>
<p>Unlike object methods (e.g. <code>myobj.do_something</code>) helper methods (e.g. <code>render_something</code>) are not available for us to use in the Rails console.</p>
<h2 id="helper-specs" tabindex="-1">Helper specs <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#helper-specs" aria-hidden="true">#</a></h2>
<p>Basic format:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token comment"># frozen_string_literal: true</span><br /><span class="token keyword">require</span> <span class="token string-literal"><span class="token string">"rails_helper"</span></span><br /><br />RSpec<span class="token punctuation">.</span>describe Foos<span class="token double-colon punctuation">::</span>BarHelper <span class="token keyword">do</span><br /> let<span class="token punctuation">(</span><span class="token symbol">:foo</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> FactoryBot<span class="token punctuation">.</span>create<span class="token punctuation">(</span><span class="token symbol">:foo</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><br /><br /> describe <span class="token string-literal"><span class="token string">"#foo_bars_sortable_link"</span></span> <span class="token keyword">do</span><br /><br /> context <span class="token string-literal"><span class="token string">"when bat is not true"</span></span> <span class="token keyword">do</span><br /> it <span class="token string-literal"><span class="token string">"does a particular thing"</span></span> <span class="token keyword">do</span><br /> expect<span class="token punctuation">(</span>helper<span class="token punctuation">.</span>foo_bars_sortable_link<span class="token punctuation">(</span>foo<span class="token punctuation">,</span> <span class="token symbol">bat</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"false"</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>to have_link<span class="token punctuation">(</span><br /> <span class="token comment"># …</span><br /> <span class="token punctuation">)</span><br /> <span class="token keyword">end</span><br /> <span class="token keyword">end</span><br /><br /> context <span class="token string-literal"><span class="token string">"when bat is true"</span></span> <span class="token keyword">do</span><br /> it <span class="token string-literal"><span class="token string">"does something else"</span></span> <span class="token keyword">do</span><br /> expect<span class="token punctuation">(</span>helper<span class="token punctuation">.</span>foo_bars_sortable_link<span class="token punctuation">(</span>foo<span class="token punctuation">,</span> <span class="token symbol">bat</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"true"</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>to have_link<span class="token punctuation">(</span><br /> <span class="token comment"># …a different link from previous test</span><br /> <span class="token punctuation">)</span><br /> <span class="token keyword">end</span><br /> <span class="token keyword">end</span><br /> <span class="token keyword">end</span><br /><span class="token keyword">end</span></code></pre>
</figure>
<p>Notes:</p>
<ul>
<li>start with <code>describe</code>: it’s a good top-level.</li>
<li>describe a helper method using hash (<code>describe "#project_link" do</code>)</li>
<li>Helper methods should not directly access controller instance variables because it makes them brittle, less reusable and less maintainable. If you find you’re doing that you might see it as an opportunity to refactor your helper method.</li>
</ul>
<h3 id="debugging-helper-methods" tabindex="-1">Debugging Helper methods <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#debugging-helper-methods" aria-hidden="true">#</a></h3>
<p>If you want to debug a helper method by running it and stepping through it at the command line you should lean on a test to get into the method’s context.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># in foo_helper.rb, insert above line of interest</span><br />binding.pry <span class="token comment"># or byebug</span><br /><br /><span class="token comment"># at command line, run helper’s spec (at relevant line/assertion)</span><br />bin/rspec spec/path/to/foo_helper_spec.rb:195<br /><br /><span class="token comment"># the “debugger” drops you in at the line where you added your breakpoint</span><br /><span class="token comment"># and shows the body of the function being run by the line of the spec we requested.</span><br />From: /path/to/app/helpers/foo_helper.rb:26 FooHelper<span class="token comment">#render_foo:</span><br /><br /><span class="token comment"># you’re now debugging in the context of the running helper method…</span><br /><span class="token comment"># with the arguments passed in by the test available to manipulate.</span><br /><span class="token comment"># this means you can run constituent parts of the method at the debugger prompt…</span><br /><span class="token comment"># for example…</span><br /><span class="token comment"># run this to get back the HTML being rendered.</span><br />render_user_profile<span class="token punctuation">(</span>user<span class="token punctuation">)</span></code></pre>
</figure>
<h2 id="blank%3F-versus-empty%3F" tabindex="-1">blank? versus empty? <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#blank%3F-versus-empty%3F" aria-hidden="true">#</a></h2>
<p>If you want to test whether something is “empty” you might use <code>empty?</code> if you’re testing a string, however it’s not appropriate for testing object properties (such as <code>person.nickname</code>) because objects can be <code>nil</code> and the <code>nil</code> object has no <code>empty?</code> method. (Run <code>nil.empty?</code> at the console for proof.) Instead use <code>blank?</code> e.g. <code>person.nickname.blank?</code>.</p>
<h2 id="frozen_string_literal%3A-true" tabindex="-1">frozen_string_literal: true <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#frozen_string_literal%3A-true" aria-hidden="true">#</a></h2>
<p>I’ll often see this at the top of files, for example Ruby classes. This is just a good practice. It makes things more efficient and thereby improves performance.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby">frozen_string_literal<span class="token operator">:</span> <span class="token boolean">true</span></code></pre>
</figure>
<h2 id="class-level-methods" tabindex="-1">Class-level methods <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#class-level-methods" aria-hidden="true">#</a></h2>
<p>They’re called class-level methods because they are methods which are never called by the instance, i.e. never called outside of the class. They are also known as <em>macros</em>.</p>
<p>Examples include <code>attr_reader</code> and ViewComponent’s <code>renders_one</code>.</p>
<h2 id="constants" tabindex="-1">Constants <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#constants" aria-hidden="true">#</a></h2>
<p>Here’s an example where we define a new constant and assign an array to it.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token constant">ALLOWED_SIZES</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token keyword">nil</span><span class="token punctuation">,</span> <span class="token symbol">:medium</span><span class="token punctuation">,</span> <span class="token symbol">:large</span><span class="token punctuation">]</span></code></pre>
</figure>
<p>Interestingly while the constant cannot be redefined later—i.e. it could not later be set to something other than an array—elements can still be added or removed. We don’t want that here. The following would be better because it locks things down which is likely what we want.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token constant">ALLOWED_SIZES</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token keyword">nil</span><span class="token punctuation">,</span> <span class="token symbol">:medium</span><span class="token punctuation">,</span> <span class="token symbol">:large</span><span class="token punctuation">]</span><span class="token punctuation">.</span>freeze</code></pre>
</figure>
<h2 id="symbols" tabindex="-1">Symbols <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#symbols" aria-hidden="true">#</a></h2>
<p>They’re not variables. They’re more like strings than variables however Strings are used to work with data whereas Symbols are identifiers.</p>
<p>You should use symbols as names or labels for things (for example methods). They are often used to represent method & instance variable names:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token comment"># here, :title is a symbol representing the @title instance variable</span><br />attr_reader <span class="token symbol">:title</span><br /><br /><span class="token comment"># refer to the render_foo method using a symbol</span><br />Myobj<span class="token punctuation">.</span>method<span class="token punctuation">(</span><span class="token symbol">:render_foo</span><span class="token punctuation">)</span><span class="token punctuation">.</span>source_location<br /><br /><span class="token comment"># you can also use symbols as hash keys</span><br />hash <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token symbol">a</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token symbol">b</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token symbol">c</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">}</span></code></pre>
</figure>
<p>From what I can gather, colons identify something as a Symbol and the colon is at the beginning when its a method name or instance variable but at the end when its a hash key.</p>
<h2 id="viewcomponents" tabindex="-1">ViewComponents <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#viewcomponents" aria-hidden="true">#</a></h2>
<p><a href="https://viewcomponent.org/">ViewComponents</a> (specifically the <code>my_component.rb</code> file) are just controllers which do not access the database.</p>
<p>They use <em>constructors</em> like the following:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">initialize</span></span><span class="token punctuation">(</span><span class="token symbol">size</span><span class="token operator">:</span> <span class="token keyword">nil</span><span class="token punctuation">,</span> <span class="token symbol">full_height</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token symbol">data</span><span class="token operator">:</span> <span class="token keyword">nil</span><span class="token punctuation">)</span><br /> <span class="token keyword">super</span><br /> <span class="token variable">@size</span> <span class="token operator">=</span> allowed_value<span class="token operator">?</span><span class="token punctuation">(</span><span class="token constant">ALLOWED_CARD_SIZES</span><span class="token punctuation">,</span> size<span class="token punctuation">)</span><br /> <span class="token variable">@full_height</span> <span class="token operator">=</span> full_height<br /> <span class="token variable">@data</span> <span class="token operator">=</span> data<br /><span class="token keyword">end</span></code></pre>
</figure>
<p>(Note that you would never include a constructor in a <em>Rails</em> controller or model.)</p>
<h3 id="viewcomponents-in-the-rails-console" tabindex="-1">ViewComponents in the Rails console <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#viewcomponents-in-the-rails-console" aria-hidden="true">#</a></h3>
<figure>
<pre class="language-bash"><code class="language-bash">view <span class="token operator">=</span> ActionView::Base.new<br />view.render<span class="token punctuation">(</span>CardComponent.new<span class="token punctuation">)</span></code></pre>
</figure>
<h2 id="instance-variables" tabindex="-1">Instance variables <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#instance-variables" aria-hidden="true">#</a></h2>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">initialize</span></span><span class="token punctuation">(</span><span class="token symbol">foo</span><span class="token operator">:</span> <span class="token keyword">nil</span><span class="token punctuation">)</span><br /> <span class="token keyword">super</span><br /> <span class="token variable">@foo</span> <span class="token operator">=</span> foo<br /><span class="token keyword">end</span></code></pre>
<p>In the above example <code>@foo</code> is an <code>instance variable</code>. These are available to an instance of the controller and private to the component. (This includes ViewComponents, which are also controllers.)</p>
<p>In a view, you can refer to it using <code>@foo</code>.</p>
<p>In a subsequent method within the controller, refer to it simply as <code>foo</code>. There’s no preceding colon (it’s not a symbol; in a conditional a symbol would always evaluate to <code>true</code>) and no preceding <code>@</code>.</p>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">classes</span></span><br /> classes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string-literal"><span class="token string">"myThing"</span></span><span class="token punctuation">]</span><br /> classes <span class="token operator"><<</span> <span class="token string-literal"><span class="token string">"myThing-foo"</span></span> <span class="token keyword">if</span> foo<br /> classes<br /><span class="token keyword">end</span></code></pre>
<h3 id="making-instance-variables-publicly-available" tabindex="-1">Making instance variables publicly available <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#making-instance-variables-publicly-available" aria-hidden="true">#</a></h3>
<p>The following code makes some instance variables of a ViewComponent publicly available.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby">attr_reader <span class="token symbol">:size</span><span class="token punctuation">,</span> <span class="token symbol">:full_height</span><span class="token punctuation">,</span> <span class="token symbol">:data</span></code></pre>
</figure>
<p>However although that’s the pattern employed by the <a href="https://viewcomponent.org/">ViewComponent website</a> you could argue it’d be better not to do this because it makes more stuff public than needs to be. Instead you could simply access the instance variables directly (including in the view). I’d like to dig into this one a bit more and just check I’m clear on the syntax (perhaps <code>card.size</code>).</p>
<h2 id="methods" tabindex="-1">Methods <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#methods" aria-hidden="true">#</a></h2>
<p>Every method returns a value. You don’t need to explicitly use <code>return</code>, because without it it will be assumed that you’re returning the last thing in the method.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">hello</span></span><br /> "hello world”<br /><span class="token keyword">end</span></code></pre>
</figure>
<h3 id="define-private-methods" tabindex="-1">Define private methods <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#define-private-methods" aria-hidden="true">#</a></h3>
<p>Add <code>private</code> above the instance methods which are only called from within the class in which they are defined and not from outside. This makes it clear for other developers that they are internal and don’t affect the external interface. This lets them know, for example, that these method names could be changed without breaking things elsewhere.</p>
<p>Also: keep your public interface small.</p>
<h3 id="naming-conventions" tabindex="-1">Naming conventions <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#naming-conventions" aria-hidden="true">#</a></h3>
<p>The convention I have worked with is that any method that returns a <code>boolean</code> should end with a question mark. This saves having to add prefixes like “is-” to method names. If a method does not return a boolean, its name should not end with a question mark.</p>
<h3 id="parameters" tabindex="-1">Parameters <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#parameters" aria-hidden="true">#</a></h3>
<p>The standard configuration of method parameters (no colon and no default value) sets them as required arguments that must be passed in order when you call the method. For example:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">write</span></span><span class="token punctuation">(</span>file<span class="token punctuation">,</span> data<span class="token punctuation">,</span> mode<span class="token punctuation">)</span><br /> …<br /><span class="token keyword">end</span><br /><br />write<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">"cats.txt"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"cats are cool!"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"w"</span></span><span class="token punctuation">)</span></code></pre>
</figure>
<p>By setting a parameter to have a default value, it becomes an optional argument when calling the method.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">write</span></span><span class="token punctuation">(</span>file<span class="token punctuation">,</span> data<span class="token punctuation">,</span> mode <span class="token operator">=</span> <span class="token string-literal"><span class="token string">"w"</span></span><span class="token punctuation">)</span><br /> …<br /><span class="token keyword">end</span><br /> <br />write<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">"shopping_list.txt"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"bacon"</span></span><span class="token punctuation">)</span></code></pre>
</figure>
<h4 id="named-parameters" tabindex="-1">Named Parameters <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#named-parameters" aria-hidden="true">#</a></h4>
<p>Configuring your method with named parameters makes the method call read a little more clearly (via the inclusion of the keywords in the call) and increases flexibility because the order of arguments is not important. After every parameter, add a colon. Parameters are mandatory unless configured with a default value.</p>
<p>Here’s an example.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">write</span></span><span class="token punctuation">(</span><span class="token symbol">file</span><span class="token operator">:</span><span class="token punctuation">,</span> <span class="token symbol">data</span><span class="token operator">:</span><span class="token punctuation">,</span> <span class="token symbol">mode</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"ascii"</span></span><span class="token punctuation">)</span><br /> …<br /><span class="token keyword">end</span><br /> <br />write<span class="token punctuation">(</span><span class="token symbol">data</span><span class="token operator">:</span> <span class="token number">123</span><span class="token punctuation">,</span> <span class="token symbol">file</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"test.txt"</span></span><span class="token punctuation">)</span></code></pre>
</figure>
<p>And here’s how you might do things for a <code>Card</code> ViewComponent.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">initialize</span></span><span class="token punctuation">(</span><span class="token symbol">size</span><span class="token operator">:</span> <span class="token keyword">nil</span><span class="token punctuation">,</span> <span class="token symbol">full_height</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token symbol">data</span><span class="token operator">:</span> <span class="token keyword">nil</span><span class="token punctuation">)</span><br /> …<br /><span class="token keyword">end</span><br /> <br /><span class="token operator"><</span><span class="token operator">%=</span> render<span class="token punctuation">(</span><span class="token class-name">CardComponent</span><span class="token punctuation">.</span><span class="token keyword">new</span><span class="token punctuation">(</span><span class="token symbol">size</span><span class="token operator">:</span> <span class="token symbol">:small</span><span class="token punctuation">,</span> <span class="token symbol">full_height</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">do</span> <span class="token operator">%</span><span class="token operator">></span></code></pre>
</figure>
<h2 id="check-if-thing-is-an-array-and-is-non-empty" tabindex="-1">Check if thing is an array and is non-empty <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#check-if-thing-is-an-array-and-is-non-empty" aria-hidden="true">#</a></h2>
<p>You can streamline this to:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby">thing<span class="token punctuation">.</span>is_a<span class="token operator">?</span><span class="token punctuation">(</span><span class="token builtin">Array</span><span class="token punctuation">)</span> <span class="token operator">&&</span> thing<span class="token punctuation">.</span>present<span class="token operator">?</span></code></pre>
</figure>
<h2 id="the-shovel-operator" tabindex="-1">The shovel operator <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#the-shovel-operator" aria-hidden="true">#</a></h2>
<p>The shovel operator (<code><<</code>) lets you add elements to an array. Here’s an example where we build up an HTML <code>class</code> attribute for a BEM-like structure:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">classes</span></span><br /> classes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><br /> classes <span class="token operator"><<</span> <span class="token string-literal"><span class="token string">"card--</span><span class="token interpolation"><span class="token delimiter punctuation">#{</span><span class="token content">size</span><span class="token delimiter punctuation">}</span></span><span class="token string">"</span></span> <span class="token keyword">if</span> size<br /> classes <span class="token operator"><<</span> <span class="token string-literal"><span class="token string">"card--tall"</span></span> <span class="token keyword">if</span> full_height<br /> classes<span class="token punctuation">.</span>join<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">" "</span></span><span class="token punctuation">)</span><br /><span class="token keyword">end</span></code></pre>
</figure>
<h2 id="double-splat-operator" tabindex="-1">Double splat operator <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#double-splat-operator" aria-hidden="true">#</a></h2>
<p>My understanding is that when you pass <code>**foo</code> as a parameter to a method call then it represents the hash that will be returned from a method <code>def foo</code> elsewhere. The contents of that hash might be different under different circumstances which is why you’d use the double-splat rather than just specifying literal attributes and values. If there are multiple items in the hash, it’ll spread them out as multiple key-value pairs (e.g. as multiple HTML attribute name and attribute value pairs). This is handy when you don’t know which attributes you need to include at the time of rendering a component and want the logic for determining that to reside in the component internals. Here’s an example, based on a ViewComponent for outputting accessible SVG icons:</p>
<p>In the <code>icon_component.html.erb</code> template:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token operator"><</span><span class="token operator">%=</span> tag<span class="token punctuation">.</span>svg<span class="token punctuation">(</span><br /> <span class="token symbol">class</span><span class="token operator">:</span> svg_class<span class="token punctuation">,</span> <br /> <span class="token symbol">fill</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"currentColor"</span></span><span class="token punctuation">,</span> <br /> <span class="token operator">**</span>aria_role<br /><span class="token punctuation">)</span> <span class="token keyword">do</span> <span class="token string-literal"><span class="token string">%><br /> …<br /><% end %></span></span></code></pre>
<p>In <code>IconComponent.rb</code>:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">aria_role</span></span><br /> title <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token symbol">role</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"img"</span></span> <span class="token punctuation">}</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token symbol">aria</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token symbol">hidden</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><br /><span class="token keyword">end</span></code></pre>
</figure>
</figure>
<p>The <code>**aria_role</code> argument resolves to the <code>hash</code> output by the <code>aria_role</code> method, resulting in valid arguments for calling Rails’s <code>tag.svg</code>.</p>
<h2 id="require" tabindex="-1">require <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#require" aria-hidden="true">#</a></h2>
<p><code>require</code> allows you to bring other resources into your current context.</p>
<h2 id="blocks" tabindex="-1">Blocks <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#blocks" aria-hidden="true">#</a></h2>
<p>The <code>do…end</code> structure in Ruby is called a “block”, and more specifically a multi-line block.</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"> <span class="token operator"><</span><span class="token operator">%=</span> render <span class="token class-name">CardComponent</span><span class="token punctuation">.</span><span class="token keyword">new</span> <span class="token keyword">do</span> <span class="token operator">|</span>c<span class="token operator">|</span> <span class="token string-literal"><span class="token string">%><br /> Card stuff in here.<br /> <% end %></span></span></code></pre>
</figure>
<p>Blocks are essentially methods (functions).</p>
<p>We can specify that a block must be present. For example:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">has_block</span></span><span class="token punctuation">(</span>param<span class="token punctuation">,</span> <span class="token operator">&</span>block<span class="token punctuation">)</span></code></pre>
</figure>
<p>Here, the ampersand (<code>&</code>) means that the block is required.</p>
<h3 id="single-line-block" tabindex="-1">Single-line block <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#single-line-block" aria-hidden="true">#</a></h3>
<p>Sometimes we don’t need to use a multiline block. We can instead employ a single-line block. This uses curly braces rather than <code>do…end</code>.</p>
<p>For example in a spec we might use:</p>
<figure>
<pre class="language-ruby"><code class="language-ruby">render_inline<span class="token punctuation">(</span><span class="token class-name">CardComponent</span><span class="token punctuation">.</span><span class="token keyword">new</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token string-literal"><span class="token string">"Content"</span></span> <span class="token punctuation">}</span><br />expect<span class="token punctuation">(</span>rendered_component<span class="token punctuation">)</span><span class="token punctuation">.</span>to have_css<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">".fe-CardV2"</span></span><span class="token punctuation">,</span> <span class="token symbol">text</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">"Content"</span></span><span class="token punctuation">)</span></code></pre>
</figure>
<p>The above two lines really just construct a “string” of the component and let you test for the presence of things in it.</p>
<h2 id="rendering-html" tabindex="-1">Rendering HTML <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#rendering-html" aria-hidden="true">#</a></h2>
<p>We have the <code>content_tag</code> helper method for rendering HTML elements. However you are arguably just as well coding the actual HTML rather than bothering with it, especially for the likes of <code>div</code> and <code>span</code> elements.</p>
<p><code>link_to</code> is a little more useful and makes more sense to use.</p>
<h3 id="multi-line-html-string" tabindex="-1">Multi-line HTML string <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#multi-line-html-string" aria-hidden="true">#</a></h3>
<p>Return a multi-line HTML string like so:</p>
<figure>
<pre><code>output = "<p>As discussed on the phone, the additional work would involve:</p>
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ol>
<p>This should get your historic accounts into a good shape.</p>".html_safe
output
</code></pre>
</figure>
<h3 id="interpolation" tabindex="-1">Interpolation <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#interpolation" aria-hidden="true">#</a></h3>
<p>Here’s an example where we use interpolation to return a string that has a text label alongside an inline SVG icon, both coming from variables.</p>
<figure>
<pre><code>"#{link[:text]} #{icon_svg}".html_safe
</code></pre>
</figure>
<h3 id="tag.send()" tabindex="-1">tag.send() <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#tag.send()" aria-hidden="true">#</a></h3>
<p><code>send()</code> is not just for use on <code>tag</code>. It’s a means of calling a method dynamically i.e. using a variable. I’ve used it so as to have a single line create either a <code>th</code> or a <code>td</code> dymamically dependent on context.</p>
<p>Only use it when you are in control of the arguments. Never use it with user input or something coming from a database.</p>
<h2 id="random-ids-or-strings" tabindex="-1">Random IDs or strings <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#random-ids-or-strings" aria-hidden="true">#</a></h2>
<p><code>object_id</code> gives you the internal ruby object id for what you’re working on. I used this in the past to append a unique id to an HTML <code>id</code> attribute value so as to automate an accessibility feature. However don’t use it unintentionally like I did there.</p>
<p>It’s better to use something like <code>rand</code>, or <code>SecureRandom</code> or <code>SecureRandom.hex</code>.</p>
<h2 id="views" tabindex="-1">Views <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#views" aria-hidden="true">#</a></h2>
<p>If you have logic you need to use in a view, this would tend to live in a <em>helper</em> method rather than in the controller.</p>
<h2 id="policies" tabindex="-1">Policies <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#policies" aria-hidden="true">#</a></h2>
<p>You might create a method such as <code>allowed_to?</code> for purposes of authorisation.</p>
<h2 id="start-(local)-rails-server" tabindex="-1">Start (local) Rails server <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#start-(local)-rails-server" aria-hidden="true">#</a></h2>
<p>Note: the following is shorthand for <code>bin/rails server -b 0.0.0.0</code>.</p>
<figure>
<pre class="language-bash"><code class="language-bash">rails s</code></pre>
</figure>
<h2 id="miscellaneous" tabindex="-1">Miscellaneous <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#miscellaneous" aria-hidden="true">#</a></h2>
<p>Use Ruby to create a local web server.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># to serve your site at localhost:5000 run this in the project’s document root</span><br />ruby -run -e httpd <span class="token builtin class-name">.</span> -p <span class="token number">5000</span></code></pre>
</figure>
<h2 id="web-fonts%3A-where-to-put-them-in-the-rails-file-structure" tabindex="-1">Web fonts: where to put them in the Rails file structure <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#web-fonts%3A-where-to-put-them-in-the-rails-file-structure" aria-hidden="true">#</a></h2>
<p>See <a href="https://gist.github.com/anotheruiguy/7379570">https://gist.github.com/anotheruiguy/7379570</a>.</p>
<h2 id="the-database" tabindex="-1">The Database <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#the-database" aria-hidden="true">#</a></h2>
<p>Reset/wipe the database.</p>
<figure>
<pre class="language-bash"><code class="language-bash">bundle <span class="token builtin class-name">exec</span> rake db:reset</code></pre>
</figure>
<h2 id="routing" tabindex="-1">Routing <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#routing" aria-hidden="true">#</a></h2>
<h2 id="get-routes-for-model-from-terminal" tabindex="-1">Get routes for model from terminal <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#get-routes-for-model-from-terminal" aria-hidden="true">#</a></h2>
<p>Let’s say you’re working on the index page for <code>pet_foods</code> and want to create a sort-by-column anchors where each link’s <code>src</code> points to the current page with some querystring parameters added. You’re first going to need the route for the current page and in the correct format.</p>
<p>To find the existing routes for <code>pet_foods</code> you can run:</p>
<figure>
<pre class="language-bash"><code class="language-bash">rails routes <span class="token operator">|</span> <span class="token function">grep</span> pet_foods</code></pre>
</figure>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/my-ruby-and-rails-cheatsheet/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.rubyguides.com/2018/02/ruby-symbols/">Symbols</a></li>
<li><a href="https://viewcomponent.org/">ViewComponent by GitHub</a></li>
<li><a href="https://learn.co/lessons/debugging-with-pry">Debugging with Pry</a></li>
<li><a href="https://blog.usejournal.com/why-byebug-will-be-your-best-friend-when-programming-in-rails-98e06f46bdb6">Why Byebug will be your best friend</a></li>
<li><a href="https://devhints.io/capybara">Capybara cheatsheet</a></li>
</ul>
Loading and Templating JSON Responses in Stimulus.js (by John Beatty)2019-12-12T15:11:32Zhttps://fuzzylogic.me/posts/2019-12-12-loading-and-templating-json-responses-in-stimulusjs-by-john-beatty/<p>Just because Stimulus.js is designed to work primarily with existing HTML doesn’t mean it can’t use JSON APIs when the need arises.</p>
<p>Here, John pimps up his Stimulus controller to get and use JSON from a remote API endpoint.</p>
<p>He triggers a <code>fetch()</code> from the <code>connect()</code> lifecycle callback, then iterates the returned JSON creating each HTML list item using a JavaScript template literal before finally rendering them into an existing <code><ul></code> via a Stimulus target.</p>
<p>Easy when you know how!</p>
Building an accessible show/hide disclosure component with vanilla JS (Go Make Things)2019-12-11T20:50:08Zhttps://fuzzylogic.me/posts/2019-12-11-building-an-accessible-showhide-disclosure-component-with-vanilla-js-go-make-things/<blockquote>
<p>A disclosure component is the formal name for the pattern where you click a button to reveal or hide content. This includes things like a “show more/show less” interaction for some descriptive text below a YouTube video, or a hamburger menu that reveals and hides when you click it.</p>
</blockquote>
<p>Chris’s article provides an accessible means of showing and hiding content at the press of a button when the native HTML <code>details</code> element isn’t suitable.</p>
The new dot com bubble is here: it’s called online advertising (The Correspondent)2019-12-10T07:45:58Zhttps://fuzzylogic.me/posts/2019-12-10-the-new-dot-com-bubble-is-here-its-called-online-advertising-the-correspondent/<blockquote>
<p>Is online advertising working? We simply don’t know</p>
</blockquote>
<p>This article reveals that despite $273bn being spent on digital ads globally (figures from 2018) the effectiveness of digital advertising is actually borderline impossible to measure. It is highly likely that any favourable figures suggested by marketers owe more to a combination of the “selection effect” and blind faith.</p>
<p>I don’t particularly enjoy being followed around the web by “targeted ads” – especially having discovered that the intrusion is relatively pointless!</p>
<p>(via <a href="https://twitter.com/clearleft">@clearleft</a>)</p>
Subgrid for CSS Grid launches in Firefox 712019-12-08T11:39:00Zhttps://fuzzylogic.me/posts/subgrid-for-css-grid-launches-in-firefox/<p>Subgrid for CSS Grid Layout has <a href="https://hacks.mozilla.org/2019/12/firefox-71-a-year-end-arrival/">arrived in Firefox</a> and it looks great. Here’s how I wrapped my head around the new concepts.</p>
<p>While MDN has <a href="https://wiki.developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Subgrid">some nice examples</a>, I generally find I need a little extra time, trial and error and note-making in order to fully grasp CSS Grid concepts.</p>
<p>For example, I always need to remind myself that parts of the syntax – such as <code>grid-template-columns</code> selectors – refer to grid <em>lines</em> rather than columns.</p>
<p>So I created a <a href="https://codepen.io/fuzzylogicx/pen/eYmpowG?editors=1100">Subgrid example pen with guideline notes</a> for future reference. Note: make sure to open the pen in Firefox rather than any other browser, because at the time of writing only Firefox supports Subgrid!</p>
Using CSS Custom Properties to streamline animation2019-12-07T13:49:00Zhttps://fuzzylogic.me/posts/using-css-custom-properties-to-streamline-animation/<p>Thanks to <a href="https://twitter.com/LucasHugdahl/status/1190438217482264576">a great tip from Lucas Hugdahl on Twitter</a>, here’s how to use CSS custom properties (variables) in your transforms so you don't need to rewrite the whole <code>transform</code> rule in order to <code>transition</code> (animate) a single property.</p>
<p>Let’s take the simple example of a <code>button</code> that we want to increase in size when hovered.</p>
<p>By using a custom property for the <code>scale</code> value, we can keep things <abbr title="Don’t Repeat Yourself">DRY</abbr>er in our <code>:hover</code> rule by only updating that variable rather than rewriting the entire <code>transform</code> rule.</p>
<p>The button HTML:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Hover over me<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span></code></pre>
<p>CSS:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">button</span> <span class="token punctuation">{</span><br /> <span class="token property">transition</span><span class="token punctuation">:</span> transform .5s ease-in-out<span class="token punctuation">;</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translateX</span><span class="token punctuation">(</span>-50%<span class="token punctuation">)</span> <span class="token function">translateY</span><span class="token punctuation">(</span>-50%<span class="token punctuation">)</span> <span class="token function">scale</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--scale<span class="token punctuation">,</span> 1<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">button:hover</span> <span class="token punctuation">{</span><br /> <span class="token property">--scale</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p><a href="https://codepen.io/fuzzylogicx/pen/PowPRwK">See it in action on Codepen</a>.</p>
IndieWeb Link Sharing | Max Böck2019-12-04T22:26:07Zhttps://fuzzylogic.me/posts/2019-12-04-indieweb-link-sharing-or-max-bock/<blockquote>
<p>A pain point of the IndieWeb is that it's sometimes not as convenient to share content as it is on the common social media platforms… That’s why I wanted to improve this process for my site.</p>
</blockquote>
<p>This was a fantastic walkthrough by <a href="https://twitter.com/mxbck">Max</a>. And based on this, I’ve just finished implementing an easy-bookmarking feature on my own website.</p>
<p>I already use this site to save <em>Bookmarks</em> so I’m hooking into that. For the bookmark-saving form, I’ve used <a href="https://stimulusjs.org/">Stimulus</a> rather than <a href="https://preactjs.com/">Preact</a>. But otherwise this is very much based on Max’s superb tutorial.</p>
<p>Here’s my bookmarklet code so that future-me can create a new browser bookmark, edit it and paste this in.</p>
<figure>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">javascript</span><span class="token operator">:</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token keyword">var</span> title <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'title'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>innerHTML<span class="token punctuation">;</span>title <span class="token operator">=</span> <span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">var</span> selection <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span>window<span class="token punctuation">.</span>getSelection<span class="token punctuation">)</span> <span class="token punctuation">{</span>selection <span class="token operator">=</span> window<span class="token punctuation">.</span><span class="token function">getSelection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>document<span class="token punctuation">.</span>selection <span class="token operator">&</span>amp<span class="token punctuation">;</span><span class="token operator">&</span>amp<span class="token punctuation">;</span> document<span class="token punctuation">.</span>selection<span class="token punctuation">.</span>type <span class="token operator">!=</span> <span class="token string">'Control'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>selection <span class="token operator">=</span> document<span class="token punctuation">.</span>selection<span class="token punctuation">.</span><span class="token function">createRange</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>text<span class="token punctuation">;</span><span class="token punctuation">}</span>selection <span class="token operator">=</span> <span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>selection<span class="token punctuation">)</span><span class="token punctuation">;</span>new_window<span class="token operator">=</span>window<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token string">'https://fuzzylogic.me/bookmarker/?title='</span><span class="token operator">+</span>title<span class="token operator">+</span><span class="token string">'&amp;body='</span><span class="token operator">+</span>selection<span class="token operator">+</span><span class="token string">'&amp;url='</span><span class="token operator">+</span><span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href<span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token string">'Sharer'</span><span class="token punctuation">,</span><span class="token string">'resizable,scrollbars,status=0,toolbar=0,menubar=0,titlebar=0,width=680,height=700,location=0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</figure>
<p>Incidentally, this process also provided a great way to dip my toes into the world of Netlify Functions and their supporting tools, <a href="https://www.netlify.com/products/dev/">netlify-dev</a> and <a href="https://github.com/netlify/netlify-lambda">netlify-lambda</a>.</p>
<p>There’s more to be done but I wanted the first bookmark created with my shiny new system to be a link to Max’s original tutorial – and this post is it.</p>
<p>Many thanks, Max!</p>
Who Can Use2019-12-04T19:00:15Zhttps://fuzzylogic.me/posts/2019-12-04-who-can-use/<blockquote>
<p>It's a tool that brings attention and understanding to how color contrast can affect different people with visual impairments.</p>
</blockquote>
<p>What’s interesting about this resource is that sheds light on the many different <em>types</em> of visual impairment, from <em>Protanomaly</em> (trouble distinguishing reds) to <em>Achromatopsia</em> (complete colour blindness; only being able to see shades) and how your website’s colour scheme fares for each. (via <a href="http://paddyduke.com/">paddyduke.com</a>)</p>
FS Split Sans and FS Split Serif (fontsmith.com)2019-12-01T16:58:08Zhttps://fuzzylogic.me/posts/2019-12-01-fs-split-sans-and-fs-split-serif-fontsmithcom/<blockquote>
<p>Although FS Split started out as a project to create a fresh, modern new sans, it has developed into a broad type family that can bring so much variety to everything from magazines and packaging to websites and branding. The conflicting yet harmonising nature of sans and serif should give designers the tools they need to be both bold and subtle, eclectic and ordinary, contemporary and classic.</p>
</blockquote>
The Size of Space (on neal.fun)2019-12-01T16:09:52Zhttps://fuzzylogic.me/posts/2019-12-01-the-size-of-space/<p>This interactive, web-based tool which lets you swipe through various space objects to see their relative size is pretty cool, really nicely done, and handy whenever you could use a dose of perspective! (via <a href="https://twitter.com/adactio">@adactio</a>)</p>
Blue Note Records: Beyond the Notes (on BBC Four)2019-11-17T20:19:00Zhttps://fuzzylogic.me/posts/2019-12-26-bbc-four-blue-note-records-beyond-the-notes/<blockquote>
<p>The story behind Blue Note Records, founded in New York in 1939 by two German Jewish refugees who allowed their musicians complete artistic freedom, revolutionising jazz in the process.</p>
</blockquote>
<p>A great watch with a fantastic back story, great interviews and amazing music including this from Art Blakey:</p>
<div class="l-frame">
<iframe title="Art Blakey & Lee Morgan – Moanin’ (alt. take)" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/nCHdXDfNgrw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
You don’t need a media query for that: #1 Inline content separators2019-11-16T15:55:39Zhttps://fuzzylogic.me/posts/2019-11-16-you-dont-need-a-media-query-for-that-1-inline-content-separators/<blockquote>
<p>Create a more flexible component which allows the text to wrap based on the content rather than the viewport size.</p>
</blockquote>
<p>Here, <a href="http://batmandy.com/">Mandy Michael</a> explores similar territory to <a href="https://every-layout.dev/">Every Layout</a> in suggesting that not all responsive pattern challenges require, or indeed are best served by, media queries.</p>
<p>The example here is a pipe-separated text pair (I could imagine an <em>author</em> and <em>publish date</em> meta line) which Mandy wants to wrap (with pipe separator hidden) only when the content and container require it, rather than based on the less-relevant <em>viewport width</em>.</p>
<p>She uses a clever combination of <code>flex-wrap:wrap</code>, generated content, padding, <code>transform</code> and <code>overflow-y:hidden</code> to achieve her goal.</p>
<p>(Via <a href="https://twitter.com/Mandy_Kerr">@Mandy_Kerr</a>)</p>
“Long Shot” DJ mix by The Nuclear Family2019-11-13T00:00:00Zhttps://fuzzylogic.me/posts/long-shot-mix/<p>A mix of electronic, house and techno records I recorded at home in November 2019.</p>
<iframe title="“Long Shot” DJ mix by The Nuclear Family" width="100%" height="120" src="https://www.mixcloud.com/widget/iframe/?hide_cover=1&hide_artwork=1&feed=%2FTheNuclearFamily%2Ftnf-mix-005-long-shot-november-2019%2F" frameborder="0"></iframe>
<p>2019 has been a fairly quiet year for my and <a href="http://tomchurchill.com/">Tom’s</a> record label The Nuclear Family. However with a couple of winter events coming up I wanted to share a little teaser mix to whet the collective appetite.</p>
<h2 id="inspiration" tabindex="-1">Inspiration <a class="direct-link" href="https://fuzzylogic.me/posts/long-shot-mix/#inspiration" aria-hidden="true">#</a></h2>
<p>Earlier in the year I joined a fine bunch of pals on a night out at 69 at The Club, Paisley to hear resident DJs Martin and Euan plus a live performance from guest John Heckle. It was a fantastic night and particularly memorable for a couple of stellar tracks played by Euan. I tried to describe them to him afterwards but wasn’t sure if I was making much sense. Cut to a few months later and a mysterious parcel containing records I’ve never heard of arrives at my door. I was convinced that someone must have sent them to me in error until dropping the needle on the grooves and realising they were the tracks from that night at 69! Channeling Sherlock Holmes, I deduced that Euan – being the all-round good guy that he is – had bought and posted them to me as a souvenir of the night. What a guy!</p>
<p>And they are brilliant.</p>
<p>The first is <em>Ricochet</em> by Bambooman (a new name on me) on Matthew Herbert’s label, <em>Accidental Jnr</em>. It features a stuttering, percussive riff complimented by searing synth stabs – proper machine funk but with a heart. The second is a double-pack by the more familiar name of i:cube, with my favourite track <em>Fractal P</em> a dark, winding, bass-heavy trip reminiscent of ’91 classic <em>Pressure Dub</em> by Ability 11 but with its own distinct flavour.</p>
<p>I knew I definitely wanted those tracks in the mix.</p>
<p>Around those touchstones I added recent favourites from Joy O (under his Sin Falta alias), Phillip McGarva (the artist formerly known as Microworld) and Dego, plus a few oldies including Isolée’s <em>Hermelin</em> and <em>Modern Tribe</em> by Jellybean (AKA Glenn Underground).</p>
<p>In terms of kit, I recorded the mix on a pair of Technics 1210s and an <a href="http://www.isonoe.com/products2/iso420-mixer/">Isonoe 420 mixer</a>.</p>
WAVE Web Accessibility Evaluation Tool2019-11-06T00:00:00Zhttps://fuzzylogic.me/posts/wave-web-accessibility-evaluation-tool/<p>The featured article in this week’s <a href="https://mailchi.mp/e7e43e8d6906/accessibility-weekly-161significant-wave-updates-and-more">Accessibility Weekly newsletter</a> was on recent improvements to the <em>WAVE</em> suite of accessibility testing tools.</p>
<p>I can’t remember using WAVE before, however just one quick test of <a href="https://fuzzylogic.me/">fuzzylogic.me</a> using their online tool revealed an accessibility issue with the linked SVG logo in the header. A great catch, now fixed, from which I learned something new. I’ll certainly be adding WAVE to my accessibility testing toolbox from here on in.</p>
<blockquote>
<p>WAVE is a suite of evaluation tools that help authors make their web content more accessible to individuals with disabilities. WAVE can identify many accessibility and Web Content Accessibility Guideline (WCAG) errors, but also facilitates human evaluation of web content. Our philosophy is to focus on issues that we know impact end users, facilitate human evaluation, and to educate about web accessibility.</p>
</blockquote>
Why much of the internet is closed off to blind people – BBC News2019-11-02T07:00:00Zhttps://fuzzylogic.me/posts/why-much-of-the-internet-is-closed-off-to-blind-people/<p>Following the recent watershed <a href="https://fuzzylogic.me/posts/dominos-lose-appeal-regarding-digital-accessibility/">Domino’s Pizza case</a>, BBC News reports that retailers in the USA & Canada are struggling to make their websites accessible and consumers are taking them to court.</p>
<blockquote>
<p>"We've even been told by businesses before that they understand, but the fact is blind people are not a very big market," Mr Danielson says. "That's what we are dealing with."</p>
</blockquote>
Colors – a nicer color palette for the web2019-11-01T00:00:00Zhttps://fuzzylogic.me/posts/colors-a-nicer-color-palette-for-the-web/<blockquote>
<p>Skinning your prototypes just got easier - colors.css is a collection of skin classes to use while prototyping in the browser.</p>
</blockquote>
<p>They also provide <a href="http://clrs.cc/a11y/">ninety examples of “A11Y compliant color combos”</a> which is really handy.</p>
“Gil Scott-Heron Saved Me”2019-10-31T00:00:00Zhttps://fuzzylogic.me/posts/gil-scott-heron-saved-me/<p>From <em>The Guardian</em> in 2011, shortly after Gil Scott-Heron’s sad death, here’s a beautiful and moving account of how the musical legend offered hope and mentorship to a young man from Liverpool and in so doing turned his life around.</p>
<p>Thanks to Nick Peacock for <a href="https://www.facebook.com/nick.peacock.944/posts/2353365751547889">sharing</a>.</p>
“Your interview test for junior developer” (from Bruce Lawson on Twitter)2019-10-30T13:39:00Zhttps://fuzzylogic.me/posts/2021-01-07-your-interview-test-for-junior-developer-from-bruce-lawson-on-twitter/<blockquote>
<p>"Ok, as part of your interview test for junior developer, we want you to put some words, an image and some links onto a webpage. We use Node, Docker, Kubernetes, React, Redux, Puppeteer, Babel, Bootstrap, Webpack, <code><div></code> and <code><span></code>. Go!"</p>
</blockquote>
<p>Bruce Lawson nicely illustrates how ridiculous many job adverts for web developers are. This (see video) never fails to crack me up. It’s funny ‘cos it’s true!</p>
<p>(via <a href="https://twitter.com/brucel">@brucel</a>)</p>
Progressively Enhanced JavaScript with Stimulus2019-10-24T00:00:00Zhttps://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/<p>I’m dipping my toes into <a href="https://stimulusjs.org/handbook/introduction">Stimulus</a>, the JavaScript micro-framework from Basecamp. Here are my initial thoughts.</p>
<p>I immediately like the ethos of Stimulus.</p>
<p>The creators’ take is that in many cases, using one of the popular contemporary JavaScript frameworks is overkill.</p>
<p>We don’t always need a nuclear solution that:</p>
<ul>
<li>takes over our whole front end;</li>
<li>renders entire, otherwise empty pages from JSON data;</li>
<li>manages state in JavaScript objects or Redux; or</li>
<li>requires a proprietary templating language.</li>
</ul>
<p>Instead, Simulus suggests a more “modest” solution – using an existing server-rendered HTML document as its basis (either from the initial HTTP response or from an AJAX call), and then progressively enhancing.</p>
<p>It advocates <em>readable markup</em> – being able to read a fragment of HTML which includes sprinkles of Stimulus and easily understand what’s going on.</p>
<p>And interestingly, Stimulus proposes storing state in the HTML/DOM.</p>
<h2 id="how-it-works" tabindex="-1">How it works <a class="direct-link" href="https://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/#how-it-works" aria-hidden="true">#</a></h2>
<p>Stimulus’ technical purpose is to automatically connect DOM elements to JavaScript objects which are implemented via ES6 classes. The connection is made by <code>data–</code> attributes (rather than <code>id</code> or <code>class</code> attributes).</p>
<p><code>data-controller</code> values connect and disconnect Stimulus controllers.</p>
<p>The key elements are:</p>
<ul>
<li>Controllers</li>
<li>Actions (essentially event handlers) which trigger controller methods</li>
<li>Targets (elements which we want to read or write to, mapped to controller properties)</li>
</ul>
<h2 id="some-nice-touches" tabindex="-1">Some nice touches <a class="direct-link" href="https://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/#some-nice-touches" aria-hidden="true">#</a></h2>
<p>I like the way you can use the <code>connect()</code> method – a <em>lifecycle callback</em> invoked whenever a given controller is connected to the DOM - as a place to test browser support for a given feature before applying a JS-based enhancement.</p>
<p>Stimulus also readily supports the ability to have multiple instances of a controller on the page.</p>
<p>Furthermore, actions and targets can be added to any type of element without the controller JavaScript needing to know or care about the specific element, promoting <em>loose coupling</em> between HTML and JavaScript.</p>
<h2 id="managing-state-in-stimulus" tabindex="-1">Managing State in Stimulus <a class="direct-link" href="https://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/#managing-state-in-stimulus" aria-hidden="true">#</a></h2>
<p>Initial state can be read in from our DOM element via a <code>data-</code> attribute, e.g. <code>data-slideshow-index</code>.</p>
<p>Then in our controller object we have access to a <code>this.data</code> API with <code>has()</code>, <code>get()</code>, and <code>set()</code> methods. We can use those methods to set new values back into our DOM attribute, so that state lives entirely in the DOM without the need for a JavaScript state object.</p>
<h2 id="possible-limitations" tabindex="-1">Possible Limitations <a class="direct-link" href="https://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/#possible-limitations" aria-hidden="true">#</a></h2>
<p>Stimulus feels a little restrictive if dealing with less simple elements – say, for example, a data table with lots of rows and columns, each differing in multiple ways.</p>
<p>And if, like in our data table example, that element has lots of child elements, it feels like there might be more of a performance hit to update each one individually rather than replace the contents with new <code>innerHTML</code> in one fell swoop.</p>
<h2 id="summing-up" tabindex="-1">Summing Up <a class="direct-link" href="https://fuzzylogic.me/posts/progressively-enhanced-javascript-with-stimulus/#summing-up" aria-hidden="true">#</a></h2>
<p>I love Stimulus’s modest and progressive enhancement friendly approach. I can see me adopting it as a means of writing modern, modular JavaScript which fits well in a <a href="https://webpack.js.org/">webpack</a> context in situations where the interactive elements are relatively simple and not composed of complex, multidimensional data.</p>
How to manage JavaScript dependencies2019-10-23T16:58:08Zhttps://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/<p>Managing JavaScript dependencies is about as much fun as a poke in the eye. However even if—like me—you prefer to keep things <a href="https://leanweb.dev/">lean</a> and dependency-free as far as possible, it’s something you’re going to need to do either in large work projects or as your personal side-project grows. In this post I tackle it head-on to reduce the problem to some simple concepts and practical techniques.</p>
<p>In modern JavaScript applications, we can add tried-and-tested open source libraries and utilities by installing <a href="https://docs.npmjs.com/about-packages-and-modules">packages</a> from the <a href="https://www.npmjs.com/">NPM registry</a>. This can aid development by letting you concentrate on your application’s <em>unique features</em> rather than reinventing the wheel for already-solved common tasks.</p>
<p>A typical example might be to add <a href="https://www.npmjs.com/package/axios">axios</a> or <a href="https://www.npmjs.com/package/node-fetch">node-fetch</a> to a Node.js project to provide a means of making API calls.</p>
<p>We can use a <em>package manager</em> such as <a href="https://yarnpkg.com/">yarn</a> or <a href="https://www.npmjs.com/get-npm">npm</a> to install packages. When our package manager installs a package it logs it as a project <em>dependency</em> which is to say that the project depends upon its presence to function properly.</p>
<p>It then follows that anyone who wants to run the application should first install its dependencies.</p>
<p>And it’s the responsibility of the project owner (you and your team) to manage the project’s dependencies over time. This involves:</p>
<ul>
<li>updating packages when they release security patches;</li>
<li>maintaining compatibility by staying on package upgrade paths; and</li>
<li>removing installed packages when they are no longer necessary for your project.</li>
</ul>
<p>While it’s important to keep your dependencies updated, in a recent survey by Sonatype <a href="https://www.sonatype.com/resources/white-paper-state-of-the-software-supply-chain-2019">52% of developers said they find dependency management painful</a>. And I have to agree that it’s not something I generally relish. However over the years I’ve gotten used to the process and found some things that work for me.</p>
<h2 id="a-simplified-process" tabindex="-1">A simplified process <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#a-simplified-process" aria-hidden="true">#</a></h2>
<p>The whole process might go something like this (NB install <a href="https://yarnpkg.com/">yarn</a> if you haven’t already).</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># Start installing and managing 3rd-party packages.</span><br /><span class="token comment"># (only required if your project doesn’t already have a package.json)</span><br /><span class="token function">yarn</span> init <span class="token comment"># or npm init</span><br /><br /><span class="token comment"># Install dependencies (in a project which already has a package.json)</span><br /><span class="token function">yarn</span> <span class="token comment"># or npm i</span><br /><br /><span class="token comment"># Add a 3rd-party library to your project</span><br /><span class="token function">yarn</span> <span class="token function">add</span> package_name <span class="token comment"># or npm i package_name</span><br /><br /><span class="token comment"># Add package as a devDependency.</span><br /><span class="token comment"># For tools only required in the local dev environment</span><br /><span class="token comment"># e.g. CLIs, hot reload.</span><br /><span class="token function">yarn</span> <span class="token function">add</span> -D package_name <span class="token comment"># or npm i package_name --save-dev </span><br /><br /><span class="token comment"># Add package but specify a particular version or semver range</span><br /><span class="token comment"># https://devhints.io/semver</span><br /><span class="token comment"># It’s often wise to do this to ensure predictable results.</span><br /><span class="token comment"># caret (^) is useful: allows upgrade to minor but not major versions.</span><br /><span class="token comment"># is >=1.2.3 <2.0.0</span><br /><span class="token function">yarn</span> <span class="token function">add</span> package_name@^1.2.3<br /><br /><span class="token comment"># Remove a package</span><br /><span class="token comment"># use this rather than manually deleting from package.json.</span><br /><span class="token comment"># Updates yarn.lock, package.json and removes from node_modules.</span><br /><span class="token function">yarn</span> remove package_name <span class="token comment"># or npm r package_name</span><br /><br /><span class="token comment"># Update one package (optionally to a specific version/range)</span><br /><span class="token function">yarn</span> upgrade package_name<br /><span class="token function">yarn</span> upgrade package_name@^1.3.2<br /><br /><span class="token comment"># Review (in a nice UI) all packages with pending updates, </span><br /><span class="token comment"># with the option to upgrade whichever you choose</span><br /><span class="token function">yarn</span> upgrade-interactive<br /><br /><span class="token comment"># Upgrade to latest versions rather than</span><br /><span class="token comment"># semver ranges you’ve defined in package.json.</span><br /><span class="token function">yarn</span> upgrade-interactive -—latest</code></pre>
</figure>
<h2 id="responding-to-a-security-vulnerability-in-a-dependency" tabindex="-1">Responding to a security vulnerability in a dependency <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#responding-to-a-security-vulnerability-in-a-dependency" aria-hidden="true">#</a></h2>
<p>If you host your source code on GitHub it’s a great idea to enable <a href="https://github.blog/2020-06-01-keep-all-your-packages-up-to-date-with-dependabot/">Dependabot</a>. Essentially Dependabot has your back with regard to any dependencies that need updated. You set it to send you automated security updates by email so that you know straight away if a vulnerability has been detected in one of your project dependencies and requires action.</p>
<p>Helpfully, if you have multiple Github repos and more than one of those include the vulnerable package you also get a round-up email with a message something like “A new security advisory on lodash affects 8 of your repositories” with links to the alert for each repo, letting you manage them all at once.</p>
<p>Dependabot also works for a variety of languages and techologies—not just JavaScript—so for example in a Rails project it might email you to suggest bumping a package in your <code>Gemfile</code>.</p>
<h3 id="automated-upgrades" tabindex="-1">Automated upgrades <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#automated-upgrades" aria-hidden="true">#</a></h3>
<p>Sometimes the task is straightforward. The Dependabot alert email tells you about a vulnerability in a package you explicitly installed and the diligent maintainer has already made a patch release available.</p>
<p>A simple <code>upgrade</code> to the relevant patch version would do the job, however <a href="https://docs.github.com/en/github/managing-security-vulnerabilities/configuring-dependabot-security-updates">Dependabot can even take care of that for you!</a> Dependabot can automatically open a new Pull Request which addresses the vulnerability by updating the relevant dependency. It’ll give the PR a title like</p>
<blockquote>
<p>Bump <code>lodash</code> from <code>4.17.11</code> to <code>4.17.19</code></p>
</blockquote>
<p>You just need to approve and merge that PR. This is great; it’s really simple and takes care of lots of cases.</p>
<p>Note 1: if you work on a corporate repo that is not set up to “automatically open PRs”, often you can still take advantage of Github’s intelligence with just one or two extra manual steps. Just follow the links in your Github security alert email.</p>
<p>Note 2: Dependabot can also be set to do automatic version updates even when your installed version does not have a vulnerability. You can enable this by <a href="https://github.blog/2020-06-01-keep-all-your-packages-up-to-date-with-dependabot/#keep-all-your-dependencies-updated">adding a <code>dependabot.yml</code> to your repo</a>. But so far I’ve tended to avoid unpredictability and excess noise by having it manage security updates only.</p>
<h3 id="manual-upgrades" tabindex="-1">Manual upgrades <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#manual-upgrades" aria-hidden="true">#</a></h3>
<p>Sometimes Dependabot will alert you to an issue but is unable to fix it for you. Bummer.</p>
<p>This might be because the package owner has not yet addressed the security issue. If your need to fix the situtation is not super-urgent, you could raise an issue on the package’s Github repo asking the maintainer (nicely) if they’d be willing to address it… or even submit a PR applying the fix for them. If you don’t have the luxury of time, you’ll want to quickly find another package which can do the same job. An example here might be that you look for a new CSS minifier package because your current one has a longstanding security issue. Having identified a replacement you’d then <code>remove</code> package A, <code>add</code> package B, then update your code which previously used package A to make it work with package B. Hopefully only minimal changes will be required.</p>
<p>Alternatively the package may have a newer version or versions available but Depandabot can’t suggest a fix because:</p>
<ol>
<li>the closest new version’s version number is beyond the allowed range you specified in <code>package.json</code> for the package; or</li>
<li>Dependabot can’t be sure that upgrading wouldn’t break your application.</li>
</ol>
<p>If the package maintainer has released newer versions then you need to decide which to upgrade to. Your first priority is to address the vulnerability, so often you’ll want to minimise upgrade risk by identifying the closest non-vulnerable version. You might then run <code>yarn upgrade <package…>@1.3.2</code>. Note also that you may not need to specify a specific version because your <code>package.json</code> might already specify a semver range which includes your target version, and all that’s required is for you to run <code>yarn upgrade</code> or <code>yarn upgrade <package></code> so that the specific “locked” version (as specified in <code>yarn.lock</code>) gets updated.</p>
<p>On other occasions you’ll read your security advisory email and the affected package will sound completely unfamiliar… likely because it’s not one you explicitly installed but rather a <em>sub-dependency</em>. Y’see, your dependencies have their own <code>package.json</code> and dependencies, too. It seems almost unfair to have to worry about these too, however sometimes you do. The vulnerability might even appear several times as a sub-dependency in your lock file’s dependency tree. You need to check that lock file (it contains much more detail than <code>package.json</code>), work out which of your top-level dependencies are dependent on the sub-dependency, then go check your options.</p>
<p>Update: use <code>yarn why sockjs</code> (replacing <code>sockjs</code> as appropriate) to find out why a module you don’t recognise is installed. It’ll let you know what module depends upon it, to help save some time.</p>
<p>When having to work out the required update to address a security vulnerability in a package that is a subdependency, I like to quickly get to a place where the task is framed in plain English, for example:</p>
<blockquote>
<p>To address a vulnerability in <code>xmlhttprequest-ssl</code> we need to upgrade <code>karma</code> to the closest available version above <code>4.4.1</code> where its dependency on <code>xmlhttprequest-ssl</code> is <code>>=1.6.2</code></p>
</blockquote>
<h4 id="case-study-1" tabindex="-1">Case Study 1 <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#case-study-1" aria-hidden="true">#</a></h4>
<p>I was recently alerted to a “high severity” vulnerability in package <code>xmlhttprequest-ssl</code>.</p>
<blockquote>
<p>Dependabot cannot update <code>xmlhttprequest-ssl</code> to a non-vulnerable version. The latest possible version that can be installed is <code>1.5.5</code> because of the following conflicting dependency: <code>@11ty/eleventy@0.12.1</code> requires <code>xmlhttprequest-ssl@~1.5.4</code> via a transitive dependency on <code>engine.io-client@3.5.1</code>. The earliest fixed version is <code>1.6.2</code>.</p>
</blockquote>
<p>So, breaking that down:</p>
<ul>
<li><code>xmlhttprequest-ssl</code> versions less than <code>1.6.2</code> have a security vulnerability;</li>
<li>that’s a problem because my project currently uses version <code>1.5.5</code> (via semver range <code>~1.5.4</code>), which I was able to see from checking <code>package-lock.json</code>;</li>
<li>I didn’t explicitly install <code>xmlhttprequest-ssl</code>. It’s at the end of a chain of dependencies which began at the <code>dependencies</code> of the package <code>@11ty/eleventy</code>, which I <em>did</em> explicitly install;</li>
<li>To fix things I want to be able to install a version of Eleventy which has updated its own dependencies such there’s no longer a subdependency on the vulnerable version of <code>xmlhttprequest-ssl</code>;</li>
<li>but according to the Dependabot message that’s not possible because even the latest version of Eleventy (<a href="https://github.com/11ty/eleventy/releases/tag/v0.12.1">0.12.1</a>) is indirectly dependent on a vulnerable version-range of <code>xmlhttprequest-ssl</code> (<code>~1.5.4</code>);</li>
<li>based on this knowledge, Dependabot cannot recommend simply upgrading Eleventy as a quick fix.</li>
</ul>
<p>So I could:</p>
<ol>
<li>decide it’s safe enough to wait some time for Eleventy to resolve it; or</li>
<li>request Eleventy apply a fix (or submit a PR with the fix myself); or</li>
<li>stop using Eleventy.</li>
</ol>
<h4 id="case-study-2" tabindex="-1">Case Study 2 <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#case-study-2" aria-hidden="true">#</a></h4>
<p>A while ago I received the following security notification about a vulnerability affecting a side-project repo.</p>
<blockquote>
<p>dot-prop < 4.2.1 “Prototype pollution vulnerability in dot-prop npm package before versions 4.2.1 and 5.1.1 allows an attacker to add arbitrary properties to JavaScript language constructs such as objects.</p>
</blockquote>
<p>I wasn’t familar with <code>dot-prop</code> but saw that it’s a library that lets you “Get, set, or delete a property from a nested object using a dot path”. This is not something I explicitly installed but rather a sub-dependency—a lower-level library that my top-level packages (or their dependencies) use.</p>
<p>Github was telling me that it couldn’t automatically raise a fix PR, so I had to fix it manually. Here’s what I did.</p>
<ol>
<li>looked in <code>package.json</code> and found no sign of <code>dot-prop</code>;</li>
<li>started thinking that it must be a sub-dependency of one or more of the packages I had installed, namely <code>express</code>, <code>hbs</code>, <code>request</code> or <code>nodemon</code>;</li>
<li>looked in <code>package-lock.json</code> and via a <kbd>Cmd-F</kbd> search for <code>dot-prop</code> I found that it appeared twice;</li>
<li>the first occurrence was as a top-level element of <code>package-lock.json</code>s top-level <code>dependencies</code> object. This object lists <em>all</em> of the project’s dependencies and sub-dependencies in alphabetical order, providing for each the details of the <em>specific version</em> that is actually installed and “locked”;</li>
<li>I noted that the installed version of <code>dot-prop</code> was <code>4.2.0</code>, which made sense in the context of the Github security message;</li>
<li>the other occurrence of <code>dot-prop</code> was buried deeper within the dependency tree as a dependency of <code>configstore</code>;</li>
<li>I was able to work backwards and see that <code>dot-prop</code> is required by <code>configstore</code> then <kbd>Cmd-F</kbd> search for <code>configstore</code> to find that it was required by <code>update-notifier</code>, which is turn is required by <code>nodemon</code>;</li>
<li>I had worked my way up to a top-level dependency <code>nodemon</code> (installed version <code>1.19.2</code>) and worked out that I would need to update <code>nodemon</code> to a version that had resolved the <code>dot-prop</code> vulnerability (if such a version existed);</li>
<li>I then googled “nodemon dot-prop” and found some fairly animated Github issue threads between <a href="https://twitter.com/remysharp">Remy</a> the maintainer of <code>nodemon</code> and some users of the package, culminating in <a href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/(https://github.com/remy/nodemon/issues/1682)">a fix</a>;</li>
<li>I checked <a href="https://github.com/remy/nodemon/releases">nodemon’s releases</a> and ascertained that my only option if sticking with <code>nodemon</code> was to install <code>v2.0.3</code>—a new major version. I wouldn’t ideally install a version which might include breaking changes but in this case <code>nodemon</code> was just a <code>devDependency</code>, not something which should affect other parts of the application, and a developer convenience at that so I went for it safe in the knowledge that I could happily remove this package if necessary;</li>
<li>I opened <code>package.json</code> and within <code>devDependencies</code> manually updated <code>nodemon</code> from <code>^1.19.4</code> to <code>^2.0.4</code>. (If I was in a <code>yarn</code> context I’d probably have done this at the command line). I then ran <code>npm i nodemon</code> to reinstall the package based on its new version range which would also update the lock file. I was then prompted to run <code>npm audit fix</code> which I did, and then I was done;</li>
<li>I pushed the change, checked my Github repo’s security section and noted that the alert (and a few others besides) had disappeared. Job’s a goodun!</li>
</ol>
<h2 id="proactively-checking-for-security-vulnerabilities" tabindex="-1">Proactively checking for security vulnerabilities <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#proactively-checking-for-security-vulnerabilities" aria-hidden="true">#</a></h2>
<p>It’s a good idea on any important project to not rely on automated alerts and proactively address vulnerabilities.</p>
<p>Check for vulnerabilities like so:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">yarn</span> audit<br /><br /><span class="token comment"># for a specific level only</span><br /><span class="token function">yarn</span> audit --level critical<br /><span class="token function">yarn</span> audit --level high<br /> </code></pre>
</figure>
<h2 id="files-and-directories" tabindex="-1">Files and directories <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#files-and-directories" aria-hidden="true">#</a></h2>
<p>When managing dependencies, you can expect to see the following files and directories.</p>
<ul>
<li><code>package.json</code></li>
<li><code>yarn.lock</code></li>
<li><code>node_modules</code> (this is the directory into which packages are installed)</li>
</ul>
<h3 id="lock-files" tabindex="-1">Lock files <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#lock-files" aria-hidden="true">#</a></h3>
<p>As well as <code>package.json</code>, you’re likely to also have <code>yarn.lock</code> (or <code>package.lock</code> or <code>package-lock.json</code>) under source control too. As described above, while <code>package.json</code> can be less specific about a package’s version and suggest a semver range, the lock file will lock down the specific version to be installed by the package manager when someone runs <code>yarn</code> or <code>npm install</code>.</p>
<p>You shouldn’t manually change a lock file.</p>
<h2 id="choosing-between-dependencies-and-devdependencies" tabindex="-1">Choosing between <code>dependencies</code> and <code>devDependencies</code> <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#choosing-between-dependencies-and-devdependencies" aria-hidden="true">#</a></h2>
<p>Whether you save an included package under <code>dependencies</code> (the default) or <code>devDependencies</code> comes down to how the package will be used and the type of website you’re working on.</p>
<p>The important practical consideration here is whether the package is necessary in the production environment. By production environment I don’t just mean the customer-facing website/application but also the enviroment that <em>builds</em> the application for production.</p>
<p>In a production “build process” environment (i.e. one which likely has the environment variable <code>NODE_ENV</code> set to <code>production</code>) the <code>devDependencies</code> are <em>not installed</em>. <code>devDependencies</code> are packages considered necessary for development only and therefore to keep production build time fast and output lean, they are ignored.</p>
<p>As an example, my personal site is JAMstack-based using the static site generator (SSG) <em>Eleventy</em> and is hosted on Netlify. On Netlify I added a <code>NODE_ENV</code> environment variable and set it to <code>production</code> (to override Netlify’s default setting of <code>development</code>) because I want to take advantage of faster build times where appropriate. To allow Netlify to build the site on each push I have Eleventy under <code>dependencies</code> so that it will be installed and is available to generate my static site.</p>
<p>By contrast, tools such as Netlify’s CLI and linters go under <code>devDependencies</code>. Netlify’s build prorcess does not require them, nor does any client-side JavaScript.</p>
<h2 id="upgrading-best-practices" tabindex="-1">Upgrading best practices <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#upgrading-best-practices" aria-hidden="true">#</a></h2>
<ul>
<li>Check the package CHANGELOG or releases on Github to see what has changed between versions and if there have been any breaking changes (especially when upgrading to the latest version).</li>
<li>Use a dedicated PR (Pull Request) for upgrading packages. Keep the tasks separate from new features and bug fixes.</li>
<li>Upgrade to the latest minor version (using <code>yarn upgrade-interactive</code>) and merge that before upgrading to major versions (using <code>yarn upgrade-interactive -—latest</code>).</li>
<li>Test your work on a staging server (or Netlify preview build) before deploying to production.</li>
</ul>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/how-to-manage-javascript-dependencies/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://classic.yarnpkg.com/en/docs/yarn-workflow/">Yarn workflow</a></li>
<li><a href="https://devhints.io/semver">Semver cheatsheet</a></li>
<li><a href="https://www.robertcooper.me/how-yarn-lock-files-work-and-upgrading-dependencies">Good explanation of the purpose of a lock file</a></li>
</ul>
Jank-free Responsive Images2019-10-23T00:00:00Zhttps://fuzzylogic.me/posts/jank-free-responsive-images/<p>Here’s how to improve performance and prevent layout <em>jank</em> when browsers load responsive images.</p>
<p>Since the advent of the Responsive Web Design era many of us, in our rush to make images flexible and adaptive, stopped applying the HTML <code>width</code> and <code>height</code> attributes to our images. Instead we’ve let CSS handle the image, setting a <code>width</code> or <code>max-width</code> of 100% so that our images can grow and shrink but not extend beyond the width of their parent container.</p>
<p>However there was a side-effect in that browsers load text first and images later, and if an image’s dimensions are not specified in the HTML then the browser can’t assign appropriate space to it before it loads. Then, when the image finally loads, this <em>bumps</em> the layout – affecting surrounding elements in a nasty, <em>janky</em> way.</p>
<p><a href="https://css-tricks.com/the-fight-against-layout-jank/">CSS-tricks have written about this</a> several times however I’d never found a solid conclusion.</p>
<h2 id="chrome%E2%80%99s-performance-warning" tabindex="-1">Chrome’s Performance Warning <a class="direct-link" href="https://fuzzylogic.me/posts/jank-free-responsive-images/#chrome%E2%80%99s-performance-warning" aria-hidden="true">#</a></h2>
<p>The other day I was testing <a href="https://fuzzylogic.me/">this here website</a> in Chrome and noticed that if you don’t provide images with inline width and height attributes, Chrome will show a console warning that this is negatively affecting performance.</p>
<p>Based on that, I made the following updates:</p>
<ol>
<li>I added width and height HTML attributes to all images; and</li>
<li>I changed my CSS from <code>img { max-width: 100%; }</code> to <code>img { width: 100%; height: auto; }</code>.</li>
</ol>
<p>NB the reason behind #2 was that I found that that CSS works better with an image with inline dimensions than <code>max-width</code> does.</p>
<h2 id="which-dimensions-should-we-use%3F" tabindex="-1">Which dimensions should we use? <a class="direct-link" href="https://fuzzylogic.me/posts/jank-free-responsive-images/#which-dimensions-should-we-use%3F" aria-hidden="true">#</a></h2>
<p>Since an image’s actual rendered dimensions will depend on the viewport size and we can’t anticipate that viewport size, I plumped for a <code>width</code> of 320 (a narrow mobile width) × <code>height</code> of 240, which fits with this site’s standard image aspect ratio of 4:3.</p>
<p>I wasn’t sure if this was a good approach. Perhaps I should have picked values which represented the dimensions of the image on desktop.</p>
<h2 id="jen-simmons-to-the-rescue" tabindex="-1">Jen Simmons to the rescue <a class="direct-link" href="https://fuzzylogic.me/posts/jank-free-responsive-images/#jen-simmons-to-the-rescue" aria-hidden="true">#</a></h2>
<p>Jen Simmons of Mozilla has <a href="https://www.youtube.com/watch?v=4-d_SoCHeWE&feature=youtu.be">just posted a video</a> which not only confirmed that my above approach was sound, but also provided lots of other useful context.</p>
<p>Essentially, we should start re-applying HTML width and height attributes to our images, because in soon-to-drop Firefox and Chrome updates the browser will use these dimensions to calculate the image’s <em>aspect ratio</em> and thereby be able to allocate the exact required space.</p>
<p>The actual dimensions we provide don’t matter too much so long as they represent the correct aspect ratio.</p>
<p>Also, if we use the modern <code>srcset</code> and <code>sizes</code> syntax to offer the browser different image options (like I do on this site), so long as the different images are the same aspect ratio then this solution will continue to work well.</p>
<p>There’s no solution at present for the <a href="https://cloudfour.com/thinks/responsive-images-101-definitions/#artdirection">Art Direction use case</a> – where we want to provide different aspect ratios dependent on viewport size – but hopefully that will come along next.</p>
<p>I just tested this new feature in Firefox Nightly 72, using the Inspector’s Network tab to set “throttling” to 2G to simulate a slow-loading connection, and it worked really well!</p>
<h2 id="lazy-loading" tabindex="-1">Lazy Loading <a class="direct-link" href="https://fuzzylogic.me/posts/jank-free-responsive-images/#lazy-loading" aria-hidden="true">#</a></h2>
<p>One thing I’m keen to test is that my newly-added inline <code>width</code> and <code>height</code> attributes play well with <code>loading="lazy"</code>. I don’t see why they shouldn’t and in fact they should in theory all support each other well. In tests so far everything seems good, however since <code>loading="lazy"</code> is currently only implemented in Chrome I should re-test images in Chrome once it adds support for the new image aspect ratio calculating feature, around the end of 2019.</p>
Beyond Automatic Testing (matuzo.at)2019-10-20T15:02:00Zhttps://fuzzylogic.me/posts/beyond-automatic-testing-matuzo/<p>Six accessibility tests Viennese Front-end Developer Manuel Matusovic runs on every website he develops, beyond simply running a Lighthouse audit.</p>
<p>Includes “Test in Grayscale Mode” and “Test with no mouse to check tabbing and focus styles”.</p>
Do Androids Dream of Electric Sheep? by Philip K. Dick2019-10-19T00:00:00Zhttps://fuzzylogic.me/posts/do-androids-dream-of-electric-sheep-by-phillip-k-dick/<p>In my ongoing quest to catch up on books I should have read years ago, I recently finished reading “Do Androids Dream of Electric Sheep?” – the book on which <em>Bladerunner</em> was based.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571641370/F4A2AEE5-111A-4D7B-AEE3-F93771203FE7_ecgnsi.jpg" width="320" height="240" alt="A photo of the book “Do Androids Dream of Electric Sheep?” by Philip K. Dick" loading="lazy" decoding="async" />
<figcaption>Do Androids Dream of Electric Sheep</figcaption>
</figure>
<p>I’m a big Bladerunner fan – and also loved last year’s follow up movie, Bladerunner 2049 – but for me, the book was a mixed bag.</p>
<p>It illuminated some of the parts of the film that in retrospect hadn’t fully sunk in – like why animals (such as Tyrell Corp’s owl) were so important in post-apocalyptic San Fransisco, due to most species being endangered or extinct.</p>
<p>It also went much deeper into the question of whether empathy and similar social emotions were solely human abilities or could be felt by androids too. And I can see now see why this was explored further with lead character Joe in Bladerunner 2049.</p>
<p>On the downside, the techno-religious angle of Mercerism didn’t really work for me – although maybe I didn’t pick up properly on the metaphor. Also, I was kind of disappointed to learn that there actually is an electric sheep in the story! I had always loved the title and thought it was just a really clever reference to counting sheep in your dreams, rather than something so literal. Never mind!</p>
<p>All of the downsides were worth it, however, for the detailed parts about <em>Voight-Kampff</em> empathy tests. I have always loved the ideas and language around this, such as measuring androids for their <em>Blush Response</em> and other signs of empathy when asked questions which would normally elicit a reaction in humans.</p>
<p>All in, I’m glad I read it to gain the additional background to the movies.</p>
<p>I’m now off to watch Bladerunner again.</p>
Note 2019-10-18T19:03:21: Everybody’s on a trip2019-10-18T19:03:21Zhttps://fuzzylogic.me/posts/1571418045-everybody-trip/<p>Original 1979 copies of Garden of Eden’s <em>Everybody’s on a Trip</em> regularly sell for £200+ so I was pretty happy to hear that it had just been reissued on Backatcha records… and even happier when I managed to snag a copy.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571416676/83F1E10C-7525-4574-8E80-49989103A25A_et3f0f.jpg" width="320" height="240" alt="“Everybody’s on a Trip” by Garden of Eden, a 7″ vinyl release on Backatcha records" loading="lazy" decoding="async" />
<figcaption>My copy of “Everybody’s on a Trip” by Garden of Eden</figcaption>
</figure>
<p>I first heard this stellar slice of deep funk a few years back on Kon and Amir’s compilation <em>Off Track Volume One: The Bronx</em>, and have been hankering after a proper copy ever since.</p>
<p>Check it out!</p>
<div class="l-frame">
<iframe title="Video of Everybody’s on a Trip by Garden of Eden" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/FIi10Bww5LM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
U.S. Supreme Court Favors Digital Accessibility in Domino’s Case2019-10-17T15:51:00Zhttps://fuzzylogic.me/posts/dominos-lose-appeal-regarding-digital-accessibility/<blockquote>
<p>Digital products which are a public accommodation must be accessible, or will be subject to a lawsuit (and probably lose).</p>
</blockquote>
<p>This US Supreme Court decision on October 7, 2019 represents a pretty favourable win for digital accessibility against a big fish that was trying to shirk its responsibilities.</p>
Replicating Jekyll’s markdownify filter in Nunjucks with Eleventy2019-10-16T16:51:00Zhttps://fuzzylogic.me/posts/replicating-jekylls-markdownify-filter-in-nunjucks-with-eleventy/<p>Here, <a href="https://edjohnsonwilliams.co.uk/">Ed</a> provides some handy code to convert a Markdown-formatted string into HTML in Nunjucks via an Eleventy shortcode.</p>
<p>This performs the same role as the <a href="https://jekyllrb.com/docs/liquid/filters/"><em>markdownify</em> filter in Jekyll</a>.</p>
<p>I’m now using it on this site in listings, using the shortcode to convert blog entry <em>excerpts</em> written in markdown (which might contain code or italics, etc) into the target HTML.</p>
Semantic Commit Messages2019-10-16T15:51:00Zhttps://fuzzylogic.me/posts/semantic-commit-messages/<p>A fairly rigid commit format (<code>chore</code>, <code>fix</code>, <code>feat</code> etc) which should lead to your git log being an easy-to-skim changelog.</p>
<p>I’d noticed that my git commit messages could benefit from greater consistency. So I’ve started adopting Sparkbox’s approach.</p>
<p>Here’s how to use the different commit types:</p>
<pre><code>chore: add Oyster build script
docs: explain hat wobble
feat: add beta sequence
fix: remove broken confirmation message
refactor: share logic between 4d3d3d3 and flarhgunnstow
style: convert tabs to spaces
test: ensure Tayne retains clothing
</code></pre>
The Testament of Gideon Mack by James Robertson2019-10-01T00:00:00Zhttps://fuzzylogic.me/posts/the-testament-of-gideon-mack-by-james-robertson/<p>A strange, otherwordly and often pretty funny tale of a Scottish minister’s dance with The Devil.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571660696/448E94E3-916B-4620-B4BE-465B6D29946B_cajijd.jpg" width="320" height="240" alt="A photo of the book “The Testament of Gideon Mack” by James Robertson" loading="lazy" decoding="async" />
<figcaption>The Testament of Gideon Mack by James Robertson</figcaption>
</figure>
<p>Cheers for the recommendation, Mick!</p>
Lazy load embedded YouTube videos (CSS-Tricks)2019-09-30T10:00:35Zhttps://fuzzylogic.me/posts/2019-12-27-lazy-load-embedded-youtube-videos-csstricks/<blockquote>
<p>This is a very clever idea via Arthur Corenzan. Rather than use the default YouTube embed, which adds a crapload of resources to a page whether the user plays the video or not, use the little tiny placeholder webpage that is just an image you can click that is linked to the YouTube embed.</p>
</blockquote>
<p>Here’s a performance-enhancing trick for embedding youtube videos which eschews the default YouTube <code>embed</code> (and all the resources it adds to a page whether the video plays or not) in favour of rendering a tiny placeholder webpage in the <code>srcdoc</code> attribute.</p>
<p>Importantly, the user experience with the video remains the same.</p>
Relearn CSS layout: Every Layout2019-09-05T23:00:00Zhttps://fuzzylogic.me/posts/relearn-css-layout-every-layout/<p>Every now and then something comes along in the world of web design that represents a substantial shift. The launch of <a href="https://every-layout.dev/">Every Layout</a>, a new project from Heydon Pickering and Andy Bell, feels like one such moment.</p>
<p>In simple terms, we get a bunch of responsive layout utilities: a Box, a Stack, a Sidebar layout and so on. However Every Layout offers so much more—in fact for me it has provided whole new ways of thinking and talking about modern web development. In that sense I’m starting to regard it in terms of classic, game-changing books like <a href="https://abookapart.com/products/responsive-web-design">Responsive Web Design</a> and <a href="https://abookapart.com/products/mobile-first">Mobile First</a>.</p>
<p>Every Layout’s components, or <em>primitives</em>, are self-governing and free from media queries. This is a great step forward because media queries tie layout changes to the viewport, and that’s suboptimal when our goal is to create modular components for Design Systems which should adapt to variously-sized containers. Every Layout describe their components as existing in a <em>quantum state</em>: simultaneously offering both narrow and wide configurations. Importantly, the way their layouts adapt is also linked to the dynamic <em>available space</em> in the container and the intrinsic width of its contents, which leads to more fluid, organic responsiveness.</p>
<p>Every Layout’s approach feels perfect for the new era of CSS layout where we have CSS Grid and Flexbox at our disposal. They use these tools to <em>suggest</em> rather than dictate, letting the browser make appropriate choices based on its native algorithms.</p>
Webfont loading strategies2019-09-02T19:15:40Zhttps://fuzzylogic.me/posts/webfont-loading-strategies/<p>When it comes to webfonts, if you want to serve an accessible and high performance experience across device types it’s not as straightforward as just specifying your fonts in CSS then hoping for the best.</p>
<p>We likely have goals such as the following:</p>
<ul>
<li>avoid Flash of Invisible Text (FOIT). Flash of Unstyled Text (FOUT) is preferable.</li>
<li>provide a good experience for users on slow connections.</li>
<li>while favouring FOUT over FOIT, take care to minimise jarring reflows.</li>
</ul>
<p>Browser support is also a factor. For example <code>font-display: swap</code> seems like a great option however as Chris Ferdinandi pointed out in <a href="https://gomakethings.com/why-use-the-vanilla-js-fontfaceset.load-method-instead-of-the-css-font-display-swap-property/"><em>Why use the vanilla JS fontfaceset.load method instead of CSS font-display: swap</em></a> it doesn’t have comprehensive mobile support. Since mobile users are regularly on slower connections they are likely to be hit hard by load times incurred due to custom fonts, therefore a solution which doesn’t cater to them is less attractive.</p>
<p>I tend to go for <a href="https://www.zachleat.com/web/comprehensive-webfonts/#fout-class">FOUT with a class</a>—an approach that is reliable and good enough for most use cases. The idea is to use JavaScript to detect when a font has loaded successfully, and only then add a <code>fonts-loaded</code> class to the HTML element causing CSS scoped to that class to take effect. To date I’ve handled the detection using <a href="https://github.com/bramstein/fontfaceobserver">Bram Stein’s Font Face Observer</a> to benefit from greater browser support (it handles IE) than I’d get using the native <code>FontFaceSet.load()</code> however I expect to gravitate toward the <a href="https://gomakethings.com/a-modern-font-loading-strategy-with-the-vanilla-js-fontfaceset.load-method/">native API solution</a> soon.</p>
<p>I’ve also experimented with pre-loading fonts in the <code><head></code> in combination with <code>font-display: swap</code> on this, my personal website. This was inspired by <a href="https://zachleat.com/web/css-tricks-web-fonts/">the font-loading approach Zach Leatherman took with CSS-Tricks</a>. However due to the fonts I’m using right now I’d currently be preloading too heavy a load for slow connections (thus temporarily <em>blocking</em> initial page render) so I’d need to go further and introduce two-stage loading into that mix.</p>
<p>I’ve also found that your choice of font and font host can really influence (constrain) the flexibility and options you have for font features and loading.</p>
<ul>
<li><code>font-display: swap</code> can only be applied on a self-hosted font or one hosted on Google Fonts (via a special querystring parameter on the font URL). So this CSS-only approach is not available with (for example) fonts hosted on Adobe Fonts or <a href="http://fonts.com/">fonts.com</a>.</li>
<li><code>link rel=preload</code> is only available for self-hosted fonts because you need to be able to rely on the URL not changing, and you can’t rely on that for externally hosted fonts.</li>
<li>You might want to use the opentype features of a font but are they available in your font hosting/loading solution? Some of the fonts hosted on Google Fonts have nice OpenType features but by default these features are pruned out.</li>
<li>Getting access to the source <code>.ttf</code> file is beneficial as it allows you to <em>subset</em> the font, including special features and characters but also cutting out any your website does not require. Google Fonts have an open license which means we don’t need to lean on their hosting but can instead download fonts in <code>.ttf</code>, subset them (I use <a href="https://github.com/filamentgroup/glyphhanger">Glyphhanger</a>) and self-host them.</li>
</ul>
<p>This is all a work in progress and I’m still working this stuff out.</p>
Animating the underlining of multi-line text2019-09-01T08:12:37Zhttps://fuzzylogic.me/posts/2019-12-12-multiline-spanning-animated-underline/<p><a href="https://twitter.com/cassiecodes">Cassie Evans</a> shows us how to combine <code>background–size</code>, a <code>linear-gradient</code> based <code>background-image</code> and a keyframe animation (all in HTML and CSS) for a lovely progressive underline effect on multi-line text.</p>
<p>Here’s the gist of it:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>This is a multi-line spanning animated underline. This took an annoyingly long time to figure out.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-css"><code class="language-css"><span class="token selector">body</span> <span class="token punctuation">{</span><br /> <span class="token property">padding</span><span class="token punctuation">:</span> 40vh 30vw<span class="token punctuation">;</span><br /> <span class="token property">font-family</span><span class="token punctuation">:</span> cursive<span class="token punctuation">;</span><br /> <span class="token property">text-align</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span><br /> <span class="token property">font-size</span><span class="token punctuation">:</span> 130%<span class="token punctuation">;</span> <br /><span class="token punctuation">}</span><br /><br /><span class="token selector">h2</span> <span class="token punctuation">{</span><br /> <span class="token property">line-height</span><span class="token punctuation">:</span> 1.5<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> inline<span class="token punctuation">;</span><br /> <span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token function">linear-gradient</span><span class="token punctuation">(</span><br /> transparent 50%<span class="token punctuation">,</span><br /> #e1fffe 50%<span class="token punctuation">,</span><br /> #b0f8ff 85%<span class="token punctuation">,</span><br /> transparent 85%<span class="token punctuation">,</span><br /> transparent 100%<br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">background-repeat</span><span class="token punctuation">:</span> no-repeat<span class="token punctuation">;</span><br /> <span class="token property">background-size</span><span class="token punctuation">:</span> 0% 100%<span class="token punctuation">;</span><br /> <span class="token property">animation</span><span class="token punctuation">:</span> animatedBackground 2s <span class="token function">cubic-bezier</span><span class="token punctuation">(</span>0.645<span class="token punctuation">,</span> 0.045<span class="token punctuation">,</span> 0.355<span class="token punctuation">,</span> 1<span class="token punctuation">)</span> 0.5s forwards<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token atrule"><span class="token rule">@keyframes</span> animatedBackground</span> <span class="token punctuation">{</span><br /> <span class="token selector">to</span> <span class="token punctuation">{</span><br /> <span class="token property">background-size</span><span class="token punctuation">:</span> 100% 100%<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>Thanks, Cassie!</p>
Native lazy-loading for the web2019-08-30T15:02:00Zhttps://fuzzylogic.me/posts/native-lazy-loading-for-the-web/<p>Now that we have the HTML attribute <code>loading</code> we can set <code>loading="lazy"</code> on our website’s media, and the loading of non-critical, <em>below-the-fold</em> media will be deferred until the user scrolls to them.</p>
<p>This can really improve performance so I’ve implemented it on images and iframes (youtube video embeds etc) throughout this site.</p>
<p>This is <a href="https://caniuse.com/#feat=loading-lazy-attr">currently only supported in Chrome</a>, but that still makes it well worth doing.</p>
Fringe Making2019-08-27T13:32:00Zhttps://fuzzylogic.me/posts/fringe-making/<p>Last Tuesday, 20/8/19 I made the train trip east for a day at the Edinburgh Festival Fringe.</p>
<p>There are always a variety of interesting shows to catch in the month-long festival and this year I was particularly looking foward to Darren McGarvey <abbr>AKA</abbr> Loki’s <em>Scotland Today</em>. Having <a href="https://fuzzylogic.me/posts/poverty-safari-by-darren-mcgarvey/">read and enjoyed</a> McGarvey’s book <em>Poverty Safari</em> last year I was keen to see and hear him in the flesh.</p>
<p>Another reason for the trip was that during a recent stint working with <a href="https://brightsignals.co.uk/">Bright Signals</a> I developed the <em>FringeMaker</em> web app – a Pokémon Go style game where you win points by “checking into” Fringe gig venues – so I was excited to hit the Edinburgh streets to give it a spin for real.</p>
<p>First port of call was to meet my friends Mick and Laura at George Square for a catch up and pre-gig beer. Having made it through the festival crowds and pouring rain to find them, we took temporary refuge with a pint and some tasty pizza from the nearby stalls, before setting off for our first gig: <span class="nobreak">Tony Slattery’s <em>Slattery Will Get You Nowhere</em></span>.</p>
<h2 id="slattery-will-get-you-nowhere" tabindex="-1">Slattery will get you nowhere <a class="direct-link" href="https://fuzzylogic.me/posts/fringe-making/#slattery-will-get-you-nowhere" aria-hidden="true">#</a></h2>
<p>In the early nineties I enjoyed watching Tony on <em>Whose Line is it Anyway?</em> and I was moved by a recent <a href="https://www.theguardian.com/lifeandstyle/2019/apr/29/tony-slattery-had-very-happy-time-went-slightly-barmy">Guardian interview</a> which revealed that in the years following the show ending he fell off the rails somewhat due to his bipolar disorder allied to alcohol and drug addictions, and was now looking for an agent and new opportunities.</p>
<p>The format of this show was just Tony and comedy historian Robert Ross sat at a table, with Tony answering a series of unscripted questions. Over the course of an hour he stepped through his career, from winning the Fringe’s inaugural Perrier Award with Cambridge Footlights pals Stephen Fry, Hugh Laurie and Emma Thompson (“yeah but where are they <em>now</em>?”), to pant-splitting (literally) and deleted scenes on <em>Whose Line is it Anyway?</em>, to acting roles in films such as <em>Peter’s Friends</em>. It was filled with funny anecdotes involving the likes of Rik Mayall and Kenneth Branagh, plus a few might-have-been stories such as when he narrowly missed out (to Sylvester McCoy) on the role of Doctor Who.</p>
<p>Overall I really enjoyed this. Despite having problems which have taken their toll, Tony Slattery is still a funny and engaging performer and is also doing his bit to help raise awareness of bipolar disorder. He seems like a good egg.</p>
<h2 id="scotland-today" tabindex="-1">Scotland Today <a class="direct-link" href="https://fuzzylogic.me/posts/fringe-making/#scotland-today" aria-hidden="true">#</a></h2>
<p>Onwards to Darren McGarvey’s show at The Stand’s New Town Theatre, and he unexpectedly begins with a TED Talk style discussion on space and quantum mechanics, setting up the idea that there are two contradictory versions of himself.</p>
<p>There’s the pre- <em>Poverty Safari</em>, lower working class <em>CDE2</em> Darren; and the new, “poster child for working class politics”, middle-class, <em>ABC1</em> Darren.</p>
<p>During the show he mostly speaks as the “new Darren”, describing how his situation has improved and priorities changed since no longer having to constantly worry about financial security. He is still angry about the injustices of life in the <abbr>UK</abbr> – citing the inadequate response to the Grenfell Tower Disaster as an example – but also realises that he has become a contradiction given his new status.</p>
<p>He moves on to suggest that the ABC1 group are in a privileged position, uniquely placed to get ahead in life while others can’t; and that because they don’t properly understand the circumstances of the CDE2s they are therefore not in a position to be making the decisions that affect them.</p>
<p>He contrasts the comfortable lives of the ABC1s with those of the CDE2s who live in <em>quicksand</em> – constantly being dragged down by financial and other societal problems, with no prospect of getting out and a feeling that by attempting to escape you only make matters worse.</p>
<p>McGarvey finishes by switching to his angry, in-your-face, baseball cap wearing alter-ego from another possible timeline; not blessed with the fortune of middle-class Darren and furious about the injustices of his situation and life in Tory-led Britain.</p>
<p>Again, I really enjoyed this show, and felt that McGarvey was just as powerful in the flesh as on paper, if not more so. There were maybe a few too many narrative devices and gimmicks going on than necessary, but he’s a really interesting voice and continually says things which make me think and challenge myself.</p>
<p>I think his new BBC show, <a href="https://www.bbc.co.uk/programmes/m00087lh">Darren McGarvey's Scotland</a> will definitely be one to watch.</p>
Flexible tag-like functionality for custom keys in Eleventy2019-08-26T13:49:00Zhttps://fuzzylogic.me/posts/flexible-tag-like-functionality-for-custom-keys-in-eleventy/<p>I have an open-source, Eleventy-based project where the posts are restaurants, each of which is located in a particular city, and contributors to the repo can add a new restaurant as a simple markdown file.</p>
<p>I just had to solve a conundrum wherein I wanted a custom front matter key, <em>city</em>, to have similar features as <em>tags</em>, namely:</p>
<ol>
<li>it takes arbitrary values (e.g. <em>Glasgow</em>, or <em>London</em>, or <em>Cañon City</em>, or anything a contributor might choose);</li>
<li>there is a corresponding <em>cityList</em> <a href="https://www.11ty.io/docs/collections/">collection</a>;</li>
<li>there is a page which lists all cities in the <em>cityList</em> collection as links; and</li>
<li>there’s a page for each city which lists all restaurants in that city (much like a “Tagged <em>Glasgow</em>” page).</li>
</ol>
<p>You could be forgiven for asking: why didn’t I just implement the cities as tags? I could have tagged posts with “glasgow”, or “edinburgh” for example. Well, here was my rationale:</p>
<ul>
<li>for cities, I need the proper, correctly spelled, spaced and punctuated name so I can display it as a page title. A lowercased, squashed together “tag” version wouldn’t cut it;</li>
<li>I list “all tags” elsewhere and wouldn’t want the cities amongst them. Although Eleventy allows you to filter given tag values out, in this case that would be a pain to achieve because the city values are not known up front;</li>
<li>Lastly it just <em>felt right</em> for ease of future data manipulation that city should be a separate entity.</li>
</ul>
<p>This task was a bit of a head-scratcher and sent me down a few blind alleys at first. Rightly or wrongly, it took me a while to realise that only all posts for <em>tag values</em> are automatically available as collections in Eleventy. So any other collections you need, you have to DIY. Once I worked that out, I arrived at a strategy of:</p>
<blockquote>
<p>implement all the requisite functionalty on <strong>tags</strong> first, then emulate that functionality for my custom key.</p>
</blockquote>
<p>First port of call was <a href="https://www.11ty.io/docs/quicktips/tag-pages/">the Eleventy <em>Tag Pages</em> tutorial</a>. That showed me how to use the existing “collection for each tag value” to create a <em>page</em> for each tag value – the “All posts tagged with X” convention. (Here’s <a href="https://fuzzylogic.me/tagged/music/">an example on this site</a>.)</p>
<p>I then referenced the <a href="https://github.com/11ty/eleventy-base-blog"><em>eleventy-base-blog</em> repo</a> which takes things further by creating a page which lists “all tags”. To achieve this you first need to create a custom <em>tagList</em> collection, then you create a page which accesses that new collection using <code>collections.tagList</code>, iterates it and displays each tag as a link. Each tag link points to its corresponding “All posts tagged with X” page we created in the step above.</p>
<p>So now I had everything working for tags. Next step: emulate that for <em>cities</em>.</p>
<p>Here’s what I ended up doing:</p>
<p>Create new file <code>_11ty/getCityList.js</code></p>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">collection</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> citySet <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Set</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> collection<span class="token punctuation">.</span><span class="token function">getAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span><span class="token punctuation">(</span> <span class="token string">"city"</span> <span class="token keyword">in</span> item<span class="token punctuation">.</span>data <span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> city <span class="token operator">=</span> item<span class="token punctuation">.</span>data<span class="token punctuation">.</span>city<span class="token punctuation">;</span><br /> citySet<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>city<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token operator">...</span>citySet<span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Then add the following to <code>.eleventy.js</code></p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Create a collection of cities</span><br />eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"cityList"</span><span class="token punctuation">,</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./_11ty/getCityList"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Create "restaurants in city" collections keyed by city name</span><br />eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"cityCollections"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">collection</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> resultArrays <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /> collection<span class="token punctuation">.</span><span class="token function">getAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span><span class="token punctuation">(</span>item<span class="token punctuation">.</span>data<span class="token punctuation">[</span><span class="token string">"title"</span><span class="token punctuation">]</span> <span class="token operator">&&</span> item<span class="token punctuation">.</span>data<span class="token punctuation">[</span><span class="token string">"city"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span><span class="token punctuation">(</span> <span class="token operator">!</span>resultArrays<span class="token punctuation">[</span>item<span class="token punctuation">.</span>data<span class="token punctuation">[</span><span class="token string">"city"</span><span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> resultArrays<span class="token punctuation">[</span>item<span class="token punctuation">.</span>data<span class="token punctuation">[</span><span class="token string">"city"</span><span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> resultArrays<span class="token punctuation">[</span>item<span class="token punctuation">.</span>data<span class="token punctuation">[</span><span class="token string">"city"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> resultArrays<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Next, create new file <code>cities-list.njk</code>:</p>
<pre class="language-liquid"><code class="language-liquid">---<br />permalink: /cities/<br />layout: layouts/home.njk<br />---<br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>All Cities<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%-</span> <span class="token keyword">for</span> city <span class="token keyword">in</span> collections<span class="token punctuation">.</span>cityList <span class="token delimiter punctuation">-%}</span></span><br /> <span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> set cityUrl <span class="token delimiter punctuation">-%}</span></span>/cities/<span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> city <span class="token delimiter punctuation">}}</span></span>/<span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> endset <span class="token delimiter punctuation">%}</span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> cityUrl <span class="token operator">|</span> <span class="token function filter">url</span> <span class="token delimiter punctuation">}}</span></span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> city <span class="token delimiter punctuation">}}</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%-</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">-%}</span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
<p>Finally, create new file <code>posts-in-city.njk</code>:</p>
<pre class="language-liquid"><code class="language-liquid">---<br />renderData:<br /> title: Restaurants in “<span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> city <span class="token delimiter punctuation">}}</span></span>”<br />pagination:<br /> data: collections.cityList<br /> size: 1<br /> alias: city<br />permalink: /cities/<span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> city <span class="token operator">|</span> <span class="token function filter">slug</span> <span class="token delimiter punctuation">}}</span></span>/<br />---<br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Restaurants in <span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> city <span class="token delimiter punctuation">}}</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /><br /><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> set postslist <span class="token operator">=</span> collections<span class="token punctuation">.</span>cityCollections<span class="token punctuation">[</span> city <span class="token punctuation">]</span> <span class="token delimiter punctuation">%}</span></span><br /><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> <span class="token keyword">include</span> &#<span class="token number">39</span>;postslist<span class="token punctuation">.</span>njk&#<span class="token number">39</span>; <span class="token delimiter punctuation">%}</span></span></code></pre>
<p>And that’s a wrap! Eleventy will do the rest when it next runs, creating for each city a page which lists all restaurants in that city.</p>
<p>Footnote: I should acknowledge <a href="https://github.com/11ty/eleventy/issues/259">this 11ty Github issue</a> in which <a href="https://twitter.com/edwardhorsford">Ed Horsford</a> was trying to do something similar (create a <em>separate</em> tags network) leading to <a href="https://twitter.com/zachleat">Zach Leatherman</a> pitching in with how he created <em>noteTags</em> for his website’s Notes section. That led me to Zach’s website’s repo on Github, specifically <a href="https://fuzzylogic.me/posts/flexible-tag-like-functionality-for-custom-keys-in-eleventy/tag-pages.njk">.eleventy.js</a> and <a href="https://github.com/zachleat/zachleat.com/blob/master/web/notes/tag-pages.njk">tag-pages.njk</a>, without which I wouldn’t have found my way.</p>
Get Waves2019-08-25T15:02:00Zhttps://fuzzylogic.me/posts/get-waves/<p>I’ve been admiring the wave effect at the foot of banners on <a href="https://www.netlify.com/blog/">Netlify’s website</a> and had noted that they were achieved using SVG. So this tool which helps you “make waves” is pretty timely!</p>
Note 2019-08-15T10:03:21: The Cure Gig2019-08-15T10:03:21Zhttps://fuzzylogic.me/posts/1565863401-cure/<p>In second year a nice school pal introduced me to The Cure when I was on an otherwise strict diet of rave tapes. <em>Mixed Up</em> with its dubby extended mixes sealed the deal. Shamefully haven’t yet seen them live so I’m at fever pitch for tomorrow’s gig at Bellahouston Park. Hopefully see some of you there!</p>
<div class="l-frame">
<iframe title="Video of Fascination Street (Extended Mix) by The Cure" loading="lazy" width="560" height="315" src="https://www.youtube-nocookie.com/embed/rzmL7ZPq1bM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
Time’s Healing, by Mac-Talla Nan Creag2019-08-14T15:15:03Zhttps://fuzzylogic.me/posts/time%E2%80%99s-healing-by-mac-talla-nan-creag/<p>Must have missed this track (from the LP The Sorrow of Derdriu) on previous listens. A Bladerunner-esque beauty!</p>
<iframe title="Time’s Healing, by Mac-Talla Nan Creag" width="100%" height="120" style="border: 0; width: 100%; height: 120px;" src="https://bandcamp.com/EmbeddedPlayer/album=1285742574/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/track=1120665509/transparent=true/" seamless=""><a href="http://firecrackerrecordings.bandcamp.com/album/firec027lp-the-sorrow-of-derdriu">FIREC027LP The Sorrow Of Derdriu by Mac-Talla Nan Creag</a></iframe>
From dynamic to static2019-08-11T10:53:00Zhttps://fuzzylogic.me/posts/from-dynamic-to-static/<p>“I’ll just make a few small tweaks to my website…” said I. Cut to three sleep-deprived days later and I’ve rebuilt it, SSG/JAMstack-stylee with Eleventy and Netlify and entirely re-coded the front-end. Silly, but so far so good, and it’s greasy fast!</p>
<p>So yes, I’ve just updated my website from being a dynamic, LAMP-stack affair which used Perch CMS and was hosted on Linode to being statically-generated using Eleventy and hosted on Netlify.</p>
<p>It mostly went smoothly. And the environmental and continuous deployment boilerplate that Netlify provide are fantastic, and will be a real time-saver over my current “set up and maintain a Linode server” approach.</p>
<p>In terms of challenges and troubleshooting, I did have to find a solution to the issue of FOUT on repeat visits. It seems this was happening as a result of <a href="https://stackoverflow.com/questions/52308658/netlify-headers-cache-control-for-static-assets">Netlify’s interesting approach to asset caching</a> which works well for most requirements but wasn’t so great for self-hosted webfonts. My solution was to add specific headers for <code>.woff</code> and <code>.woff2</code> files in my application’s Netlify config file.</p>
Resources for special typographic characters2019-08-09T10:58:00Zhttps://fuzzylogic.me/posts/resources-for-special-typographic-characters/<p>A collection of resources for finding that curly quote or em dash character quickly.</p>
<p><a href="http://smartquotesforsmartpeople.com/">Smart quotes for smart people</a></p>
<p><a href="https://www.toptal.com/designers/htmlarrows/punctuation/">Toptal HTML Symbols, Entities and Character reference</a></p>
Saying bye-bye to autoprefixer2019-08-08T12:50:04Zhttps://fuzzylogic.me/posts/saying-bye-bye-to-autoprefixer/<p>For a while now I’ve been using <a href="https://www.npmjs.com/package/gulp-autoprefixer">gulp-autoprefixer</a> as part of my front-end build system. However, I’ve just removed it from my boilerplate. Here’s why.</p>
<p>The npm module <code>gulp-autoprefixer</code> takes your standard CSS then automatically parses the rules and generates any necessary vendor-prefixed versions, such as <code>::-webkit-input-placeholder</code> to patch support for <code>::placeholder</code> in older Webkit browsers.</p>
<p>I’ve often felt it excessive—like using a hammer to crack a nut. And I’ve wondered if it might be doing more harm than good, by leading me to believe I have a magical sticking plaster for non-supporting browsers when actually (especially in the case of IE) the specific way in which a browser lacks support might be more nuanced. Furthermore I’ve never liked the noise generated by all those extra rules in my CSS output, especially when using the inspector to debug what would otherwise be just a few lines of CSS.</p>
<p>But I always felt it was a necessary evil.</p>
<p>However, I’ve just removed <code>gulp-autoprefixer</code> from my boilerplate. Why? Because:</p>
<ol>
<li>Browsers are no longer shipping any new CSS with prefixes, and as at 2019, they haven’t been for years;</li>
<li>With the browsers that <em>do</em> require prefixed CSS now old and in the minority, it feels like progressive enhancement rather than “kitchen sink” autoprefixing should take care of them. (Those browsers might not get the enhanced experience but what they’ll get will be fine.)</li>
</ol>
<p><a href="https://twitter.com/jensimmons/status/1067833878025564163">Jen Simmons’ tweet on this topic</a> was the push I needed.</p>
<p>So I’ve removed one layer of complexity from my set-up, and so far nothing has exploded. Let’s see how it goes.</p>
Cookie Consent by Osano2019-08-07T13:51:02Zhttps://fuzzylogic.me/posts/cookie-consent-by-osano-the-most-popular-solution-to-the-eu-cookie-law/<p>The most popular drop-in solution to the EU Cookie Law requirements.</p>
<p>Over the last year I’ve been successfully using Cookie Consent by Osano on a number of commercial websites. Essentially this is a banner which appears at the bottom (or top) of your website and asks the visitor to explicitly give (or decline to give) consent for the cookies your website uses. It’s a great free resource which handles the requisite GDPR requirements (and more) and offers a number of customisation options.</p>
<p>it’s very simple to include and use – you just step through their WYSIWYG generator, include the generated JavaScript-based settings in your site, and point to their CSS and JavaScript libraries. I like <a href="https://csswizardry.com/2019/05/self-host-your-static-assets/">self-hosting my own static assets</a> so I integrate the libraries into my code rather than linking to their externally hosted files, but that’s just my personal preference.</p>
<h2 id="why-do-we-need-this%3F" tabindex="-1">Why do we need this? <a class="direct-link" href="https://fuzzylogic.me/posts/cookie-consent-by-osano-the-most-popular-solution-to-the-eu-cookie-law/#why-do-we-need-this%3F" aria-hidden="true">#</a></h2>
<p>It’s because In 2018, the European Union’s General Data Protection Regulation (GDPR) went into effect, establishing a number of principles governing the collection of personal information. Any company or individual that processes personal information of European Union citizens must comply with the GDPR, regardless of where data is stored or processed.</p>
<p>Cookies often collect information about their users that is not specifically identified with one individual, but if that information, combined with other data, can be used to identify an individual, it becomes “personal information” for the purposes of the GDPR and must be treated as such.</p>
<p>The clearest and most effective way to notify a user in advance of the collection of information using cookies is to provide a web banner or “pop-up” cookie notice that appears automatically when the home page is accessed for the first time, and requires some affirmative action.</p>
Real Favicon Generator2019-08-05T10:53:00Zhttps://fuzzylogic.me/posts/real-favicon-generator/<p>Knowing how best to serve, size and format favicons and other icons for the many different device types and operating systems can be a minefield. My current best practice approach is to create a 260px × 260px (or larger) source icon then upload it to <a href="https://realfavicongenerator.net/">Real Favicon Generator</a>.</p>
<p>This is the tool <a href="https://css-tricks.com/favicon-quiz">recommended by CSS-Tricks</a> and it takes care of most of the pain by not only generating all the formats and sizes you need but also providing some code to put in your <code><head></code> and <code>manifest.webmanifest</code> file.</p>
Everybody in the place2019-08-03T13:41:00Zhttps://fuzzylogic.me/posts/everybody-in-the-place/<p>Enjoyed this acid house history lesson from Jeremy Deller – especially some of the footage from the early Manchester scene which I hadn’t seen before.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1625998629/p07hsqny_wzkfgu.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1625998629/p07hsqny_wzkfgu.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1625998629/p07hsqny_wzkfgu.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1200/v1625998629/p07hsqny_wzkfgu.jpg 1200w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1625998629/p07hsqny_wzkfgu.jpg" width="160" height="90" alt="Nightclub graphic from the documentary “Everybody in the place”" loading="lazy" decoding="async" />
<figcaption>Nightclub shot from “Everybody in the place”</figcaption>
</figure>
Bookshelf - daverupert.com2019-08-01T09:29:45Zhttps://fuzzylogic.me/posts/2019-08-01-bookshelf-daverupertcom/<p>Just saw this – <a href="https://daverupert.com/bookshelf/">https://daverupert.com/bookshelf/</a> – and now I really need to up my book-logging game!</p>
<p>(via <a href="https://twitter.com/davatron5000">@davatron5000</a>)</p>
A Visit from the Goon Squad, by Jennifer Egan2019-08-01T00:00:00Zhttps://fuzzylogic.me/posts/a-visit-from-the-goon-squad-by-jennifer-egan/<p>I really enjoyed this book, recommended to me by <a href="https://twitter.com/Gilco80">Gillian</a> and <a href="https://twitter.com/mrtomchurchill">Tom</a>.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1571418924/IMG_2430_pgzfhc.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571418924/IMG_2430_pgzfhc.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1571418924/IMG_2430_pgzfhc.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1571418924/IMG_2430_pgzfhc.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1571418924/IMG_2430_pgzfhc.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1571418924/IMG_2430_pgzfhc.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1571418924/IMG_2430_pgzfhc.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1571418924/IMG_2430_pgzfhc.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1571418924/IMG_2430_pgzfhc.jpg" width="320" height="240" alt="A photo of the book “A Visit from the Goon Squad” by Jennifer Egan" loading="lazy" decoding="async" />
<figcaption>A Visit from the Goon Squad</figcaption>
</figure>
<p>It’s set primarily in New York and tells the stories of a cast of interconnected characters (and their children) linked by the music industry, taking in themes of youth and ageing, loss and regret, insecurity, celebrity and image.</p>
<p>There are some great moments including Rob’s story which called to mind <a href="https://www.imdb.com/title/tt0134119/">The Talented Mr Ripley</a>; Jules’s unpublished and unhinged newspaper article on the celebrity interview which sent him to jail; and the dystopian final chapter which suggests where the internet and the world of influencers might be headed if we don’t watch out.</p>
<p>I loved author Jennifer Egan’s storytelling, dark humour and also the way she switched her writing style dependent on the era or character.</p>
<p>Recommended!</p>
Intrinsically Responsive CSS Grid with minmax and min2019-07-31T18:14:00Zhttps://fuzzylogic.me/posts/intrinsically-responsive-css-grid-with-minmax-and-min/<p>Evan Minto notes that flexible grids created with CSS Grid’s <code>repeat</code>, <code>auto-fill</code>, and <code>minmax</code> are only intrinsically responsive (responsive to their <em>container</em> rather than the viewport) up to a point, because when the container width is narrower than the minimum width specified in <code>minmax</code> the grid children overflow.</p>
<p>Applying media queries to the grid is not a satisfactory solution because they relate to the the viewport (hence why <a href="https://every-layout.dev/">Every Layout</a> often prefer Flexbox to CSS Grid because it allows them to achieve intrinsic responsiveness).</p>
<p>However we’ll soon be able to suggest grid item width as a percentage of the parent container, avoiding the overflow problem. The new “CSS Math functions” to help us achieve this are <code>min()</code>, <code>max()</code> and <code>clamp()</code>. At the time of writing, these are <a href="https://caniuse.com/#feat=css-math-functions">only supported in Safari</a> however Chrome support is in the pipeline.</p>
GOV.UK Design System2019-07-25T15:02:00Zhttps://fuzzylogic.me/posts/gov-uk-design-system/<blockquote>
<p>Use this design system to make your service consistent with <a href="http://gov.uk/">GOV.UK</a>. Learn from the research and experience of other service teams and avoid repeating work that’s already been done.</p>
</blockquote>
Intro to CSS 3D transforms2019-07-23T12:25:00Zhttps://fuzzylogic.me/posts/intro-to-css-3d-transforms/<p>Excellent tutorials by David DeSandro. I’ve already used the <a href="https://3dtransforms.desandro.com/card-flip">card flip</a> and it worked really well.</p>
Flickity – touch, responsive, flickable carousels2019-07-23T12:17:00Zhttps://fuzzylogic.me/posts/flickity-touch-responsive-flickable-carousels/<p>This slider/carousel certainly looks nice, and I like author David DeSandro’s work, having taken inspiration from his <a href="https://3dtransforms.desandro.com/card-flip">3d Card Flip tutorial</a> for a recent project. I’d just like to dig into it a little further to see how it fares in terms of accessibility before using it in the wild.</p>
The Guardian Digital Design Style Guide2019-07-22T14:40:58Zhttps://fuzzylogic.me/posts/the-guardian-digital-design-style-guide/<p>This is a nice whistle-stop tour of the the Guardian’s current digital design system. Apart from looking great, some of the terminology is interesting (fronts, kickers and thrashers) and I like the way they have different Card types for different types of article, “each having its own flavour and tone”.</p>
Katherine Kato’s personal website2019-07-21T20:17:31Zhttps://fuzzylogic.me/posts/katherine-kato-s-personal-website/<p>Some simple but inspiring work here from Seattle-based web developer Katherine Kato. I really like the use of space, the typography, the colour palette and the use of CSS grid for layout.</p>
8 Days: To the Moon and Back (on BBC iPlayer)2019-07-20T15:12:27Zhttps://fuzzylogic.me/posts/2019-12-26-8-days-to-the-moon-and-back-on-bbc-iplayer/<blockquote>
<p>Previously classified cockpit audio, recorded by the astronauts themselves, gives a unique insight into their fears and excitement as they undertake the mission. And dramatic reconstruction brings those recordings to life, recreating the crucial scenes that were never filmed - the exhilarating launch, the first sight of the moon, the dramatic touchdown and nail-biting journey home.</p>
</blockquote>
<p>Original archive footage from the Apollo programme is combined with newly shot film and cinematic CGI to create the ultimate documentary of the ultimate human adventure.</p>
<p>This can only be described as a stunning audiovisual experience and a fantastic tribute on the 50-year anniversary of the Apollo 11 mission!</p>
Rutger Hauer R.I.P.2019-07-20T12:17:42Zhttps://fuzzylogic.me/posts/rutger-hauer-r.i.p/<p>Farewell Rutger Hauer; famous for his roles in Bladerunner, The Hitcher and the Guinness ads. And those were undoubtedly great, however… in 1989, for 13-year-old me at the height of my ninja obsession, he was <em>the man</em> as Nick Parker in Blind Fury, a film about a blind war veteran who is implausibly handy with a samurai sword and goes on to defeat Sho Kuzugi in the final showdown. It was daft, but I loved it.</p>
<div class="l-frame"><iframe title="Blind Fury movie trailer" width="560" height="315" src="https://www.youtube-nocookie.com/embed/N-bt0O9jcH0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
Project Apollo Archive (on Flickr)2019-07-16T12:29:14Zhttps://fuzzylogic.me/posts/project-apollo-archive-on-flickr/<p>Over 8,400 NASA Apollo moon mission photos, online, in high-resolution.</p>
CSS pointer-events to the rescue2019-07-13T08:48:00Zhttps://fuzzylogic.me/posts/css-pointer-events-to-the-rescue/<p>Sometimes, for reasons unknown, we find that clicking or tapping an element just isn’t working. Here’s a CSS-based approach that might help.</p>
<p>I’ve recently encountered the scenario – usually in reasonably complex user interfaces – where I have an anchor (or ocassionally, a button) on which clicks or taps just aren’t working, i.e. they don’t trigger the event I was expecting.</p>
<p>On further investigation I found that this is often due to having an absolutely positioned element which is to some extent overlaying (or otherwise interfering with) our target clickable element. Alternatively, it may be because we needed a child/nested element inside our anchor or button and it is this element that the browser perceives as being the clicked or tapped element.</p>
<p>I’ve found that setting <code>.my-elem { pointer-events: none; }</code> on the obscuring element resolves the problem and get you back on track.</p>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events">Here’s some more information on CSS pointer events</a>.</p>
Note 2019-07-06T11:00:00: Finished Harry’s Kebabs on ‘oliday2019-07-06T11:00:00Zhttps://fuzzylogic.me/posts/1562410800-harrys-kebabs/<p>I’ll tell you wot – that woz a propa’ poolside page-turner and no mistake. Nice work <a href="https://www.facebook.com/harryskebabsbook/">Russ Forman</a>.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1577820760/7613D088-D977-4551-ABAF-CC43637E44E4_znpbi4.jpg" width="320" height="240" alt="Laurence with a copy of “Harry’s Kebabs” by Russ Forman" loading="lazy" decoding="async" />
<figcaption>Me with my copy of “Harry’s Kebabs” by DJ Dribbler</figcaption>
</figure>
Polypane: The browser for responsive web development and design2019-07-04T11:23:16Zhttps://fuzzylogic.me/posts/polypane-the-browser-for-responsive-web-development-and-design/<p>Polypane is a browser built specifically for developing responsive websites. It can present typical device resolutions side-by-side (for example iphone SE next to iphone 7 next to iPad) but also has some nice features such as automatically creating views based on your stylesheet’s media query breakpoints.</p>
<p>It’s a subscription service and at the moment I’m happy using a combination of Firefox Nightly and Chrome so I think I’ll wait this one out for the time being. But I’ll be keeping my eye on it!</p>
Using aria-current is a win-win situation2019-07-03T13:30:04Zhttps://fuzzylogic.me/posts/using-aria-current-is-a-win-win-situation/<p>The HTML attribute <code>aria-current</code> allows us to indicate the currently active element in a sequence. It’s not only great for accessibility but also doubles as a hook to style that element individually.</p>
<p>By using <code>[aria-current]</code> as your CSS selector (rather than a <code>.current</code> class) this also neatly binds and syncs the way you cater to the visual experience and the screen reader experience, reducing the ability for the latter to be forgotten about.</p>
<p><a href="https://tink.uk/using-the-aria-current-attribute/">As Léonie Watson explains</a>, according to <a href="https://www.w3.org/TR/wai-aria-1.1/#aria-current">WAI-ARIA 1.1</a> there are a number of useful values that the <code>aria-current</code> attribute can take:</p>
<ul>
<li><code>page</code> to indicate the current page within a navigation menu or pagination section;</li>
<li><code>step</code> for the current step in a step-based process;</li>
<li><code>date</code> for the current date.</li>
<li><code>time</code> for the current time.</li>
</ul>
<p>I’ve been using the <code>aria-current="page"</code> technique on a couple of navigation menus recently and it’s working well.</p>
<p>Also: my thanks go to Ethan Marcotte, David Kennedy and <a href="https://twitter.com/LittleKope/">Lindsey</a>. Ethan recently suggested that <a href="https://ethanmarcotte.com/wrote/the-web-we-broke/">the industry should try harder regarding accessibility</a> and recommended subscribing to David Kennedy’s <a href="https://a11yweekly.com/">a11y Weekly newsletter</a>. I duly subscribed (it’s great!) and one of the issues linked to Lindsey’s article <a href="https://www.a11ywithlindsey.com/blog/introduction-aria-states/">An Introduction to ARIA states</a> in which I learned about <code>aria-current</code>.</p>
Solar Design System by Bulb2019-06-25T15:02:00Zhttps://fuzzylogic.me/posts/bulb-solar-design-system/<blockquote>
<p>It’s a collection of shared patterns and practices that allow our team to build quality user interfaces consistently and quickly.</p>
</blockquote>
My Sketch Cheatsheet2019-06-23T16:58:08Zhttps://fuzzylogic.me/posts/sketch-tips-and-tricks/<p>Here’s a list of useful (Mac-based) Sketch tips for my reference and yours.</p>
<h2 id="commands-quick-reference" tabindex="-1">Commands Quick Reference <a class="direct-link" href="https://fuzzylogic.me/posts/sketch-tips-and-tricks/#commands-quick-reference" aria-hidden="true">#</a></h2>
<table>
<thead>
<tr>
<th style="text-align:left">Task</th>
<th style="text-align:left">Command</th>
<th style="text-align:left">Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Add an artboard</td>
<td style="text-align:left"><kbd>a</kbd></td>
<td style="text-align:left">or Insert > Artboard</td>
</tr>
<tr>
<td style="text-align:left">Insert text element</td>
<td style="text-align:left"><kbd>t</kbd></td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Insert rectangle</td>
<td style="text-align:left"><kbd>r</kbd></td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Centre screen on current element</td>
<td style="text-align:left"><kbd>Command-2</kbd></td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Zoom out, centred on artboard</td>
<td style="text-align:left"><kbd>Escape</kbd> then <kbd>Command-2</kbd> then <kbd>Command-0</kbd></td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Zoom in on current element to 100% of screen size</td>
<td style="text-align:left"><kbd>Command-0</kbd></td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Show and hide rulers</td>
<td style="text-align:left"><kbd>Control-R</kbd></td>
<td style="text-align:left">or use “View” dropdown at top-right</td>
</tr>
<tr>
<td style="text-align:left">Duplicate element</td>
<td style="text-align:left">Hold <kbd>Option</kbd> while drag from original. Hold <kbd>Shift</kbd> for alignment</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Check distances</td>
<td style="text-align:left">Select one layer then hold down <kbd>Option</kbd> then hover over the other layer</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Adjust text size by decimal increments</td>
<td style="text-align:left">Hold <kbd>Option</kbd> while adjust size via right-hand panel</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Resize an image</td>
<td style="text-align:left">Drag from sides or corners to your target size, holding shift to maintain aspect ratio</td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">Crop an image</td>
<td style="text-align:left">Select then double-click image to go into image mode. Draw the rectangular shape you want to crop over the image, then select “crop” from top-right</td>
<td style="text-align:left"></td>
</tr>
</tbody>
</table>
<h2 id="key-concepts" tabindex="-1">Key Concepts <a class="direct-link" href="https://fuzzylogic.me/posts/sketch-tips-and-tricks/#key-concepts" aria-hidden="true">#</a></h2>
<h3 id="starting-with-an-artboard" tabindex="-1">Starting with an Artboard <a class="direct-link" href="https://fuzzylogic.me/posts/sketch-tips-and-tricks/#starting-with-an-artboard" aria-hidden="true">#</a></h3>
<p>The initial <em>canvas</em> is infinite so we need a fixed frame (representing a device screen) on which to work.</p>
<p>Steps:</p>
<ol>
<li>Add an artboard.</li>
<li>From the top-right choose one of the options (presets) e.g. Responsive Web > Desktop (1024 × 1024) or select “Custom”.</li>
<li>Rename your layer to something appropriate for the overall task, e.g. News Article.</li>
</ol>
<h3 id="creating-something" tabindex="-1">Creating something <a class="direct-link" href="https://fuzzylogic.me/posts/sketch-tips-and-tricks/#creating-something" aria-hidden="true">#</a></h3>
<ul>
<li>Show rulers.</li>
<li>Add markers by clicking in the horizontal ruler at the top to provide gutters. Create them at, say, 32px from each side.</li>
<li>Add a text element, with lateral boundaries snapped to your markers. If it’s for body text, type my <kbd>lorem0</kbd> shortcut <sup>1</sup>.</li>
</ul>
<h2 id="appendix" tabindex="-1">Appendix <a class="direct-link" href="https://fuzzylogic.me/posts/sketch-tips-and-tricks/#appendix" aria-hidden="true">#</a></h2>
<ol>
<li>the <code>lorem0</code> shortcut accesses “lorem ipsum” text which I previously saved into Mac > Preferences > Keyboard > Text.</li>
</ol>
Bram Stein’s personal website2019-06-22T20:37:43Zhttps://fuzzylogic.me/posts/bram-stein-s-personal-website/<p>Bram Stein, a software architect at Adobe, <a href="https://abookapart.com/products/webfont-handbook">wrote the book on Webfonts</a>, so it’s no surprise that his own website showcases some pretty beautiful typography.</p>
<p>Type is set in Expo Serif Pro, Expo Sans Pro and Source Code Pro.</p>
webmention.app: automate your outgoing webmentions2019-06-22T07:49:26Zhttps://fuzzylogic.me/posts/webmention.app-automate-your-outgoing-webmentions/<p><a href="https://webmention.app/">webmention.app</a> is a great new project by <a href="https://remysharp.com/">Remy Sharp</a>. He created it because he noticed that while adding webmentions to your site is relatively straightforward, sending outgoing webmentions is less so.</p>
<p>At the moment my personal website is Perch-based and I have webmentions enabled, so let’s see what happens when I <a class="u-in-reply-to" href="https://remysharp.com/2019/06/18/send-outgoing-webmentions">link to Remy’s explainer article</a>.</p>
Unsplash – Beautiful free images and pictures2019-06-12T16:58:08Zhttps://fuzzylogic.me/posts/unsplash-beautiful-free-images-and-pictures/<blockquote>
<p>The internet’s source of freely usable images. Powered by creators everywhere.</p>
</blockquote>
<p>I’ve seen a couple of other developers use <a href="https://unsplash.com/">photos from Unsplash</a> in their demos, and it just came in handy for me recently when needing some free food photography for a website.</p>
<p>It’s choc-full of lovely – and free – high-res photographs, offers a simple URL-based pattern for embedding, and has an API so will be really useful.</p>
Guest reggae and dub mix on Vic’s Sunday Soundclash2019-06-11T19:18:08Zhttps://fuzzylogic.me/posts/guest-reggae-and-dub-mix-on-vic-s-sunday-soundclash/<p>A couple of weeks ago I was kindly asked to provide a guest DJ mix for the Vic’s Sunday Soundclash show on Radio Magnetic.</p>
<p>You can <a href="https://www.mixcloud.com/RadioMagnetic/vics-sunday-soundclash-08-w-laurence-hughes/">listen to the show</a> on demand.</p>
<p>Here’s the tracklist for my mix:</p>
<ul>
<li>Black Uhuru - Chill Out</li>
<li>Jackie Mittoo - Oboe</li>
<li>Joe Higgs - There’s A Reward For Me</li>
<li>UBrown - Me Chat You Rock</li>
<li>Riddim Tuffa ft OBF - Food Dub Ninja</li>
<li>Mosca - Prento</li>
<li>The Royals - My Sweat Turns To Blood</li>
<li>Tatham/Ranks/Lord/Mensah - Private Life</li>
<li>Freddie McGregor w/ Sound Dimension - Africa Here I Come</li>
<li>Carlton Patterson w/King Tubby - King At The Controls</li>
<li>King Tubby - Herbal Dub</li>
<li>Carlton Coffie - Chant Away</li>
<li>Fabian - Prophecy</li>
<li>Prophecy Dub</li>
</ul>
<p>I really enjoyed the chance to pull together reggae, dub and dancefloor favourites (old and new) for the mix. Cheers for the invite, Vicky!</p>
<p>You can catch Vic’s Sunday Soundclash on the first Sunday of each month at 2pm on <a href="https://www.radiomagnetic.com/">Radio Magnetic</a>.</p>
Codrops CSS Reference2019-05-20T08:08:12Zhttps://fuzzylogic.me/posts/codrops-css-reference/<p>Here’s a comprehensive and great-looking CSS reference featuring lots of examples.</p>
<p>While these days I normally reach for <a href="https://developer.mozilla.org/en-US/docs/Web/CSS">MDN Web Docs</a> to keep me right on any given CSS feature, I’ve been thinking that with the recent explosion of new CSS features and syntax it’d be great to do a refresher course by working my way through a structured list of features—just like I did with Eric Meyer’s <a href="https://meyerweb.com/eric/books/css-tdg/">CSS: The Definitive Guide</a> back in the day—and Codrops’ reference could be the perfect place.</p>
<p>In a similar vein, the <a href="https://css-tricks.com/almanac/">CSS-Tricks Almanac</a> looks good and <a href="https://cssreference.io/">cssreference.io</a> is worth bookmarking, too.</p>
Making a slider with just HTML and CSS (on CSS-Tricks)2019-05-08T20:15:54Zhttps://fuzzylogic.me/posts/making-a-slider-with-just-html-and-css-on-css-tricks/<p>Sliders (or carousels) are a fairly common practical requirement in web projects. Here, Chris Coyier shows us how far we can get in 2019 with HTML and CSS alone.</p>
'Easy Sass' extension for Visual Studio Code (from wojciechsura on GitHub)2019-04-24T19:15:09Zhttps://fuzzylogic.me/posts/2021-01-24-easy-sass-extension-for-visual-studio-code-from-wojciechsura-on-github/<blockquote>
<p>Automatically compiles SASS/SCSS files to .css and .min.css upon saving. You may also quickly compile all SCSS/SASS files in your project.</p>
</blockquote>
<p>As I consider different ways in which to simplify my development stack and avoid excess tooling (<a href="https://css-irl.info/building-a-dependency-free-site/">much like Michelle Barker did</a>), this might be worth a look.</p>
<p>(via <a href="https://twitter.com/MicheBarks">@MicheBarks</a>)</p>
Fading out siblings on hover in CSS (by Trys Mudford)2019-04-22T13:03:36Zhttps://fuzzylogic.me/posts/fading-out-siblings-on-hover-in-css-by-trys-mudford/<p>Here’s a nice CSS-only hover technique from Trys Mudford incorporating scale transforms, opacity transitions and mouse pointer events.</p>
Don’t set cursor: pointer on buttons2019-04-08T14:55:29Zhttps://fuzzylogic.me/posts/don-t-set-cursor-pointer-on-buttons/<p>For many years I’ve been applying <code>cursor: pointer</code> to buttons because it felt right and would improve the user experience.</p>
<p><a href="https://github.com/necolas/normalize.css/issues/371#issuecomment-60072171">As Florens Verschelde explains</a>, that approach is probably best avoided. I was going against the W3C’s spec that <code>cursor: pointer</code> should be reserved for links, and was adding to the usability <em>antipattern</em> where “everything resembles a link”.</p>
<p>I’ll leave button cursor behaviour as it is from here on in.</p>
Using CSS display: contents to snap grandchild elements to a grid2019-04-05T11:14:27Zhttps://fuzzylogic.me/posts/using-css-display-contents-to-snap-grandchild-elements-to-a-grid/<p>I realised last night while watching a presentation by Lea Verou that I could streamline my CSS Grid layouts.</p>
<p>I’d been creating an overall page grid by setting <code>body { display: grid; }</code> then some grid areas but realised that this only worked for direct children and didn’t help with aligning more deeply nested elements to that outer grid.</p>
<p>For example in the case of the main <code>header</code> if I wanted its child logo, <code>nav</code> and search elements to snap to the <code>body</code> grid then I found myself having to duplicate the <code>display: grid</code> and <code>grid-template-areas</code> again on the <code>header</code>.</p>
<p>It didn’t feel very <abbr title="Don’t Repeat Yourself">DRY</abbr> but my understanding was that while we await <code>subgrid</code>, it was a necessary evil.</p>
<p>What I should have been using is <code>display: contents</code>.</p>
<p>If you set your <code>header</code> to <code>display: contents</code> then the parent (<code>body</code>) grid layout will apply to the header’s contents (logo, <code>nav</code>, etc) as if the <code>header</code> element (the “real” direct child of the grid) wasn’t there. This gives us good semantics without the need to redefine the grid on the <code>header</code>.</p>
<p><a href="https://codepen.io/fuzzylogicx/pen/WWwPrm">Here’s a codepen to illustrate.</a></p>
<p>I was aware of the existence of <code>display: contents</code> but somehow it hadn’t sunk in because I’d only read about it in the abstract. <a href="https://www.youtube.com/watch?v=8BXQ3zCihYM&t=3536s">Lea Verou’s explanation</a> made all the difference. Cheers, Lea!</p>
<h2 id="update-4%2F5%2F2019" tabindex="-1">Update 4/5/2019 <a class="direct-link" href="https://fuzzylogic.me/posts/using-css-display-contents-to-snap-grandchild-elements-to-a-grid/#update-4%2F5%2F2019" aria-hidden="true">#</a></h2>
<p>Frustratingly, I’ve learned that although we <em>can</em> apply this technique, we shouldn’t… or at least not for a while.</p>
<p>Due to a bug in all supporting browsers the property will currently also remove the element (<code>header</code> in our case) from the accessibility tree meaning that its semantics will be lost.</p>
<p>For reference, see:</p>
<ul>
<li><a href="https://github.com/w3c/csswg-drafts/issues/3040">https://github.com/w3c/csswg-drafts/issues/3040</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/display">MDN’s <code>display</code> property docs</a></li>
</ul>
<h2 id="update-11%2F4%2F2021" tabindex="-1">Update 11/4/2021 <a class="direct-link" href="https://fuzzylogic.me/posts/using-css-display-contents-to-snap-grandchild-elements-to-a-grid/#update-11%2F4%2F2021" aria-hidden="true">#</a></h2>
<p>Thanks to Rachel Andrew for the heads-up that <a href="https://rachelandrew.co.uk/archives/2021/03/11/good-news-about-display-contents-and-chrome/">this issue is now fixed in both Firefox and Chrome</a>.</p>
<p>We’re now just waiting for Edge and Safari to roll out fixes before we can regard this as a safe option.</p>
The Art of DJing: Jeff Mills (on Resident Advisor)2019-04-04T13:13:23Zhttps://fuzzylogic.me/posts/the-art-of-djing-jeff-mills-on-resident-advisor/<p>Fair play, Jeff – once this interview gets going it’s pretty damn good.</p>
<p>Amongst other ground, it covers:</p>
<ul>
<li>The technique of “Subtraction”;</li>
<li>the last quarter of records being the best;</li>
<li>the bar for electronic music being set too low;</li>
<li>the complexity of the art form of DJing; and</li>
<li>thinking about other things while DJing in front of 2000 people…</li>
</ul>
<p>Plenty of good bits to chew over!</p>
How to control SVG icon size and colour in context2019-04-01T13:25:00Zhttps://fuzzylogic.me/posts/how-to-control-svg-icon-size-and-colour-in-context/<p>A while back I read <a href="https://twitter.com/andybelldesign/status/1098915626050117633">a great SVG icon tip from Andy Bell</a> which I’d been meaning to try and finally did so today. Andy recommended that for icons with text labels we set the <code>width</code> and <code>height</code> of the icons to <code>1em</code> since that will size them proportionately to the adjacent text and additionally lets us use <code>font-size</code> to make any further sizing tweaks.</p>
<p>As <a href="https://fuzzylogic.me/thoughts/grey-scales-something-fishy-with-svg">previously mentioned</a>, I’ve recently been working on my SVG skills.</p>
<p>Andy Bell’s SVG icon-sizing technique is really clever and feels like it adds lots of flexibility and future-friendliness so I was keen to try it out.</p>
<p>Here’s how it works.</p>
<p>The HTML:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>call-to-action<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>I’m a link<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <br /> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cta-icon<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1em<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1em<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">viewBox</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0 0 14 13<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2000/svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>path</span> <br /> <span class="token attr-name">fill</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>currentColor<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">fill-rule</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>evenodd<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">d</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>M3.49.868l7.683 3.634a2 2 0 0 1 .052 3.59l-7.682 3.913a2 2 0 0 1-2.908-1.782V2.676A2 2 0 0 1 3.49.868z<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>path</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>call-to-action call-to-action-alt<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>I’m a large link<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <br /> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cta-icon<span class="token punctuation">"</span></span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1em<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1em<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">viewBox</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0 0 14 13<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2000/svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>path</span> <br /> <span class="token attr-name">fill</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>currentColor<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">fill-rule</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>evenodd<span class="token punctuation">"</span></span> <br /> <span class="token attr-name">d</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>M3.49.868l7.683 3.634a2 2 0 0 1 .052 3.59l-7.682 3.913a2 2 0 0 1-2.908-1.782V2.676A2 2 0 0 1 3.49.868z<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>path</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
<p>The CSS:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span> <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>183<span class="token punctuation">,</span> 65<span class="token punctuation">,</span> 14<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><br /><span class="token selector">a:hover</span> <span class="token punctuation">{</span> <span class="token property">color</span><span class="token punctuation">:</span> #6A2000<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><br /><span class="token selector">.call-to-action</span> <span class="token punctuation">{</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> inline-flex<span class="token punctuation">;</span><br /> <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /> <span class="token property">font-weight</span><span class="token punctuation">:</span> bold<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.call-to-action-alt</span> <span class="token punctuation">{</span><br /> <span class="token property">font-size</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span> <br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.cta-icon</span> <span class="token punctuation">{</span><br /> <span class="token property">margin-left</span><span class="token punctuation">:</span> .5em<span class="token punctuation">;</span><br /> <span class="token property">font-size</span><span class="token punctuation">:</span> .8em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Here are my key takeaways:</p>
<ul>
<li>By applying <code>width</code> and <code>height</code> of <code>1em</code> to our icon it is predictably sized by default.</li>
<li>It can now have its size further tweaked in CSS using <code>font-size</code>, for example with ems (where <code>1em</code> = the font-size of the parent anchor element).</li>
<li>This technique requires the <code>viewbox</code> attribute being present on the svg.</li>
<li>Apply the width and height =1em as inline attributes on the svg. We <em>could</em> apply them using CSS, however the inline approach avoids potentially massive icons showing in cases where CSS doesn’t load.</li>
<li>To get the colour matching, apply <code>fill="currentColor"</code> as an inline attribute on the svg’s path.</li>
<li>Now, when you apply a hover colour to the anchor in CSS, the icon will just pick that up. Nice!</li>
<li>Applying <code>inline-flex</code> to the anchor makes the vertical-alignment of text and icon easier.</li>
<li>Apply <code>aria-hidden</code> to the icon because it’s mainly decorative so we don’t want it read out by screen readers.</li>
</ul>
<p><a href="https://codepen.io/fuzzylogicx/pen/QPwjyZ">And here’s a demo I created to test-drive the technique</a>.</p>
$$ in the DevTools Console2019-03-28T00:31:37Zhttps://fuzzylogic.me/posts/in-the-devtools-console/<p>I learned something new today when developing in the Firefox Dev Tools console (although this applies to Chrome too)—something which was really useful and which I thought I’d share.</p>
<p>Basically, type <code>$$('selector')</code> into the console (replacing <em>selector</em> as desired) and it’ll give you back all matching elements on the page.</p>
<p>So for example, <code>$$('script')</code> or <code>$$('li')</code>.</p>
<p>Similarly you can select a single element by instead using one dollar sign (<code>$</code>).</p>
<p>These seem to be console shortcuts for <code>document.querySelector()</code> (in the case of <code>$</code>) and <code>document.querySelectorAll()</code> (in the case of <code>$$</code>).</p>
<p>The other really cool thing is that the resultant <code>nodeList</code> is returned as an array, so you could do e.g. <code>$$('li').forEach(…)</code> or similar.</p>
<p>via <a href="https://twitter.com/rem">@rem</a> (Remy Sharp)</p>
Check localhost development on your iPhone2019-03-26T21:10:57Zhttps://fuzzylogic.me/posts/check-localhost-development-on-your-iphone/<p>Here’s how to check the application you’re running locally on your MacBook on your iPhone.</p>
<p>It’s pretty much a case of connecting your iPhone to your MacBook by USB, tweaking some settings, then browsing to the application via a given IP in iOS Safari.</p>
Stuffing the front end2019-03-25T16:58:29Zhttps://fuzzylogic.me/posts/stuffing-the-front-end/<p>Here’s Bridget Stewart, a developer from Ohio, with some thoroughly enjoyable “curmudgeonly” thoughts on why your website doesn’t necessarily need a Javascript framework.</p>
<p>With websites taking a median time of 5.8 seconds to show primary content (source: HTTPArchive) and Google warning us that 53% of mobile visits leave pages that take longer than three seconds to load, it’s hard to justify stuffing the front-end unnecessarily.</p>
<p>Bridget’s article also contains this quote which I love:</p>
<blockquote>
<p>First, solve the problem. Then, write the code.</p>
<footer>— John Johnson</footer>
</blockquote>
<p>Essentially, <code>don’t select the tooling first</code>—a <a href="https://fuzzylogic.me/thoughts/website-delivery-principles">principle I fully endorse</a>.</p>
Accessible modal dialogues in 20192019-03-09T00:00:00Zhttps://fuzzylogic.me/posts/accessible-modal-dialogues-in-2019/<p>I <a href="https://fuzzylogic.me/posts/meet-the-new-dialog-element/">previously noted</a> Keith J Grant’s article on the HTML <code>dialog</code> element which promised a native means of handling popups and modal dialogues. I’ve not yet used <code>dialog</code> in production, partly because of <a href="https://caniuse.com/#search=dialog">spotty browser support</a> (although there is a polyfill) but also partly because—for reasons I couldn’t quite put my finger on after reading the spec—it just didn’t feel like the finished article.</p>
<p>Fast forward to March 2019 and <a href="https://www.scottohara.me/blog/2019/03/05/open-dialog.html">Scott O’Hara has written an excellent piece</a> describing why it’s still not ready. There are a combination of factors: lack of browser support, reliance on JavaScript; and multiple accessibility issues.</p>
<p>The good news is: having dug deeper into Scott’s work I see that among the <a href="https://github.com/scottaohara/accessible_components">many accessible components</a> he has shared with the world is a <a href="https://github.com/scottaohara/accessible_modal_window">custom, accessible modal dialogue</a>. So next time the need arises, I think I’ll start there.</p>
<p>Thanks, <a href="https://twitter.com/scottohara">Scott</a>!</p>
Box Shadow around the full box2019-03-08T19:30:51Zhttps://fuzzylogic.me/posts/box-shadow-around-the-full-box/<p>Sometimes when coding a UI element you want a shadow around the <em>whole</em> box. However, most CSS box-shadow examples/tutorials tend to show <em>inset</em> box-shadows or ones that otherwise sit off to the side.</p>
<p>Here’s how to apply <code>box-shadow</code> to the whole box for a simple but nice effect.</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token selector">.box-with-shadow</span> <span class="token punctuation">{</span><br /> <span class="token property">box-shadow</span><span class="token punctuation">:</span> 0 0 4px #ccc<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>And here’s how it looks:</p>
<div style="box-shadow: 0 0 4px #ccc; margin: 2em; padding: 2em; display: grid; place-items: center;">Lorem ipsum</div>
Details and summary for no-JavaScript disclosure widgets2019-02-20T00:00:00Zhttps://fuzzylogic.me/posts/details-and-summary-for-no-javascript-disclosure-widgets/<p>The fairly-recently added <code><details></code> element is a great, native HTML way to toggle content visibility.</p>
<div class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="WNOJbKd" data-preview="true" data-user="fuzzylogicx" data-prefill="{"title":"Hiding: native disclosure using <details>","tags":["hide","hiding","html","details"],"scripts":[],"stylesheets":[]}">
<pre data-lang="html"><p>Lorem ipsum dolor sit amet.</p>
<p><details><br />
<summary>System Requirements</summary><br />
<p>Requires a computer running an operating system. The computer<br />
must have some memory and ideally some kind of long-term storage.</p><br />
</details></p>
<p><p class="end">Remember: built-in beats bolt-on, bigly!</p></p>
<p><!--<br />
<details> is great but there are a few gotchas:</p>
<ul>
<li>Not totally flexible design-wise</li>
<li>Unsuitable for accordions with multiple sibling elements unless you add some JS</li>
<li>Unsupported in IE 11 (but content is still available)<br />
--></li></ul></pre><pre data-lang="css">:root {
font-size: 110%;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
<p>}</p>
<p>input,<br />
button {<br />
font-size: inherit;<br />
}</p>
<p>.end {<br />
margin-top: 2rem;<br />
}<br />
</p></pre></div><p></p>
<script async="" src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
Certbot Troubleshooting2019-02-13T00:00:00Zhttps://fuzzylogic.me/posts/certbot-troubleshooting/<p>When taking the DIY approach to building a new server, Certbot is a great option for installing secure certificates. However, sometimes you can run into problems. Here, I review the main recurring issues I’ve encountered and how I fixed them.</p>
<p>When creating new servers for my projects I use <a href="https://certbot.eff.org/">Certbot</a> as a means of installing free Let’s Encrypt secure certificates.</p>
<p>It’s great to be able to get these certificates for free and the whole process is generally very straightforward. However, since working with Let’s Encrypt certificates over the last few years I’ve found that the same recurring questions tend to plague me.</p>
<p>This is a note to “future me” (and anyone else it might help) with answers to the questions I’ve pondered in the past.</p>
<h2 id="how-do-i-safely-upgrade-from-the-old-le-system-to-certbot%3F" tabindex="-1">How do I safely upgrade from the old LE system to Certbot? <a class="direct-link" href="https://fuzzylogic.me/posts/certbot-troubleshooting/#how-do-i-safely-upgrade-from-the-old-le-system-to-certbot%3F" aria-hidden="true">#</a></h2>
<p>For servers where you previously used the 2015/2016, pre-Certbot Let’s Encrypt system for installing SSL certs, you can just <a href="https://certbot.eff.org/">install Certbot</a> on top and it will <em>just work</em>. It will supersede the old certificates without conflict.</p>
<h2 id="how-do-i-upgrade-certbot-now-that-let%E2%80%99s-encrypt-have-removed-support-for-domain-validation-with-tls-sni-01%3F" tabindex="-1">How do I upgrade Certbot now that Let’s Encrypt have removed support for domain validation with TLS-SNI-01? <a class="direct-link" href="https://fuzzylogic.me/posts/certbot-troubleshooting/#how-do-i-upgrade-certbot-now-that-let%E2%80%99s-encrypt-have-removed-support-for-domain-validation-with-tls-sni-01%3F" aria-hidden="true">#</a></h2>
<p>Essentially the server needs Certbot v0.28 or above. See <a href="https://community.letsencrypt.org/t/how-to-stop-using-tls-sni-01-with-certbot/83210">Let’s Encrypt’s post</a> on how to check your Certbot version and steps to take after upgrading to check everything is OK. To apply the upgrade I performed <code>apt-get update && apt-get upgrade -y</code> as root although depending on when you last did it this might be a bit risky as it could update a lot of packages rather than just the Certbot ones. It might be better to just try <code>sudo apt-get install certbot python-certbot-apache</code>.</p>
<h2 id="to-what-extent-should-i-configure-my-443-virtualhost-block-myself-or-is-it-done-for-me%3F" tabindex="-1">To what extent should I configure my 443 VirtualHost block myself or is it done for me? <a class="direct-link" href="https://fuzzylogic.me/posts/certbot-troubleshooting/#to-what-extent-should-i-configure-my-443-virtualhost-block-myself-or-is-it-done-for-me%3F" aria-hidden="true">#</a></h2>
<p>When creating a new vhost on your Linode, DigitalOcean (or other cloud hosting platform) server, you need only add the <code><VirtualHost *:80></code> directive. No need to add a <code><VirtualHost *:443></code> section, nor worry about pointing to LE certificate files, nor bother writing rules to redirect http to https like I used to. When you install your secure certificate, certbot will automatically add the redirect into your original file and create an additional vhost file (with extension <code>-le.ssl.conf</code>) based on the contents of your existing file but handling <code><VirtualHost *:443></code> and referencing all the LE SSL certificate files it installed elsewhere on the system.</p>
<h2 id="how-should-i-manage-automated-renewals%3F" tabindex="-1">How should I manage automated renewals? <a class="direct-link" href="https://fuzzylogic.me/posts/certbot-troubleshooting/#how-should-i-manage-automated-renewals%3F" aria-hidden="true">#</a></h2>
<p>There’s no longer any need to manually add a cron job for certiticate renewal. Auto-renewal of certificates is now handled by a cron job which comes bundled with the certbot package you initially install – in my case usually a certbot ppa package for Ubuntu 16.04 or 18.04. However you won’t find that cron job in the crontab for either your limited user, nor the root user. Instead, it is <a href="https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-18-04">installed at a lower level</a> (<code>/etc/cron.d</code>) and should <em>just work</em> unless you’ve done something fancy with <code>systemd</code> in your system which in my case is unlikely.</p>
<h2 id="how-can-i-tell-if-renewals-are-working-and-what-should-i-do-if-they%E2%80%99re-not%3F" tabindex="-1">How can I tell if renewals are working and what should I do if they’re not? <a class="direct-link" href="https://fuzzylogic.me/posts/certbot-troubleshooting/#how-can-i-tell-if-renewals-are-working-and-what-should-i-do-if-they%E2%80%99re-not%3F" aria-hidden="true">#</a></h2>
<p>If you notice that the SSL certificate for your domain is within 30 days of expiry and hasn’t yet auto-renewed, then you know that something has gone wrong with the auto-renewal process. You can test for problems by running <code>sudo certbot renew --dry-run</code>. You may find that there is, for example, a syntax error in your <code>apache2.conf</code> or nginx config file which needs corrected – not that I’ve ever been guilty of this, you understand…</p>
W3C HTML Element Sampler2019-02-08T13:24:32Zhttps://fuzzylogic.me/posts/w3c-html-element-sampler/<p>In all my years of spinning up “HTML Typographic Elements” lists or pages as a reference for designers, I didn’t realise that the W3C provide the very thing I needed in their <em>HTML Element Sampler</em>. These pages provide comprehensive dummy content covering all the main typographic elements which is really handy when designing a website’s typographic styles and pattern library.</p>
Newspaper Terminology (from The Guardian)2019-01-11T21:03:21Zhttps://fuzzylogic.me/posts/newspaper-terminology-from-the-guardian/<p>The web and print are different media, however I still find some of print’s time-honoured terminology useful for naming things.</p>
<p>For example I use <em>standfirst</em> to identify intro paragraphs on <a href="https://www.greenhilldigital.com/journal/greenhill-goes-back-to-school">Greenhill Journal Entries</a>. This Guardian resource is a useful reference.</p>
Styling a Select Like It’s 2019 (Filament Group, Inc.)2019-01-09T19:06:04Zhttps://fuzzylogic.me/posts/2019-12-21-styling-a-select-like-its-2019-or-filament-group-inc/<blockquote>
<p>Recently, we’d seen some articles suggest that things haven’t changed a great deal with select's styling limitations, but I decided to return to the problem and tinker with it myself to be sure. As it turns out, a reasonable set of styles can create a consistent and attractive select across new browsers, while remaining just fine in older ones too.</p>
</blockquote>
<p>Here’s a breakthrough in the always-frustrating field of styling form elements. Scott Jehl of Filament Group introduces a new technique for styling the <code>select</code> element in a modern way without the need for a parent element, pseudo-elements, or javascript. Thanks, Scott!</p>
<p>(via <a href="https://twitter.com/scottjehl">@scottjehl</a>)</p>
Promises in JavaScript2018-12-13T17:07:00Zhttps://fuzzylogic.me/posts/javascript-promises-explained/<p>A brief explainer (for future-me and anyone else it helps) on what promises are and how to use them. Note: this is not an <em>official</em> definition, but rather one that works for me.</p>
<p>In the normal run of things, JavaScript code is <em>synchronous</em>. When line 1 has run (perhaps defining a new variable) and the operation has completed, line 2 runs (perhaps operating on the variable we just defined). However sometimes in line 1 we need to do something which will take longer – maybe an unknown length of time – for example to call a function which fetches data from an external API. In many cases we don’t mind that taking a while, or even eventually failing, but we want it to execute <em>separately</em> from the main JavaScript thread so as not to hold up the execution of line 2. So instead of waiting for the task to complete and return its value, our API-calling function instead returns a <em>promise</em> to supply that value in the future.</p>
<p>A Promise is an object we use for asynchronous operations. It’s a proxy for the success value or failure reason of the asynchronous operation, which at the time the promise is created is not necessarily yet known.</p>
<p>A promise is in one of three states:</p>
<ul>
<li>pending</li>
<li>fulfilled (the operation completed successfully)</li>
<li>rejected (the operation failed)</li>
</ul>
<p>We say a pending promise can go on to be either fulfilled with a value, or rejected with a reason (error).</p>
<p>We also talk about a promise being <em>settled</em> when it is no longer pending.</p>
<p>One memorable analogy was provided in Mariko Kosaka’s <em><a href="https://web.archive.org/web/20190212114232/http://kosamari.com/notes/the-promise-of-a-burger-party">The Promise of a Burger Party</a></em>. In it she describes the scenario of ordering a burger from, say, Burger King. It goes something like this:</p>
<ul>
<li>you place your order for a Whopper;</li>
<li>they give you a tray with a buzzer. The tray is a <em>promise</em> that they will provide your burger as soon as it has been cooked, and the buzzer is the promise‘s <em>state</em>;</li>
<li>the buzzer is not buzzing to start with: it’s in the <em>pending</em> state;</li>
<li>the buzzer buzzes: the promise is now <em>settled</em>;</li>
<li>they might inform you that their flame-grill broke down half-way through. The cooking operation failed, and the promise of a burger has been rejected with that reason. You’ll likely want to act on that (by getting a refund);</li>
<li>alternatively all goes to plan, you go the counter and they fulfil their promise of a tasty burger placed onto your tray.</li>
<li>you decide you want to act on the success of getting your tasty burger by doing another thing, namely buying a coke. In code you’ll be within the <code>.then()</code> method which is the success handler for your promise and in there you can just call <code>buyCoke()</code>. (Note: the <code>buyCoke()</code> operation might be <em>synchronous</em>; the real life analogy being that it’s so quick to pour a coke that the assistant does it and serves it on a tray immediately rather than giving you a tray as a promise for it.) At the end of your <code>then()</code> you might choose to return a <code>meal</code> object which combines your burger and coke.</li>
<li>You could then chain a further <code>.then()</code> to the original <code>.then()</code> to work with your snowballing data value. This is because <code>then()</code> methods always return a promise (even if the operation within was not asynchronous), and we already know that promises are <em>thenable</em> (i.e. have a <code>then()</code> method) hence our ability to keep chaining.</li>
</ul>
<h2 id="promise-syntax" tabindex="-1">Promise syntax <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-promises-explained/#promise-syntax" aria-hidden="true">#</a></h2>
<p>There are two things we need to be able to do with promises:</p>
<ol>
<li>create and return them;</li>
<li>work with a returned promise.</li>
</ol>
<h3 id="create-and-return-a-promise" tabindex="-1">Create and return a promise <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-promises-explained/#create-and-return-a-promise" aria-hidden="true">#</a></h3>
<p>When you create a promise you pass a function known as the executor to it, which runs instantly. Its arguments <code>resolve</code> and <code>reject</code> are callbacks provided by JavaScript. Our code goes inside the executor.</p>
<figure>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> examplePromise <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// do a thing, possibly async, then…</span><br /><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token comment">/* everything turned out fine */</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">"Stuff worked!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br /> <span class="token function">reject</span><span class="token punctuation">(</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token string">"It broke"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /></code></pre>
</figure>
<h3 id="work-with-a-returned-promise" tabindex="-1">Work with a returned promise <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-promises-explained/#work-with-a-returned-promise" aria-hidden="true">#</a></h3>
<figure>
<pre class="language-js"><code class="language-js">examplePromise<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Success!"</span><span class="token punctuation">,</span> response<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><br /><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Failed!"</span><span class="token punctuation">,</span> error<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
</figure>
<h2 id="references" tabindex="-1">References <a class="direct-link" href="https://fuzzylogic.me/posts/javascript-promises-explained/#references" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://web.dev/promises/">Promises, by Jake Archibald</a></li>
<li><a href="https://javascript.info/promise-basics">Promises, by javascript.info</a></li>
</ul>
My Git Cheatsheet2018-12-01T16:58:08Zhttps://fuzzylogic.me/posts/my-git-cheatsheet/<p>I’ve used Git for many years but it can still trip me up. At times I’ve worked primarily in a GUI (like Sourcetree or Fork), and other times directly on the command line. I’ve worked on projects where I’ve been the sole developer and others where I’m part of a large team. Regardless of the tools or context, I’ve learned there are certain <em>need-to-knows</em>. Here’s a list of useful Git concepts and commands for my reference and yours.</p>
<p>Note: the following is not an exhaustive list but rather the thing I keep coming back to and/or regularly forget. For deeper explanations, see the list of resources at the foot of the article.</p>
<h2 id="table-of-contents" tabindex="-1">Table of contents <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#table-of-contents" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#starting-work">Starting work</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#remotes">Remotes</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#committing-updates">Committing updates</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#branches">Branches</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#save-changes-temporarily">Save changes temporarily</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#staying-current-and-compatible">Staying current and compatible</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#reviewing-your-activity">Reviewing your activity</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#fixing-things">Fixing things</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#miscellaneous-handy-things">Miscellaneous handy things</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#useful-github-stuff">Useful GitHub stuff</a></li>
<li><a href="https://fuzzylogic.me/posts/my-git-cheatsheet/#useful-external-resources">Useful external resources</a></li>
</ul>
<h2 id="starting-work" tabindex="-1">Starting work <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#starting-work" aria-hidden="true">#</a></h2>
<h3 id="create-a-remotely-hosted-repo" tabindex="-1">Create a remotely-hosted repo <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#create-a-remotely-hosted-repo" aria-hidden="true">#</a></h3>
<details>
<summary>Option 1: Create a new repo in your Github account</summary>
<p>This generates a new, empty repo (optionally initialised with a README).</p>
<p>Do this when you will be working on a new, dedicated project rather than contributing changes to a pre-existing one.</p>
</details>
<details>
<summary>Option 2: Create repo from a “template repository” (owned by you or someone else)</summary>
<p>This generates a new repo with the same directory structure and files as the template. It’s a good option for starting your own new, potentially long-lived project from a solid starting point.</p>
<p>Unlike a fork it does not include the entire commit history of the parent repository. Instead it starts with a single commit.</p>
<p>Github Reference: <a href="https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template">Creating a repository from a template</a></p>
</details>
<details>
<summary>Option 3: Fork an existing repo (usually owned by someone else)</summary>
<p>This generates a new repo which is a copy of another repo, including its commit history. Your commits will update your copy rather than the original repo.</p>
<p>Do this by clicking the <em>Fork</em> button in the header of a repository.</p>
<p>This is good for (often short-lived) collaboration on an existing repo. You can contribute code to someone else’s project, via PRs.</p>
<p>Github Reference: <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks">Working with forks</a></p>
</details>
<h3 id="start-locally-by-cloning" tabindex="-1">Start locally by cloning <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#start-locally-by-cloning" aria-hidden="true">#</a></h3>
<p><code>clone</code> creates a <em>local copy</em> on your computer of a remote (Github-hosted) repo.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token builtin class-name">cd</span> projects<br /><span class="token function">git</span> clone https://github.com/githubusername/projectname.git optionallocaldirectoryname</code></pre>
</figure>
<p>You might be cloning a repo you own, or one owned by someone else (to use its features in your project).</p>
<p>Your local copy will, by default, have its <code>origin</code> remote set to the Github repo you cloned.</p>
<details>
<summary>I cloned an empty new project</summary>
<p>We’re in easy streets. The default remote is set exactly as you want it. Just write code, <code>push</code> at your leisure, and <code>pull</code> if/when you need to.</p>
</details>
<details>
<summary>I cloned a pre-existing project (owned by me or someone else):</summary>
<details>
<summary>I plan to use it in my own, separate project</summary>
<p>You might want to cut all ties and have a clean slate, git-wise.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">rm</span> -rf .git<br /><span class="token function">git</span> init<br /><span class="token function">git</span> remote <span class="token function">add</span> origin https://github.com/mygithubusername/mynewproject.git<br /><span class="token function">git</span> push -u origin master</code></pre>
</figure>
<p>Alternatively you might want to keep the original <code>remote</code> available so you can pull in its future project updates, but reset the <code>origin</code> remote to your new/target repo.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> remote <span class="token function">rename</span> origin upstream<br /><span class="token function">git</span> remote <span class="token function">add</span> origin https://github.com/mygithubusername/mynewproject.git<br /><span class="token function">git</span> push origin master<br /><span class="token function">git</span> pull origin master<br /><span class="token comment"># in the future the original repo gets an update</span><br /><span class="token function">git</span> pull upstream master</code></pre>
</figure>
</details>
<details>
<summary>The source repo is my fork of a project to which I want to contribute</summary>
<p>See <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks">Working with forks</a> for how best to stay in sync and open PRs.</p>
</details>
<summary>Duplicating (also knows as “duplicate without forking”)</summary>
<p>This is a special type of clone. I know this is an option, but it‘s not one I’m familiar with or have had call to use. I can refer to <a href="https://help.github.com/en/github/creating-cloning-and-archiving-repositories/duplicating-a-repository">Duplicating a repository</a> if need be.</p>
</details>
<h3 id="start-locally-from-a-blank-slate" tabindex="-1">Start locally from a blank slate <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#start-locally-from-a-blank-slate" aria-hidden="true">#</a></h3>
<p>Although cloning is the easiest way to get started locally, ocassionally I start by coding from scratch instead.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">mkdir</span> myproject <span class="token operator">&&</span> <span class="token builtin class-name">cd</span> myproject<br /><span class="token builtin class-name">echo</span> <span class="token string">"# Welcome to My Project Repo"</span> <span class="token operator">>></span> README.md<br /><span class="token function">git</span> init<br /><span class="token function">git</span> <span class="token function">add</span> README.md<br /><span class="token function">git</span> commit -m <span class="token string">"first commit"</span><br /><br /><span class="token comment"># go to Github and create an empty repo, if you haven’t already.</span><br /><span class="token comment"># then add as a remote</span><br /><span class="token function">git</span> remote <span class="token function">add</span> origin https://github.com/mygitusername/myproject.git<br /><br /><span class="token comment"># push up, passing -u to set the remote branch as the default upstream branch our local branch will track</span><br /><span class="token comment"># this saves typing out ‘origin master’ repeatedly in future.</span><br /><span class="token function">git</span> push -u origin master</code></pre>
</figure>
<h2 id="remotes" tabindex="-1">Remotes <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#remotes" aria-hidden="true">#</a></h2>
<p>Remove a remote from your local settings:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> remote <span class="token function">rm</span> <span class="token operator"><</span>name<span class="token operator">></span></code></pre>
</figure>
<p>Rename a remote:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> remote <span class="token function">rename</span> oldname newname</code></pre>
</figure>
<h2 id="configuration" tabindex="-1">Configuration <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#configuration" aria-hidden="true">#</a></h2>
<p>Configure your favourite editor to be used for commit messages:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> config --global core.editor <span class="token string">"nano"</span></code></pre>
</figure>
<p>Use <code>git st</code> as a shortcut for <code>git status</code> (to stop me mistyping as “statsu”):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> config --global alias.st status</code></pre>
</figure>
<p>Configure any setting:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> config <span class="token punctuation">[</span>--global<span class="token punctuation">]</span> <span class="token operator"><</span>key<span class="token operator">></span> <span class="token operator"><</span>value<span class="token operator">></span><br /> <br /><span class="token function">git</span> config --global user.email <span class="token string">"myname@domain.com"</span></code></pre>
</figure>
<h2 id="staging%2C-unstaging-and-deleting-files" tabindex="-1">Staging, unstaging and deleting files <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#staging%2C-unstaging-and-deleting-files" aria-hidden="true">#</a></h2>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># stage all unstaged files</span><br /><span class="token function">git</span> <span class="token function">add</span> <span class="token builtin class-name">.</span><br /><br /><span class="token comment"># stage individual file/s</span><br /><span class="token function">git</span> <span class="token function">add</span> filename.txt</code></pre>
</figure>
<p>Unstage with <code>reset</code> (the opposite of <code>git add</code>):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># unstage all staged files</span><br /><span class="token function">git</span> reset <span class="token builtin class-name">.</span><br /><br /><span class="token comment"># unstage individual file/s</span><br /><span class="token function">git</span> reset filename.txt</code></pre>
</figure>
<p>Delete a physical file and stage the deletion for the next commit:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> <span class="token function">rm</span> folder/filename.txt</code></pre>
</figure>
<h2 id="committing-updates" tabindex="-1">Committing updates <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#committing-updates" aria-hidden="true">#</a></h2>
<p>Commit with <a href="https://thoughtbot.com/blog/5-useful-tips-for-a-better-commit-message">a multi-line message</a>:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> commit</code></pre>
</figure>
<p>Commit with short message:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> commit -m <span class="token string">"fix: typo in heading"</span></code></pre>
</figure>
<p>Stage and commit all changes in a single command (note: doesn’t work with new, untracked files):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> commit -am <span class="token string">"fix: typo in heading"</span></code></pre>
</figure>
<h2 id="branches" tabindex="-1">Branches <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#branches" aria-hidden="true">#</a></h2>
<p>Show all local branches:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> branch</code></pre>
</figure>
<p>Show all local <em>and remote</em> branches:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> branch -a</code></pre>
</figure>
<p>Show branches you last worked on (most recently commited to):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> branch --sort<span class="token operator">=</span>-committerdate</code></pre>
</figure>
<p>Save current state to new branch but don’t yet switch to it (useful after committing to wrong branch):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> branch newbranchname</code></pre>
</figure>
<p>Create and switch to new branch (<code>main</code> or whatever branch you want to branch off):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout -b mynewbranch</code></pre>
</figure>
<p>Note that if you branch off <code>foo_feature</code> then when creating a PR in GitHub for your changes in <code>mynewbranch</code> you can change the <em>Base</em> branch from the default of <code>main</code> to <code>foo_feature</code>. This specifies that you are requesting your changes be merged into <code>foo_feature</code> rather than <code>main</code> and makes the comparison of changes relative to <code>foo_feature</code> rather than <code>main</code>.</p>
<p>Switch to an existing branch:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout branchname</code></pre>
</figure>
<p>Save typing by setting the upstream remote branch for your local branch:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># git branch -u remotename/branchname</span><br /><span class="token function">git</span> branch -u fuzzylogic/v3<br /><br /><span class="token comment"># now there’s no need to type origin master</span><br /><span class="token function">git</span> pull</code></pre>
</figure>
<p>Delete local branch:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> branch -d name_of_branch<br /><br /><span class="token comment"># need to force it because of some merge issue or similar?</span><br /><span class="token function">git</span> branch -D name_of_branch</code></pre>
</figure>
<h2 id="save-changes-temporarily" tabindex="-1">Save changes temporarily <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#save-changes-temporarily" aria-hidden="true">#</a></h2>
<p><code>stash</code> is like a clipboard for git.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># Before changing branch, save changes you’re not ready to commit</span><br /><span class="token function">git</span> stash<br /><br /><span class="token comment"># change branch, do other stuff. Then when return:</span><br /><span class="token function">git</span> stash pop</code></pre>
</figure>
<h2 id="staying-current-and-compatible" tabindex="-1">Staying current and compatible <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#staying-current-and-compatible" aria-hidden="true">#</a></h2>
<p><code>fetch</code> remote branch and <code>merge</code> simultaneously:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> pull remotename branchname<br /><br /><span class="token comment"># common use case is to update our local copy of master</span><br /><span class="token function">git</span> pull origin master<br /><br /><span class="token comment"># shorthand when a default upstream branch has been set</span><br /><span class="token function">git</span> pull<br /><br /><span class="token comment"># an alternative is to update (fetch) which does not auto-merge, then 'reset' to the latest commit on the remote</span><br /><span class="token comment"># https://stackoverflow.com/questions/55731891/effects-of-git-remote-update-origin-prune-on-local-changes</span><br /><span class="token function">git</span> checkout master<br /><span class="token function">git</span> remote update --prune<br /><span class="token function">git</span> reset --hard origin/master</code></pre>
</figure>
<p>Merge another branch (e.g. master) into current branch:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> merge otherbranch<br /><br /><span class="token comment"># a common requirement is to merge in master</span><br /><span class="token function">git</span> merge master</code></pre>
</figure>
<h3 id="rebasing" tabindex="-1">Rebasing <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#rebasing" aria-hidden="true">#</a></h3>
<p><code>git rebase</code> can be used as:</p>
<ol>
<li>an alternative to merge; and</li>
<li>a means of tidying up our recent commits.</li>
</ol>
<p>As an alternative to merge its main pro is that it leads to a more linear therefore easier-to-read history. Note however that it is potentially more disruptive therefore not right for every situation.</p>
<p>Say I’ve been working on a feature branch and I think it’s ready.</p>
<p>I might want to just tidy up my feature branch’s commits and can do this with an “interactive rebase”. This technique allows me to tidy my feature branch work to remove trivial, exploratory and generally less relevant commits so as to keep the commit history clean.</p>
<p>I might also want to bring in <code>master</code> to ensure synchronicity and compatibility. <code>rebase</code> sets the head of my feature branch to the head of <code>master</code> then adds my feature branch’s commits on top.</p>
<p>While it’s a good idea to <code>rebase</code> <em>before</em> making a <abbr title="Pull Request">PR</abbr>, <strong>don’t use it after making a PR</strong> because from that point on the branch is <em>public</em> and rebasing a public branch can cause problems for collaborators on the branch. (The only exception to the previous rule is if you’re likely to be the only person working on the PR branch)</p>
<p>Rebuild your feature branch’s changes on top of master:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout master<br /><span class="token function">git</span> pull origin master<br /><span class="token function">git</span> checkout myfeaturebranch<br /><span class="token function">git</span> rebase master</code></pre>
</figure>
<p>Force push your rebased branch (again, only when you’re unlikely to have/require collaborators on the PR):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> push --force origin myfeaturebranch</code></pre>
</figure>
<p>Tidy a feature branch before making a PR:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout myfeaturebranch<br /><span class="token function">git</span> rebase -i master<br /><br /><span class="token comment"># just tidy the last few (e.g. 3) commits</span><br /><span class="token function">git</span> rebase -i HEAD~3<br /><br /><span class="token comment"># this opens a text editor listing all commits due to be moved, e.g.:</span><br />pick 33d5b7a Message <span class="token keyword">for</span> commit <span class="token comment">#1</span><br />pick 9480b3d Message <span class="token keyword">for</span> commit <span class="token comment">#2</span><br />pick 5c67e61 Message <span class="token keyword">for</span> commit <span class="token comment">#3</span><br /><br /><span class="token comment"># change 'pick' to 'fixup' to condense commits, say if #2 was just a small fix to #1</span><br />pick 33d5b7a Message <span class="token keyword">for</span> commit <span class="token comment">#1</span><br />fixup 9480b3d Message <span class="token keyword">for</span> commit <span class="token comment">#2</span><br />pick 5c67e61 Message <span class="token keyword">for</span> commit <span class="token comment">#3</span><br /> <br /><span class="token comment"># alternatively if use 'squash', after saving it will open an editor </span><br /><span class="token comment"># and prompt you to set a new commit message for the combined stuff.</span><br />pick 33d5b7a Message <span class="token keyword">for</span> commit <span class="token comment">#1</span><br />squash 9480b3d Message <span class="token keyword">for</span> commit <span class="token comment">#2</span><br />squash 5c67e61 Message <span class="token keyword">for</span> commit <span class="token comment">#3</span></code></pre>
<p><a href="https://www.git-tower.com/learn/git/faq/git-squash">More on squash including a handly little video if I forget how it works.</a></p>
</figure>
<p>Undo a rebase:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> reset --hard ORIG_HEAD</code></pre>
</figure>
<p>For more detail, read <a href="https://www.atlassian.com/git/tutorials/merging-vs-rebasing">Atlassian’s guide to rebasing</a>.</p>
<h2 id="reviewing-your-activity" tabindex="-1">Reviewing your activity <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#reviewing-your-activity" aria-hidden="true">#</a></h2>
<p>Show commit history (most recent first; <code>q</code> to quit):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> log<br /><br /><span class="token comment"># compact version</span><br /><span class="token function">git</span> log --oneline<br /><br /><span class="token comment"># limit scope to commits on a branch</span><br /><span class="token function">git</span> log branchname</code></pre>
</figure>
<p>Check if your feature branch is trailing behind:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># show commits in master that are not yet in my feature branch</span><br /><span class="token function">git</span> log --oneline my-feature<span class="token punctuation">..</span>master<br /><br /><span class="token comment"># show commits on remote branch that are not yet in my local branch</span><br /><span class="token function">git</span> log --pretty<span class="token operator">=</span><span class="token string">'format:%h - %an: %s'</span> new-homepage<span class="token punctuation">..</span>origin/new-homepage<br /><br /><span class="token comment"># show commits by me that included “heroku” and that changed file Gemfile</span><br /><span class="token function">git</span> log --author<span class="token operator">=</span>Demaree --grep<span class="token operator">=</span>heroku --oneline Gemfile</code></pre>
</figure>
<p>Show changes that occurred in the most recent commit or a given commit.</p>
<figure>
<pre><code>git show
# show changes in a given commit
git show 591672e
</code></pre>
</figure>
<p>Review differences between staged changes and last commit:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> <span class="token function">diff</span> --cached</code></pre>
</figure>
<p>Review changes between a given version/commit and the latest:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> <span class="token function">diff</span> 591672e<span class="token punctuation">..</span>master</code></pre>
</figure>
<h2 id="fixing-things" tabindex="-1">Fixing Things <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#fixing-things" aria-hidden="true">#</a></h2>
<p>Discard all your as-yet uncommitted changes:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> restore <span class="token builtin class-name">.</span></code></pre>
</figure>
<p>Get your local feature branch out of a problem state by resetting to the state it is on the remote (e.g. at last <code>push</code>).</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> reset --hard origin/my-branch</code></pre>
</figure>
<p>Undo all the changes in a given commit:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> revert 591672e</code></pre>
</figure>
<p>Alter the previous commit (change the message and/or include further updates):</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># we are amending the previous commit rather than creating a new commit.</span><br /><span class="token comment"># if file changes are staged, it amends previous commit to include those.</span><br /><span class="token comment"># if there are no staged changes, it lets us amend the previous commit’s message only.</span><br /><span class="token function">git</span> commit --amend</code></pre>
</figure>
<p>Move current branch tip backward to a given commit, reset the staging area to match, but leave the working directory alone:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> reset 591672e<br /><br /><span class="token comment"># additionally reset the working directory to match the given commit</span><br /><span class="token function">git</span> reset --hard 591672e</code></pre>
</figure>
<p>See what the app/site was like (e.g. whether things worked or were broken) at a given previous commit, noting the following:</p>
<ul>
<li>You’re now “detatched”, in that your computer’s HEAD is pointing at a commit rather than a branch.</li>
<li>You’re expected to merely review, not to make commits. Any commits you make would be “homeless”, since commits are supposed to go in branches. (However you could then branch off.)</li>
</ul>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout 591672e</code></pre>
</figure>
<p>Return one or more files to the state they were in at a previous commit, without reverting everything else.</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout 3aa647dac9a8a251ca223a693d4c140fd3c1db11 /path/to/file.md /path/to/file2.erb<br /><br /><span class="token comment"># if happy you then need to commit those changes</span><br /><span class="token function">git</span> commit</code></pre>
</figure>
<p>When <code>git st</code> reveals a list of staged files including lots of strange files you don’t want there mixed with others you do…</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># add those you want to stay modified and staged</span><br /><span class="token function">git</span> <span class="token function">add</span> path/to/file-I-want-1.rb path/to/file-I-want-2.md <br /><br /><span class="token comment"># this will clear all others out of the stage</span><br /><span class="token function">git</span> checkout <span class="token builtin class-name">.</span></code></pre>
</figure>
<p>Grab one or more commits from elsewhere and drop into your current branch:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> cherry-pick 591672e<br /><br /><span class="token comment"># grab the last commit from a branch e.g. master</span><br /><span class="token function">git</span> cherry-pick master</code></pre>
</figure>
<p>Fix a pull that went wrong / shouldn’t have been done:</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> pull origin branchname<br /><span class="token comment"># whoops!</span><br /><br /><span class="token function">git</span> reflog<br /><span class="token comment"># shows a list of every thing you've</span><br /><span class="token comment"># done in git, across all branches!</span><br /><span class="token comment"># each one has an index HEAD@{index}</span><br /><span class="token comment"># find the one before you broke everything</span><br /><br /><span class="token function">git</span> reset HEAD@<span class="token punctuation">{</span>index<span class="token punctuation">}</span><br /><span class="token comment"># magic time machine</span></code></pre>
</figure>
<h2 id="miscellaneous-handy-things" tabindex="-1">Miscellaneous handy things <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#miscellaneous-handy-things" aria-hidden="true">#</a></h2>
<p>Revert to the previous branch you were on</p>
<figure>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> checkout -</code></pre>
</figure>
<h2 id="useful-github-stuff" tabindex="-1">Useful GitHub stuff <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#useful-github-stuff" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://github.com/%5Buser%5D/%5Brepo%5D/branches/yours">Review your branches on a repo</a></li>
<li><a href="https://github.com/notifications/subscriptions">Review PRs and issues you’re subscribed to</a>, i.e. ones on which you were active or mentioned</li>
<li><a href="https://github.com/pulls?q=is%3Apr+author%3Afuzzylogicxx+archived%3Afalse+">Review your or another user’s PRs</a></li>
<li>If you are fixing something that was raised in a GitHub issue, link that issue in your fix PR’s sidebar under <em>Linked Issues</em> (rather than just mentioning it in the PR) and it will automatically close the issue when you merge.</li>
</ul>
<h2 id="useful-external-resources" tabindex="-1">Useful external resources <a class="direct-link" href="https://fuzzylogic.me/posts/my-git-cheatsheet/#useful-external-resources" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.atlassian.com/git/tutorials/atlassian-git-cheatsheet">Tips, tutorials and Cheat Sheets from Atlassian</a></li>
<li>Need to undo an old commit? Committed to master by mistake? Get out of trouble with <a href="https://ohshitgit.com/"><em>Oh Shit, Git!</em></a></li>
<li>More getting out of trouble: <a href="https://github.com/k88hudson/git-flight-rules">Git Flight Rules</a></li>
<li><a href="https://jasonm23.github.io/oh-my-git-aliases.html">Oh-my-zsh Git aliases</a> and <a href="https://github.com/ohmyzsh/ohmyzsh/issues/6266">how to add your own</a></li>
<li><a href="https://git-scm.com/book/en/v2">The original Pro Git reference</a></li>
<li><a href="https://abookapart.com/products/git-for-humans"><em>Git for Humans</em></a> by David Demaree from <em>A List Apart</em> is a great intro to the concepts and basic commands.</li>
</ul>
Definitive web font @font-face syntax2018-11-27T13:14:00Zhttps://fuzzylogic.me/posts/definitive-web-font-font-face-syntax/<p>These days, whenever I’m about to use a web font on a new site I generally find myself running a google search for the latest “definitive <code>@font-face</code> syntax” that covers all modern browser/device needs.</p>
<p>For a long time I headed straight for <a href="https://www.paulirish.com/2009/bulletproof-font-face-implementation-syntax/">Paul Irish’s Bulletproof @font-face Syntax</a> but I noted a few years back that he’d stopped updating it.</p>
<p>When buying web fonts from type foundries such as <a href="https://www.fontsmith.com/">Fontsmith</a> the foundries do tend to provide their own guidelines. However, I’m not convinced that these are sufficiently cross-platform compatible.</p>
<p>Recently I’ve been reading <a href="https://abookapart.com/products/flexible-typesetting">Flexible Typesetting</a> by Tim Brown and in it he recommends <a href="https://abookapart.com/products/webfont-handbook">Webfont Handbook</a> by Bram Stein. That’s now next on my reading list, however in the meantime I found <a href="https://alistapart.com/article/using-webfonts/">an excerpt on <em>A List Apart</em></a> which specifically covers the best modern <code>@font-face</code> syntax.</p>
<p>Based on Stein’s advice, here’s what I’m now using.</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@font-face</span></span> <span class="token punctuation">{</span><br /> <span class="token property">font-family</span><span class="token punctuation">:</span> Elena<span class="token punctuation">;</span><br /> <span class="token property">src</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>elena.woff2<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff2"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>elena.woff<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>elena.otf<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"opentype"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
<p>Soon, when all browsers support the <code>woff</code> format we’ll be able to reduce this to simply:</p>
<figure>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@font-face</span></span> <span class="token punctuation">{</span><br /> <span class="token property">font-family</span><span class="token punctuation">:</span> Elena<span class="token punctuation">;</span><br /> <span class="token property">src</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>elena.woff2<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff2"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span>elena.woff<span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</figure>
Surface Noise2018-11-14T09:30:00Zhttps://fuzzylogic.me/posts/surface-noise/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1589737885/tnf003sideb_qdaezf.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1589737885/tnf003sideb_qdaezf.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1589737885/tnf003sideb_qdaezf.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1250/v1589737885/tnf003sideb_qdaezf.jpg 1250w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1589737885/tnf003sideb_qdaezf.jpg" width="320" height="320" alt="B-side artwork of TNF003: The Nuclear Family vs Other Lands – “Surface Noise”" loading="lazy" decoding="async" />
<figcaption>TNF003: Side B artwork
</figcaption></figure>
<p>It’s taken a few years, but me and Tom are excited to be releasing a new record on our label, <a href="https://www.discogs.com/label/708424-The-Nuclear-Family">The Nuclear Family</a>.</p>
<p><a href="https://soundcloud.com/the_nuclear_family/sets/tnf-003-surface-noise-clips">Check out the audio previews</a>.</p>
<p>Titled <em>Surface Noise</em>, our third release will be available on both 12″ vinyl and digital, hitting all good record stores in early November ‘18.</p>
<p>You can <a href="https://the-nuclear-family.bandcamp.com/album/surface-noise">pre-order it now from our Bandcamp page</a>.</p>
<p>Here's what our press release says:</p>
<p>Artist: The Nuclear Family vs Other Lands<br />
Title: Surface Noise<br />
Label: The Nuclear Family<br />
A: The Nuclear Family - Surface Noise<br />
B: Other Lands - See Thru Time</p>
<p>Did you miss us? The Nuclear Family - Tom Churchill and Laurence Hughes - are back after a three-year hiatus, and this time we’ve roped in one of our good buddies, <a href="https://www.discogs.com/artist/6118087-Other-Lands">Other Lands</a>, to help us deliver a double-header of deep delights for discerning DJs and dancers, cut nice and loud over a full side each.</p>
<p>Surface Noise, on side A, is the first of the Family’s recent studio jams to see the light of day, with its classic 808 drums and analogue bass underpinning warm pads, twinkling melodies and some subtle vocoder flourishes.</p>
<p>On the flipside, we’re honoured to present a killer track from Other Lands - aka Edinburgh’s veteran DJ/producer Gavin Sutherland, fresh from the success of his recent Pattern Transform 12” for Firecracker and all manner of other exciting studio and live projects. See Thru Time is a masterclass for the heads, with mellifluous chord progressions and a timeless groove.</p>
<p>TNF 003 will be available on vinyl via Rubadub in November, along with a digital version via Bandcamp.</p>
Rise by Gina Miller2018-10-30T16:13:11Zhttps://fuzzylogic.me/posts/rise-by-gina-miller/<p>I’ve just read <em>Rise</em> by Gina Miller.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1623696669/img2jan2019at185002_fqghbo.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1623696669/img2jan2019at185002_fqghbo.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1623696669/img2jan2019at185002_fqghbo.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1623696669/img2jan2019at185002_fqghbo.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1623696669/img2jan2019at185002_fqghbo.jpg 1600w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1623696669/img2jan2019at185002_fqghbo.jpg" width="320" height="240" alt="A photo of the book Rise, by Gina Miller" loading="lazy" decoding="async" />
<figcaption>Rise by Gina Miller</figcaption>
</figure>
<p>In 2016 Miller took the UK government to court for attempting to force through Article 50—the mechanism for starting Brexit—which would have lead to the nation leaving the EU without parliamentary consent.</p>
<p>Its title a reference to the Maya Angelou poem <a href="https://www.poetryfoundation.org/poems/46446/still-i-rise">Still I Rise</a>, the book is partly the author’s story of how she has been shaped by the successes and failures in her life, and partly a personal manifesto stating that every person can stand up and make a positive difference, even in the face of adversity.</p>
<p>Miller begins with her fight, in the aftermath of the Brexit vote and the “festering wounds” it exposed, to ensure that the UK’s democratic process and constitution be upheld. She traces her background as a child born in Guayana, a British colony at the time. As the daughter of a self-made man who became the country’s attorney general, she and her family saw Great Britain as the promised land, “a culture where the rule of law was observed and decency was embedded in the national fabric.” Since moving to the UK, forging a successful career and speaking up for her beliefs, that notion of justice and decency has come under scrutiny as she has been met with racist and sexual prejudice and abuse from all walks of society.</p>
<p>The author goes on to describe some of the specific challenges she has faced in her life including vicious hate mail, attacks by the press, being in an abusive marriage, and raising a daughter with special needs. In the end however, as a successful businesswoman with a happy family, hers is a story of strength and survival and a message of hope.</p>
<p>As a man, at times I felt that the book—which often returned to themes of female empowerment—perhaps wasn’t intended for me. Then on other occasions I felt that it was as important (if not more important) for me and other men as for anyone else to absorb these stories of sexist bullying, discrimination and abuse told from the female perspective.</p>
<p>Other core messages of the book were universal: finding your voice, speaking up when it is important to do so, overcoming adversity, and demonstrating tolerance in a divided society.</p>
<p>This was a book I picked up on a whim as a departure from my usual reading subjects, and I’m glad I did.</p>
Cloudinary2018-09-16T15:59:24Zhttps://fuzzylogic.me/posts/2018-09-16-cloudinary/<p>Cloudinary is a very handy tool for image and video upload, storage, optimisation and CDN.</p>
<blockquote>
<p>Store, transform, optimize, and deliver all your media assets with easy-to-use APIs, widgets, or user interface.</p>
</blockquote>
<p>This was brought to my attention by <a href="https://twitter.com/grigs">Jason Grigsby</a> at An Event Apart. We were discussing his article series on Responsive Images and I asked if he could recommend a tool which auto-generated all of the images you needed for your responsive image code, if you provide a single source image.</p>
<p>I’ve been trying Cloudinary out and so far, so good.</p>
<p>(via <a href="https://twitter.com/grigs">@grigs</a>)</p>
Atomic Design by Brad Frost2018-09-12T00:00:00Zhttps://fuzzylogic.me/posts/atomic-design-by-brad-frost/<p>The original call-to-arms and manual for Design Systems.</p>
<p>Brad Frost explains why Design Systems are necessary, provides a methodology for Pattern Library creation, discusses Design System benefits and offers strategies for maintenance.</p>
Image Color2018-09-09T10:51:00Zhttps://fuzzylogic.me/posts/image-color/<p>A handy tool for identifying colours – provided in numerous different CSS-ready formats – and creating a complimentary colour palette from an image you upload or provide as a URL.</p>
Small Victories2018-09-09T10:40:00Zhttps://fuzzylogic.me/posts/small-victories/<blockquote>
<p>No CMS, no installation, no server, no coding required.</p>
</blockquote>
<p>Another quick and clever way of creating a website; this time by collecting a bunch of files (HTML, video, images, bookmarks) into a folder, connecting Dropbox and <em>Small Victories</em> to that, choosing a theme and Hey Presto, you have a website.</p>
<p>I could see this as maybe being useful for some sort of transient campaign idea that doesn’t need a CMS and that you want others to be able to collaborate on.</p>
<p>Note: to get a custom domain and host CSS and JS files, you need to sign up to a paid plan, but at $4/month or $36/year it’s pretty cheap.</p>
Carrd - simple, free, fully responsive one-page sites for pretty much anything2018-09-06T18:51:00Zhttps://fuzzylogic.me/posts/carrd/<p>These days when friends tell me they want a personal website, it’s often just a single-page profile that they’re really after rather than something pricier and more complicated.</p>
<p>In the past there were services like <a href="http://flavors.me/">http://flavors.me/</a> but it seems to have fallen by the wayside. This looks like a decent option to point friends toward if they’re not looking for a blog or want to take baby steps toward that. Incidentally, I came across Carrd through Chris Ferdinandi’s <a href="https://vanillajslist.com/">Vanilla JS List</a> which features organisations which favour Vanilla JavaScript over JS frameworks.</p>
Pendulum Sidespin Serve2018-09-06T06:18:00Zhttps://fuzzylogic.me/posts/pendulum-sidespin-serve/<p>Great video (in German with subtitles) which shows and tells the most important elements of this serve, namely:</p>
<ol>
<li>Brush the ball sideways extremely fast;</li>
<li>Swing your wrist about 90° extremely fast when touching the ball; and</li>
<li>The third bounce should be close to the side-edge of the table so that the opponent cannot easily attack and your spin has the strongest effect.</li>
</ol>
1984 by George Orwell2018-09-05T00:00:00Zhttps://fuzzylogic.me/posts/1984-by-george-orwell/<p>I’ve just read <em>1984</em> by George Orwell. I know, I know… I should have done this a long time ago. Anyway, here’s what I thought.</p>
<p>I remember a copy of <em>1984</em> being around the house when I was growing up but for some reason I never got around to reading it. I did, however, see the film when I was young – the “Room 101” scene in particular being unforgettable – and have always known the general plot.</p>
<p>On a recent work trip I realised while in the airport shop that I’d left a book at home so it seemed like as good a time as any to pick up a copy of <em>1984</em> and scratch this particular itch.</p>
<p>As a book about a dystopian future, I knew it would be dark, but it was even darker that I imagined. The constant sense of dread was really palpable.</p>
<p>I loved the concepts Orwell created – the Two Minutes Hate, doublethink, Thought Crime, Room 101 to name but a few.</p>
<p>I also loved the language in general and the appendix, <em>The Principles of Newspeak</em>.</p><p></p>
<p>And even though it was heart-wrenching and pretty harrowing, I loved the final descent into brainwashing (or “re-education”) and ultimately, betrayal.</p>
<p>This was an amazing book that I loved reading, while not necessarily always being ”enjoyable”.</p>
Gifox 2 for Mac - Delightful GIF Recording and Sharing App2018-09-03T21:00:41Zhttps://fuzzylogic.me/posts/2020-10-25-gifox-2-for-mac-delightful-gif-recording-and-sharing-app/<p>When watching presentations recently I’ve noticed that a few speakers use this tool to generate animated images for their slides.</p>
<blockquote>
<p>Gifox is a menu bar app that records your screen into animated GIFs – a great compromise between static images and full-size videos.</p>
</blockquote>
TunnelBear – VPN Software for Bears2018-09-03T15:42:00Zhttps://fuzzylogic.me/posts/tunnelbear-%E2%80%93-vpn-software-for-bears/<p>I was introduced to this smile-inducing website by Val Head’s An Event Apart Talk “Building more expressive projects”.</p>
<p>TunnelBear describes itself as “A more secure way to browse the web” and it does this by encrypting your internet connection to keep your online activity private on any network.</p>
<p>More interestingly to me, it succeeds at making a techy subject friendly by the use of illustrated and animated bears. And who doesn’t like bears?</p>
Chicago 20182018-09-02T15:36:00Zhttps://fuzzylogic.me/posts/chicago-2018/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1603638280/bc15350c-a925-4713-a184-ebf695582f14_olylnd.jpg" width="320" height="240" alt="Chicago, North River, by night" loading="lazy" decoding="async" />
<figcaption>Chicago, North River, by night</figcaption>
</figure>
<p>I just made a first visit to Chicago. It was primarily to attend <a href="https://aneventapart.com/">An Event Apart</a> but I was lucky enough to have a little time to check out the city, too.</p>
<p>Firstly I want to thank all the friends who provided tips for things to do and see in The Windy City – Aleks, Susan, Jenny, Lucy, Alan and Karen, Collette etc – cheers!</p>
<p>Thanks also to <a href="https://www.instagram.com/daviec7/">Davie</a> for jetting in from <abbr>NYC</abbr> to join me and <a href="https://twitter.com/liamjnugent">Liam</a> for a couple of days. I doff my cap to your knowledge of beautifully designed restaurants with really expensive menus 😉.</p>
<p>I also got the chance to catch up with old friend Nick Calingaert <abbr>AKA</abbr> <a href="https://www.discogs.com/artist/173-Common-Factor">Common Factor</a>, a lovely guy and talented producer who DJed for me and my friends at a couple of our club nights back in the early 00s.</p>
<p>We only had a few days, but I felt we managed to cram in some good stuff. Here’s a summary of the highlights.</p>
<h2 id="eating-out" tabindex="-1">Eating out <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#eating-out" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.swiftandsonschicago.com/">Swift & Sons</a></li>
<li><a href="https://www.momotarochicago.com/">Momataro</a></li>
<li><a href="https://www.chicagoathletichotel.com/restaurants/cherry-circle">Chicago Athletic Club</a> (with its appropriately posh tag-line “Dine and Libate”…)</li>
</ul>
<h2 id="bars" tabindex="-1">Bars <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#bars" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.facebook.com/pages/Dannys-Bar-Wicker-Park/292381780773679">Danny’s Bar</a></li>
<li><a href="https://www.chibarproject.com/Reviews/RainboClub/RainboClub.html">Rainbo Bar</a></li>
</ul>
<h2 id="record-shopping" tabindex="-1">Record Shopping <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#record-shopping" aria-hidden="true">#</a></h2>
<ul>
<li><a href="http://gramaphonerecords.com/">Gramaphone Records</a></li>
<li><a href="https://www.dustygroove.com/">Dusty Groove</a></li>
<li><a href="https://www.shugarecords.com/">Shuga Records</a>, 1272 N. Milwaukee Ave</li>
<li><a href="https://reckless.com/">Reckless Records</a></li>
</ul>
<h2 id="cool-neighbourhoods" tabindex="-1">Cool Neighbourhoods <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#cool-neighbourhoods" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.timeout.com/chicago/wicker-park-bucktown">Wicker Park area</a></li>
</ul>
<h2 id="culture-%2F-history" tabindex="-1">Culture / History <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#culture-%2F-history" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://architecturetourchicago.com/">Architecture Boat Tour</a></li>
<li><a href="http://www.artic.edu/">The Art Institute of Chicago</a></li>
</ul>
<h2 id="things-to-do" tabindex="-1">Things to do <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#things-to-do" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.tripsavvy.com/chicagos-millennium-park-1492258">Millenium Park</a></li>
<li><a href="https://millenniumparkfoundation.org/art-architecture/cloud-gate/">Cloud Gate (<abbr>AKA</abbr> The Bean)</a></li>
</ul>
<h2 id="and-if-we%E2%80%99d-had-more-time%E2%80%A6" tabindex="-1">And if we’d had more time… <a class="direct-link" href="https://fuzzylogic.me/posts/chicago-2018/#and-if-we%E2%80%99d-had-more-time%E2%80%A6" aria-hidden="true">#</a></h2>
<ul>
<li><a href="https://www.mlb.com/cubs/ballpark">Go see the Cubs playing baseball at Wrigley Field</a></li>
<li><a href="http://greenmilljazz.com/">Green Mill Jazz Club</a></li>
</ul>
Into The Outer feat. Other Lands, 27th October 2018 on NTS2018-09-01T13:51:02Zhttps://fuzzylogic.me/posts/into-the-outer-w-other-lands-firecracker-27th-october-2018-on-nts/<p>Magical sounds in the mix, from Auld Reekie’s finest.</p>
<p>Other Lands consistently plays amazing records.</p>
<p>He’s also been cultivating a quirky but cuddly radio voice which, combined with the heartfelt electronic sounds, makes for a warm and fuzzy listen.</p>
<p>This two hour show is notable for featuring lots of amazing music from Glasgow and Edinburgh, including tracks by Being, Lord of the Isles, a cut from the Off-World Transmissions LP on Invisible Inc, and a preview of the forthcoming Mac-Talla Nan Creag sequel on Firecracker.</p>
<p>Gav also plays both sides of <a href="https://fuzzylogic.me/posts/surface-noise">the new Nuclear Family EP</a> and I'm chuffed for our record to feature in this company.</p>
Namecheap2018-08-30T18:51:00Zhttps://fuzzylogic.me/posts/namecheap/<p>I’ve heard a couple of people mention that when they buy domain names, they use Namecheap because they are cheap and trustworthy. I tend not to have any particular favourites but I’ll maybe give Namecheap a go next time.</p>
Record Shopping at Gramaphone, Chicago2018-08-26T21:13:00Zhttps://fuzzylogic.me/posts/record-shopping-at-gramaphone-chicago/<p>When in Chicago, buy #house</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1603638115/86f73c36-e6c1-4f89-9a69-e59b6a9666f4_aw0nsm.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1603638115/86f73c36-e6c1-4f89-9a69-e59b6a9666f4_aw0nsm.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1603638115/86f73c36-e6c1-4f89-9a69-e59b6a9666f4_aw0nsm.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1603638115/86f73c36-e6c1-4f89-9a69-e59b6a9666f4_aw0nsm.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1603638115/86f73c36-e6c1-4f89-9a69-e59b6a9666f4_aw0nsm.jpg 1600w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1603638115/86f73c36-e6c1-4f89-9a69-e59b6a9666f4_aw0nsm.jpg" width="320" height="240" alt="Records and slipmats purchased from Gramaphone Records, Chicago, in August 2018" loading="lazy" decoding="async" />
<figcaption>My haul from Gramaphone Records, Chicago, August 2018</figcaption>
</figure>
DJ Gig at Max’s Bar, Glasgow with Jamie Porter (21-07-18)2018-07-23T09:43:00Zhttps://fuzzylogic.me/posts/dj-gig-at-maxs-bar-glasgow-with-jamie-porter/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1589137434/lhdjinginmaxsrecordskit_caamev.jpg" width="320" height="240" alt="Laurence’s record purchases in March 2020" loading="lazy" decoding="async" />
</figure>
<p>Jamie (<abbr>aka</abbr> <a href="https://twitter.com/burroughsbud">Bud Burroughs</a> of Stirling’s <a href="https://www.facebook.com/jrsscotland/">Jelly Roll Soul</a> crew) kindly invited me to DJ with him at <a href="http://maxsbar.co.uk/">Max’s Bar</a> last Saturday night (21st July ‘18).</p>
<p></p>
<p>We played from 9pm–3am. Max’s was rammed to the rafters as usual and it was fun to have six hours to play with, going through the gears and playing different styles and tempos. We also had some friendly faces for company – not only was it Jason Brunton’s birthday but we also had Chris Reid over from Italia and on the birras!</p>
<p>Music-wise, it was cool to mix on the <abbr>DJR</abbr>-400 and I particularly enjoyed playing <em>EXU</em>, the new one from Patrick Pulsinger & Irl:</p><p></p>
<div class="l-frame">
<iframe title="EXU by Patrick Pulsinger & Irl" loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/iZ2TgelxvtU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p>Jamie played lots of tracks I liked, including an upbeat version of <em>Space Jungle Luv</em> by Oneness-Of-Juju that I would post but can’t find anywhere!</p>
<p>Thanks to Jamie for the invite, and if you don’t already know his productions, check out:</p>
<ul>
<li><a href="https://www.discogs.com/Bud-Burroughs-The-Mail-Art-EP-/release/11579156">The Mail Art EP</a> by Bud Burroughs on Seventh Sign Recordings</li>
<li><a href="https://www.discogs.com/label/932277-Jelly-Roll-Soul">Jelly Roll Soul</a> record label</li>
<li><a href="https://www.discogs.com/Dam-Ru-Too-Many-Voices/release/11519804">Too Many Voices</a> by Dam-Ru on Temporize Recordings</li>
</ul>
Rubadub App2018-07-23T08:13:00Zhttps://fuzzylogic.me/posts/rubadub-app/<p><a href="https://www.rubadub.co.uk/">Rubadub</a> have a new mobile app that delivers the RaD crew’s top vinyl recommendations (the best around) direct to your phone.</p>
<p>At a time when lots of vinyl releases are highly limited, this gets you early access to the latest heat before it disappears. It should also generally save untold hours browsing/searching since in their recommendations Rubadub have already done the job of separating the wheat from the chaff.</p>
<p>The app was developed by me and the team at <a href="https://www.greenhilldigital.com/">Greenhill</a>.</p>
<p>It was quite tricky, because aside from developing the mobile app itself there was a lot of API work needed to integrate it with Rubadub’s stock and e-commerce systems. We also built middleware specifically for machine-learning customer tastes.</p>
<p>The current v1 app handles the core feature of letting people listen to, save and buy records but there’s a lot of cool stuff vis-a-vis personalised messaging and taste-based recommendations on the roadmap. <a href="https://www.greenhilldigital.com/portfolio/case-studies/rubadub-app">I’ve written about this in more detail over on Greenhill’s site</a>.</p>
<p>The long-term idea is that it becomes the app equivalent of the actual record shop experience...i.e. going into Rubadub on Howard St and one of the guys/gals handing you a pile of tunes with a side of witty repartee.</p>
<p>If you’re a vinyl junkie like me or into electronic music in general, I recommend checking it out.</p>
Stasiland2018-07-22T17:23:00Zhttps://fuzzylogic.me/posts/stasiland/<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1603637926/0e5885c4-546e-4a0f-a0c6-e1b570a153ce_hmicrw.jpg" width="320" height="240" alt="“Stasiland”, a book by Anna Funder" loading="lazy" decoding="async" />
</figure>
<p>I've just finished reading <em>Stasiland</em> by Anna Funder, having received the recommendation from a friend.</p>
<p>It tells a series of extraordinary and often heart-wrenching stories from the underbelly of the former East Germany. I thought it was fantastic and highly recommend it.</p>
Releasing early, releasing often… and avoiding paralysis by analysis2018-07-12T09:02:00Zhttps://fuzzylogic.me/posts/releasing-early-releasing-often-and-avoiding-paralysis-by-analysis/<p>My name is Laurence Hughes and I’m a perfectionist. But I’m working on it.</p>
<p>I’ve suffered from the painful affliction of perfectionism for as long as I can remember (I blame the mother…) and although I’m much better than I used to be, I don’t think it ever fully leaves you.</p>
<p>Good things undoubtedly come from <em>sweating the details</em>, but a perfectionist streak left unchecked can cause creative endeavours to take longer than they otherwise would, sucking out the initial spark and motivation.</p>
<p>A related affliction – and this particularly applies to coding – is spending so long considering the many different ways to tackle a problem that you end up at a temporary standstill… i.e. <em>paralysis by analysis</em>.</p>
<p>At work, developing software for <a href="https://www.greenhilldigital.com/">Greenhill</a>, the perfectionist streak is kept in check because we follow the <a href="https://en.wikipedia.org/wiki/Release_early,_release_often">release early, release often</a> philosophy and our development sprints just don’t allow time for it.</p>
<p><em>Release early, release often</em> works well when we’re building applications for clients because it leads to a tighter feedback loop between the customers, the client and ourselves; and also leads to new features being released more regularly.</p>
<p>On this, my own website, I’m going to take that principle further and hopefully release even earlier and more often.</p>
<p>So – things may look rough and ready or even broken (temporarily) when you visit this site now or in the future. And in this case I’m OK with that. This isn’t a client’s site – it’s mine. The <em>Minimum Viable Product</em> (or baseline before <a href="https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement">progressive enhancement</a>) is that visitors can read and navigate the content. Right now, at re-launch, it’s as simple as that. There’s no stylesheet as yet. It was more important for me to get the ball rolling than anything else. Hopefully as you read this, if the site in a state of flux (read: looks like a riot) you’ll still be able to enjoy the content! I have <a href="https://trello.com/b/3EObg1XV/fuzzy-logic-personal-site">plenty of nice features in the pipeline</a> but they’ll happen bit-by-bit, one step at a time.</p>
<p>This site is a work in progress – a bit like myself!</p>
Ampersand Conference 20182018-06-30T00:00:00Zhttps://fuzzylogic.me/posts/ampersand-conference-2018/<p>I’m just back from a fantastic couple of days in Brighton attending <a href="https://2018.ampersandconf.com/">Ampersand</a> – The Web Typography Conference – and also a Responsive Web Typography workshop with <a href="http://clagnut.com/">Richard Rutter</a> at <a href="https://clearleft.com/">Clearleft</a>.</p>
<figure>
<img class="u-full-parent-width" srcset="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_320/v1572430088/IMG-1997_fyqnjf.jpg 320w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1572430088/IMG-1997_fyqnjf.jpg 640w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_960/v1572430088/IMG-1997_fyqnjf.jpg 960w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1280/v1572430088/IMG-1997_fyqnjf.jpg 1280w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1600/v1572430088/IMG-1997_fyqnjf.jpg 1600w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_1920/v1572430088/IMG-1997_fyqnjf.jpg 1920w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2240/v1572430088/IMG-1997_fyqnjf.jpg 2240w, https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_2560/v1572430088/IMG-1997_fyqnjf.jpg 2560w" sizes="(min-width: 1600px) 646px, (min-width: 700px) 612px, 91.58vw" src="https://res.cloudinary.com/fuzzylogic/image/upload/q_auto,f_auto,w_640/v1572430088/IMG-1997_fyqnjf.jpg" width="320" height="240" alt="Attendees take their seats at Ampersand Conference 2018" loading="lazy" decoding="async" />
<figcaption>Attendees take their seats at Ampersand 2018</figcaption>
</figure>
Museum of the Moon at Mackintosh Queen’s Cross2018-06-23T19:36:00Zhttps://fuzzylogic.me/posts/museum-of-the-moon-at-mackintosh-queens-cross/<p>Today I and my brother Martin and two nieces Sophie and Mia, made a first visit to the <a href="http://www.mackintoshchurch.com/">Mackintosh Church</a> in Maryhill, Glasgow.</p>
<p>We were there to visit <em>Museum of the Moon</em>, a new touring artwork by UK artist <a href="https://www.lukejerram.com/">Luke Jerram</a>. I’d first heard about this exhibition when watching the BBC documentary <a href="https://www.bbc.co.uk/programmes/b09qjl7g"><em>Wonders of the Moon</em></a>.</p>
<p>The installation is a fusion of lunar imagery, moonlight and surround sound composition created by BAFTA and Ivor Novello award winning composer Dan Jones. Measuring seven metres in diameter, the sculpture features 120dpi detailed NASA imagery of the lunar surface. At an approximate scale of 1:500,000, each centimetre represents 5km of the moon’s surface.</p>
<div class="embed-container">
<iframe width="560" height="315" src="https://www.youtube.com/embed/3YDOmKezwsI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p>We all really enjoyed seeing this striking artwork in such a beautiful setting and learning a little more about the moon, too.</p>
A Dao of Web Design (on A List Apart)2018-06-14T11:51:17Zhttps://fuzzylogic.me/posts/a-dao-of-web-design-on-a-list-apart/<p>John Allsopp’s classic article in which he looks at the medium of web design through the prism of the <em>Tao Te Ching</em>, and encourages us to embrace the web’s inherent flexibility and fluidity.</p>
<blockquote>
<p>It’s time to throw out the rituals of the printed page, and to engage the medium of the web and its own nature.</p>
</blockquote>
<p>It’s choc-full of quotable lines, but here are a few of my favourites:</p>
<blockquote>
<p>We must “accept the ebb and flow of things.”</p>
</blockquote>
<blockquote>
<p>Everything I’ve said so far could be summarized as: <em>make pages which are adaptable</em>.</p>
</blockquote>
<p>…and…</p>
<blockquote>
<p>The web’s greatest strength, I believe, is often seen as a limitation, as a defect. It is the nature of the web to be flexible, and it should be our role as designers and developers to embrace this flexibility, and produce pages which, by being flexible, are accessible to all. The journey begins by letting go of control, and becoming flexible.</p>
</blockquote>
Grid by Example2018-06-04T10:17:00Zhttps://fuzzylogic.me/posts/grid-by-example/<p>Great resource from CSS Grid expert <a href="https://rachelandrew.co.uk/">Rachel Andrew</a>, with the <em>Patterns</em> and <em>Examples</em> sections which provide quick-start grid layouts being particularly handy.</p>
Meet the New Dialog Element2018-02-01T00:00:00Zhttps://fuzzylogic.me/posts/meet-the-new-dialog-element/<p>Introducing <code>dialog</code>: a new, easier, standards-based means of rendering a popup or modal dialogue.</p>
<p>The new element can be styled via CSS and comes with Javascript methods to show and close a dialog. We can also listen for and react to the show and close events.</p>
<p>Although currently only supported in Chrome, the Google Chrome dev team have provided <a href="https://github.com/GoogleChrome/dialog-polyfill">a polyfill</a> which patches support in all modern browsers and back to IE9.</p>
Using the tabindex attribute | TPG2017-08-04T00:00:00Zhttps://fuzzylogic.me/posts/using-the-tabindex-attribute/<p>Léonie Watson explains how the HTML tabindex attribute is used to manage keyboard focus. Of particular interest to me was a clarification of what <code>tabindex="-1"</code> does (because I always forget).</p>
<h2 id="tabindex%3D%22-1%22" tabindex="-1">tabindex="-1" <a class="direct-link" href="https://fuzzylogic.me/posts/using-the-tabindex-attribute/#tabindex%3D%22-1%22" aria-hidden="true">#</a></h2>
<p>The element becomes programmatically focusable but isn’t included in the tab order. It can’t be reached by someone using the tab key to navigate through content, but it can be focused on with scripting via the <code>focus()</code> method.</p>
<p>We might use this because we want to be able to set focus to a particular element via a script. Léonie offers the example of a list of form errors.</p>
<p>Alternatively we might use this because we want to prevent a normally tabbable element from being tabbable. <a href="https://aneventapart.com/news/post/practical-tips-for-building-more-accessible-front-ends">Sara Souidean uses this technique</a> (in combination with <code>aria-hidden=true</code>) on e-commerce product teaser “media objects” in order to limit the number of duplicate links that keyboard users must tab through.</p>
<h3 id="tabindex-on-page-targets-to-assist-with-keyboard-focus" tabindex="-1">Tabindex on page targets to assist with keyboard focus <a class="direct-link" href="https://fuzzylogic.me/posts/using-the-tabindex-attribute/#tabindex-on-page-targets-to-assist-with-keyboard-focus" aria-hidden="true">#</a></h3>
<p>I’ve often seen <code>tabindex="-1"</code> used as a companion to the <code>id</code> attribute on elements of a page intended to be directly accessible via links. Examples include a <code>main</code> element that should be directly accessible from a “Skip to content” link, or the headings in a blog article to support sharing direct links to page sections.</p>
<p>Before HTML5, creating an internal “link target” required creating an anchor element that used the <code>name</code> attribute. In HTML5 this use of anchor was deprecated with authors instead encouraged to add the <code>id</code> attribute to any element they wish. The reason why developers added <code>tabindex="-1"</code> to their <code>main</code> and <code>h2</code> (etc) “targets” is because some older browsers, when responding to a link to such a resource, would move visual focus to the target element (i.e. scroll to it) but not <em>programatically</em> set focus to it if the target element was not focusable. Including <code>tabindex="-1"</code> solved that problem.</p>
<p>Modern browsers move the focus correctly and so using <code>tabindex</code> for this purpose is no longer necessary.</p>
<h2 id="tabindex%3D%220%22" tabindex="-1">tabindex="0" <a class="direct-link" href="https://fuzzylogic.me/posts/using-the-tabindex-attribute/#tabindex%3D%220%22" aria-hidden="true">#</a></h2>
<p>Applying <code>tabindex="0"</code> to an element inserts it into the tabbing order based on its position in the source. It is not necessary to apply this to an interactive element such as a button or checkbox since they are focusable by default. You should use it sparingly (because it requires care to ensure accessibility) but you might use it on a custom element which needs to be interactive under certain circumstances such as <a href="https://inclusive-components.design/data-tables/">the horizontally scrollable container in a Data Table</a>.</p>
<h2 id="tabindex%3D%221%2B%22" tabindex="-1">tabindex="1+" <a class="direct-link" href="https://fuzzylogic.me/posts/using-the-tabindex-attribute/#tabindex%3D%221%2B%22" aria-hidden="true">#</a></h2>
<p>This imposes a tab order on the content that bears no resemblance to the expected tab order. It’s an antipattern. Don’t do it.</p>
The best way to Install Node.js and NPM on a Mac2017-01-19T00:00:00Zhttps://fuzzylogic.me/posts/the-best-way-to-install-nodejs-and-npm-on-a-mac/<p>In modern front-end development, we tend to use a number of JavaScript-based build tools (such as task runners like Gulp) which have been created using Node.js and which we install using NPM. Here’s the best way I’ve found for installing and maintaining Node and NPM on a Mac.</p>
<p>To install and use NPM packages, we first need to install Node.js and NPM on our computer (in my case a Mac).</p>
<p>I’ve found that although the <a href="https://nodejs.org/en/">Node.js website</a> includes an installer, using <a href="https://brew.sh/">Homebrew</a> is a better way to install Node and NPM on a Mac. Choosing the Homebrew route means you don’t have to install using <code>sudo</code> (or non-sudo but with complicated workarounds) which is great because it presents less risk of things going wrong later down the line. It also means you don’t need to mess around with your system <code>$PATH</code>.</p>
<p>Most importantly, it makes removing or updating Node really easy.</p>
<h2 id="installation" tabindex="-1">Installation <a class="direct-link" href="https://fuzzylogic.me/posts/the-best-way-to-install-nodejs-and-npm-on-a-mac/#installation" aria-hidden="true">#</a></h2>
<p>The whole process (after you have XCode and Homebrew installed) should only take you a few minutes.</p>
<p>Just open your Terminal app and type <code>brew install node</code>.</p>
<h2 id="updating-node-and-npm" tabindex="-1">Updating Node and NPM <a class="direct-link" href="https://fuzzylogic.me/posts/the-best-way-to-install-nodejs-and-npm-on-a-mac/#updating-node-and-npm" aria-hidden="true">#</a></h2>
<p>First, check whether or not Homebrew has the latest version of Node. In your Terminal type <code>brew update</code>.</p>
<p>Then, to Upgrade Node type: <code>brew upgrade node</code>.</p>
<h2 id="uninstalling-node-and-npm" tabindex="-1">Uninstalling Node and NPM <a class="direct-link" href="https://fuzzylogic.me/posts/the-best-way-to-install-nodejs-and-npm-on-a-mac/#uninstalling-node-and-npm" aria-hidden="true">#</a></h2>
<p>Uninstalling is as easy as running <code>brew uninstall node</code>.</p>
<h2 id="credits" tabindex="-1">Credits <a class="direct-link" href="https://fuzzylogic.me/posts/the-best-way-to-install-nodejs-and-npm-on-a-mac/#credits" aria-hidden="true">#</a></h2>
<p>This post was based on information from an <a href="https://blog.teamtreehouse.com/install-node-js-npm-mac">excellent article on Treehouse</a>.</p>