Archive for February, 2019

2018 book review

In the spirit of last year’s blog post, this is an extremely belated round-up of books I read in 2018.

I read a lot of books last year. I chalk this up to many things, but quitting Twitter was probably a big one. Without Twitter, I actually run out of things to read on the internet. At some point the internet gets boring, and it’s nice to have a few books around to pick up the slack.

A photo of books on a bookshelf

A completely unstaged photo of my remarkably tidy bookshelf

To keep things simple, I’ll focus on the books I actually enjoyed, rather than the ones I thought were duds. Who wants to read about boring books, anyway?

So without further ado:

Quick links

Fiction

Non-fiction

Fiction

Life’s too short not to enjoy good fiction. I don’t read it often enough, but when I do find a good novel, it’s like a breath of fresh air. I can immerse myself in another world for a while, and try to empathize with its characters.

This year I didn’t read a lot of fiction, but what I did read was very good.

Theory of Bastards by Audrey Schulman (2018)

What a remarkable book. I read it because I got a sudden hankering for post-apocalyptic fiction last year, plus there was a review in The Economist.

This book definitely doesn’t disappoint on the post-apocalyptic front, but it’s also just a great piece of pop-science drama. It’s clear that the author did their research (about bonobos in this case) and developed the characters with a lot of care. Strongly recommended.

Three Weeks in December by Audrey Schulman (2012)

This book is a bit harder to find, but I found it’s every bit as good as Schulman’s other book. Some well-researched science, a bit of colonial history, and once again Schulman’s keen eye for character development (even if her protagonist bears a resemblance to the one from Bastards). I may just have to read everything Schulman’s ever written.

Blindness by José Saramago (1995)

Continuing the post-apocalyptic trend, this is a tightly-written drama that captures what’s best about science fiction: an understanding of how humans react when put into unfamiliar situations, for good and for evil. Also it’s written in one of the most unique styles I’ve ever read – breathless, using mostly commas, with hardly a period to stop the flow of action.

Apparently there’s a movie, but the reviews were bad so I didn’t watch it. The book is great.

A Canticle for Leibowitz by Walter M. Miller Jr. (1959)

I promise I didn’t just read post-apocalyptic fiction this year. In any case, this book is considered a classic, but I found it to be three thinly-connected novellas where only the first one is worth reading. If you get bored during the second one, I’d say skip it.

What’s great about this book is its understanding for how humans behave during a dark age. Knowledge gets lost or deliberately destroyed, history becomes myth, cult becomes religion. It’s chilling to imagine how that may happen to our own civilization.

Never Let Me Go by Kazuo Ishiguro (2010)

Last post-apocalyptic fiction, I promise. This one is pretty good, although you’re better off not reading any reviews or synopses so as to not spoil the premise.

Also, if you’re expecting something like The Remains of the Day, then you should know that Never Let Me Go is not only very different thematically, but I also found it didn’t linger in my mind as much as Remains did. Still, it’s worth reading.

Once again, there’s a movie, but I haven’t seen it. I have no idea how you would adapt a book like this into a movie, but I guess that doesn’t stop people from trying.

A Tale for the Time Being by Ruth Ozeki (2013)

Marvelous book. Maybe as someone who’s studied French and Japanese, and who lives in the Pacific Northwest, and who has developed a middling interest in Buddhism, the book also seemed to speak to me in a eerily precise way.

If you’re a fan of wordplay, inventive storytelling, and Murakami-style magic realism, this is a great book to pick up.

Cherry by Nico Walker (2018)

A strange, haunting, disturbing book, but also a page-turner. Apparently this is Walker’s first book, and it’s really a virtuoso performance. I’ll be interested to see what he comes up with next.

The New York Trilogy by Paul Auster (1987)

A bizarre book. You get the impression that Paul Auster had one story to tell, but he couldn’t decide how to do it, so he wrote the same story three ways. Somewhat like Canticle, you’re probably better off just reading the first one and skipping the others.

Still, it’s worth it, especially if you’re a fan of hard-boiled detective fiction and surrealism.

Non-fiction

As usual for me, I read a lot of non-fiction last year. For the purposes of this list, though, I’m skipping about half the books I read, because a lot of them didn’t have much new to say, or didn’t really stick in my mind.

So this list contains only books I would recommend. (Note: that doesn’t mean I agree with every sentence that the author has ever uttered. Which should be obvious, but hey, on the internet, you’re rarely given the benefit of the doubt these days.)

Sapiens (2014), Homo Deus (2017), and 21 Lessons for the 21st Century (2018) by Yuval Noah Harari

I first came across Harari in this excellent Atlantic article, and I quickly devoured all three of his books. I’m not really sure what to say, except that he’s one of the most clever, funny, and innovative thinkers writing today. Sapiens in particular is a masterpiece of history, anthropology, and political science.

Harari has upset my thinking on a lot of things – in particular, how technology interacts with democracy and citizenship to potentially upend the relationship between the individual and the state in the 21st century. I also found his portrayal of factory farming as one of the biggest moral failures in modern human history to be very compelling (and not just because I’ve been an on-again off-again pescetarian for years).

But probably the best thing I can say about these books is that they’re all page-turners, despite the dense subject matter. Also, Harari isn’t afraid to veer into controversy, but he’s always clear about where he gets the facts that inform his opinions. (His conclusion in Sapiens that, scientifically, we just don’t know why humans are a patriarchal species was refreshingly honest.)

Some of the best non-fiction I’ve read in my life, and definitely worth picking up.

The Mechanical Horse by Margaret Guroff (2016)

A joyous book, a celebration of the bicycle and its impact on American society. Even if you’re not a cyclist, you may find this book interesting, just to see how much a simple two-wheeled vehicle has reshaped our culture.

If you want a preview, you can take a look at this excerpt on how bicycles did, in Susan B. Anthony’s words, “more to emancipate women than any one thing in the world.”

Enlightenment Now by Steven Pinker (2018)

Everyone’s already reviewed, rebutted, and counter-rebutted this book to death during 2018, but I’ll toss my hat in the ring as well.

This is maybe the most important book I read last year.

In terms of non-fiction, I’ve spent the last few years mostly reading what my wife calls “tech is destroying the world” books. So my non-fiction diet is generally very dire and gloomy and focused on all the problems in the world (and, as a techie, how I’m partially complicit in it). Maybe it’s no surprise then that I tend to be pretty pessimistic in my outlook.

This book aims to destroy that mindset with cold-hard data. And the thing is, I can’t argue with most of his points. The world really has gotten better over the past few centuries, unless you want to refute dozens of meticulously-researched charts and graphs.

I’ve read some of the rebuttals, and most of them pick one or two points and try to skewer them to death, as if that invalidates the entire book. But the book is over 400 pages; you can’t take exception with one or two pages and then pretend that it invalidates the main sweep of his argument.

I still retain some skepticism that mankind can effectively tackle climate change, the transition away from fossil fuels, the drug epidemic (Pinker’s one graph that doesn’t slope in the good direction), or the decline of liberal values, but Pinker gives about a hundred reasons for optimism. So for that, I’m grateful.

Why Liberalism Failed by Patrick Deneen (2018)

Now here’s a truly radical book, and one that might serve as a good contrast to Pinker’s. Deneen’s argument is basically that liberalism (in the sense of “Western liberalism,” or “the Washington consensus,” or whatever you want to call it) has become a victim of its own success. It works so well to elevate the individual – as a consumer, as a liberated sexual being, etc. – that it rips apart families and communities in the process.

Deneen might look at Pinker’s book and say, “Okay, so we’ve got all the material comfort we could possibly want, but maybe the human soul needs something more than that?”

One thought that this book helped crystallize in my head, along with Identity by Francis Fukuyama (which I read and thought was just okay) and Why Buddhism is True by Robert Wright (which I started but didn’t finish) is that there’s a lot of wisdom to the Buddhist idea that suffering is caused by desire, and you can’t really address your suffering without addressing your desire.

Here’s Deneen:

“[H]uman appetite is insatiable and the world is limited. For both of these reasons, we cannot be truly free in the modern sense. We can never attain satiation, and will be eternally driven by our desires rather than satisfied by their attainment. And in pursuit of the satisfaction of our limitless desires, we will very quickly exhaust the planet.” (p125, hardcover)

Some of these arguments you may even call environmentalist. Others, like his critique of free markets, you might call anticapitalist. Despite broadly coming across as something like “radical reactionary paleo-conservative,” Deneen is hard to pin down.

I can’t really do this book justice by summarizing it here, as Deneen is such an original thinker that it’s best to let him explain his arguments himself. I don’t agree with him on everything, but I think if you want to understand the recent decline in liberal values, this book (as well as Edward Luce’s The Retreat of Western Liberalism, which I reviewed last year) would be a good place to start.

Thinking, Fast and Slow by Daniel Kahneman (2011)

This might be the second most important book I read last year (after Pinker’s). It’s a good overview of all the ways that our brains can fool us, and how statistical thinking can help reshape your perception of the world.

One part that stood out to me was the story of the Israeli flight instructor who would always criticize his students after a bad flight, and praise them after a good flight. And since a bad flight is usually followed by a better one, but a good flight is usually followed by a worse one, he concluded that criticism works, but praise doesn’t.

Kahneman points out that this is really just an expression of regression to the mean. If he had been berating his students on how high of a dice roll they got (“You got a six, stupendous!” or “You got a one, try harder!”) he would get exactly the same effect. The widespread belief in things like “streaks” and “hot hands,” though, shows how far most folks are from internalizing this basic statistical concept.

I’m sure this book hasn’t totally cured me of my monkey-brain misconceptions, but hopefully I’ll be able to catch a few more of them now.

Ten Arguments for Deleting Your Social Media Accounts Right Now by Jaron Lanier (2018)

Despite the snippy title, this is a well-thought-out and sobering book that puts a lot of recent social media controversies into perspective. I like how Lanier draws a line from Twitter and Facebook all the way back to old-school message boards.

This book has made me more skeptical of social media in general (even after deleting my Twitter account). If nothing else, reading this book is a good way to reflect on one own’s social media usage, and whether or not it’s a healthy relationship.

“Briefly I was one of the HuffPost’s top bloggers, always on the front page. But I found myself falling into that old problem again whenever I read the comments, and I could not get myself to ignore them. I would feel this weird low-level boiling rage inside me. Or I’d feel this absurd glow when people liked what I wrote, even if what they said didn’t indicate that they had paid much attention to it. Comment authors were mostly seeking attention for themselves.

We were all in the same stew, manipulating each other, inflating ourselves. (pp42-43, hardcover)

Atrocities by Matthew White (2011)

The funniest book about war, genocide, and famine that you’ll ever read. If it doesn’t sound like “funniest” belongs in the same sentence with those words, it’s best to pick up the book yourself to understand what I mean.

This book is not only well-researched and educational; it’s also a masterpiece of black humor that will make you gape and shake your head at the depths of human stupidity.

On Genghis Khan:

“Keep in mind that even with 16 million [living] descendants, Genghis Khan hasn’t replaced the number of people he killed.” (p115, 2013 edition)

On the Time of Troubles:

  • Location: Russia
  • Number of Dmitris: 4
  • Lesson learned: Always insist on seeing a photo ID before you proclaim someone emperor. (p207, 2013 edition)

There’s more, but I’d hate to spoil it by quoting it at length. In any case, it’s a hard book to put down, and a good conversation-starter to leave on a coffee table.

The Stranger in the Woods by Michael Finkel (2017)

A “strange but true” story about a guy who lived alone in the woods for 27 years. Pretty fascinating story, and a good meditation on what it means to live with other people, and why some might try to escape it.

The Blank Slate by Steven Pinker (2002)

I was intrigued by Pinker’s Enlightenment Now, so I picked this one up. It’s a bit older, but its core argument is still relevant. It does a great job of unmasking a kind of lazy thinking that denies any evidence from biology that might be politically inconvenient. (On both the left and the right, but I think Pinker focuses on the left because that’s his target audience.)

Something this book helped me realize is that, if I have a core political belief, it’s that evidence and facts matter. Unfortunately there’s a growing strain of thought across the political spectrum that emphasizes lived experiences, feelings, and political expediency at the expense of evidence and a shared set of facts. It argues that science is a tool of oppression, and “facts” are only useful for information warfare.

I can appreciate the anti-elitism and distrust of authority that motivates a lot of this thinking, but I also think it’s inherently dangerous. Science, reason, and liberalism have lifted a large chunk of humanity out of poverty and misery, and we abandon them at our own risk.

The Curse of Bigness by Tim Wu (2018)

In a year conspicuously absent of “tech is destroying the world” books on my bookshelf (or at least, on this list), this one stands out. It’s short, it’s sweet, and it captures our present tech moment very well by identifying the main problem as being a political one, rather than an economic or a technical one.

Essentially, this is a history of antitrust and anti-antitrust thinking. Wu’s other books (The Master Switch and The Attention Merchants) did a great job of tying together present trends with a history lesson, and this book offers more of the same. Well worth a read.

Living with Tinnitus by Laura Cole (2017)

This is a very personal inclusion on this list, but I’ll put it here anyway.

Last year I developed tinnitus, which means that I constantly hear a low, high-pitched buzzing in my ears. It affects a large number of people (10-15% of the population according to Wikipedia), but surprisingly few talk about it.

How did I get it? Probably from listening to too many podcasts on the bus without noise-canceling headphones. Or maybe an ear infection. To be honest, I’m not sure.

When it first developed, it was scary and frustrating. I went to an audiologist, but they just ran some tests, told me my hearing was fine, and sent me on my way with a short pamphlet on tinnitus. For several months it affected my sleep, my mood, and my social life, but I wasn’t really sure what to do about it.

Almost a year later, I can say that my tinnitus doesn’t really bother me at all, and I rarely think about it, even though it’s the first thing I hear in the morning and the last thing I hear at night. This book was one of the things that helped with that.

As it turns out, tinnitus doesn’t have a lot of research. Reading internet forums can just make you more scared, as the symptoms and severity can vary wildly. This book acknowledges the lack of evidence, but offers a wide range of potential solutions, mitigations, and coping mechanisms. The author is also very clear about which ones have strong evidence and which ones don’t.

If you or one of your loved ones has tinnitus, I’d strongly recommend this book.

Building a modern carousel with CSS scroll snap, smooth scrolling, and pinch-zoom

Recently I had some fun implementing an image carousel for Pinafore. The requirements were pretty simple: users should be able to swipe horizontally through up to 4 images, and also pinch-zoom to get a closer look.

The finished product looks like this:

 

Often when you’re building something like this, it’s tempting to use an off-the-shelf solution. The problem is that this often adds a large dependency size, or the code is inflexible, or it’s framework-specific (React, Vue, etc.), or it may not be optimized for performance and accessibility.

Come on, it’s 2019. Isn’t there a decent way to build a carousel with native browser APIs?

As it turns out, there is. My carousel implementation uses a few simple building blocks:

  1. CSS scroll snap
  2. scrollTo() with smooth behavior
  3. The <pinch-zoom> custom element

CSS scroll snap

Let’s start off with CSS scroll snap. This is what makes the scrollable element “snap” to a certain position as you scroll it.

The browser support is pretty good. The only trick is that you have to write one implementation for the modern scroll snap API (supported by Chrome and Safari), and another for the older scroll snap points API (supported by Firefox[1]).

You can detect support using @supports (scroll-snap-align: start). As usual for iOS Safari, you’ll also need to add -webkit-overflow-scrolling: touch to make the element scrollable.

But lo and behold, we now have the world’s simplest carousel implementation. It doesn’t even require JavaScript – just HTML and CSS!

Note: for best results, you may want to view the above pen in full mode.

The benefit of having all this “snapping” logic inside of CSS rather than JavaScript is that the browser is doing the heavy lifting. We don’t have to use touchmove listeners or requestAnimationFrame to try to get the pixel-perfect snapping behavior with the right animation curve – the browser handles all of it for us, in native code.

And unlike touchmove, this scroll-snapping works for any method of scrolling – touchpad, touchscreen, scrollbar, you name it.

scrollTo() with smooth scrolling

The next piece of the puzzle is that most carousels have little indicator buttons that let you navigate between the items in the list.

Screenshot of a carousel containing an image of a cat with indicator buttons below showing 1 filled circle and 3 unfilled circles

For this, we will need a little bit of JavaScript. We can use the scrollTo() API with {behavior: 'smooth'}, which tells the browser to smoothly scroll to a given offset:

function scrollToItem(itemPosition, numItems, scroller) {
  scoller.scrollTo({
    scrollLeft: Math.floor(
      scroller.scrollWidth * (itemPosition / numItems)
    ),
    behavior: 'smooth'
  })
}

The only trick here is that Safari doesn’t support smooth scroll behavior and Edge doesn’t support scrollTo() at all. But we can detect support and fall back to a JavaScript implementation, such as this one.

Here is my technique for detecting native smooth scrolling:

function testSupportsSmoothScroll () {
  var supports = false
  try {
    var div = document.createElement('div')
    div.scrollTo({
      top: 0,
      get behavior () {
        supports = true
        return 'smooth'
      }
    })
  } catch (err) {}
  return supports
}

Being careful to set aria-labels and aria-pressed states for the buttons, and adding a debounced scroll listener to update the pressed state as the user scrolls, we end up with something like this:

View in full mode

You can also add generic “go left” and “go right” buttons; the principle is the same.

Hiding the scrollbar (optional)

Now, the next piece of the puzzle is that most carousels don’t have a scrollbar, and depending on the browser and OS, you might not like how the scrollbar appears.

Also, our carousel already includes all the buttons needed to scroll left and right, so it effectively has its own scrollbar. So we can consider removing the native one.

To accomplish this, we can start with overflow-x: auto rather than overflow-x: scroll, which ensures that at least if there’s only one image (and thus no possibility of scrolling left or right), the scrollbar doesn’t show.

Beyond that, we may be tempted to add overflow-x: hidden, but this actually makes the list entirely unscrollable. Bummer.

So we can use a little hack instead. Here is some CSS to remove the scrollbar, which works in Chrome, Edge, Firefox, and Safari:

.scroll {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.scroll::-webkit-scrollbar {
  display: none;
}

And it works! The scrollbar is gone:

View in full mode

Admittedly, though, this is a bit icky. The only standards-based CSS here is scrollbar-width, which is currently only supported by Firefox. The -webkit-scrollbar hack is for Chrome and Safari, and the -ms-overflow-style hack is for Edge/IE.

So if you don’t like vendor-specific CSS, or if you think scrollbars are better for accessibility, then you can just keep the scrollbar around. Follow your heart!

Pinch-zoom

For pinch-zooming, this is one case where I allowed myself an indulgence: I use the <pinch-zoom> element from Google Chrome Labs.

I like it because it’s extremely small (5.2kB minified) and it uses Pointer Events under the hood, meaning it supports mobile touchscreens, touchpads, touchscreen laptops, and any device that supports pinch-zooming.

However, this element isn’t totally compatible with a scrollable list, because dragging your finger left and right causes the image to move left and right, rather than scroll left and right.

 

I thought this was actually a nice touch, though, since it allows you to choose which part of the image to zoom in on. So I decided to keep it.

To make this work inside a scrollable carousel, though, I decided to add a separate mode for zooming. You have to tap the magnifying glass to enable zooming, at which point dragging your finger moves the image itself rather than the carousel.

Toggling the pinch-zoom mode was as simple as removing or adding the <pinch-zoom> element to toggle it [2]. I also decided to add some explicit “zoom in” and “zoom out” buttons for the benefit of users who don’t have a device that supports pinch-zooming.

 

Of course, I could have implemented this myself using raw Pointer Events, but <pinch-zoom> offers a small footprint, a nice API, and good browser compatibility (e.g. on iOS Safari, where Pointer Events are not supported). So it felt like a worthy addition.

Intrinsic sizing

The last piece of the puzzle (I promise!) is a way to keep the images from doing a re-layout when they load. This can lead to janky-looking reflows, especially on slow connections.

 

Assuming we know the dimensions of the images in advance, we can fix this by using the intrinsicsize attribute. Unfortunately this isn’t supported in any browser yet, but it’s coming soon to Chrome! And it’s way easier than any other (hacky) solution you may think of.

Here it is in Chrome 72 with the “experimental web platform features” flag enabled:

 

Notice that the buttons don’t jump around while the image loads. Much nicer!

Accessibility check

Looking over the WAI Carousel Concepts document, there are a few good things to keep in mind when implementing this carousel:

  1. To make the carousel more keyboard-navigable, you may add keyboard shortcuts, for instance and to navigate left and right. (Note though that a scrollable horizontal list can already be focused and scrolled with the keyboard.)
  2. Use <ul> and <li> elements instead of <div>s, so that a screen reader announces it as a list.
  3. The smooth-scrolling can be distracting or nausea-inducing for some folks, so respect prefers-reduced-motion or provide an option to turn it off.
  4. As mentioned previously, use aria-label and aria-pressed for the indicator buttons.

Compatibility check

But what about IE support? I can hear your boss screaming at you already.

If you’re one of the unfortunate souls who still has to maintain IE11 support, rest assured: a scroll-snap carousel is just a normal horizontal-scrolling list on IE. It doesn’t work exactly the same, but hey, does it need to? IE11 users probably don’t expect the best anymore.

Conclusion

So that’s it! I decided not to publish this as a library, and I’m leaving the pinch-zooming and intrinsic sizing as an exercise for the reader. I think the core building blocks are simple enough that folks really ought to just take the native APIs and run with them.

Any decisions I could bake into a library would only limit the flexibility of the carousel, and leave its users high-and-dry when they need to tweak something, because I’ve taught them how to use my library instead of the native browser API.

At some point, it’s just better to go native.

Footnotes

1. For whatever reason, I couldn’t get the old scroll snap points spec to work in Edge. Sarah Drasner apparently ran into the same issue. On the bright side, though, a horizontally scrolling list without snap points is just a regular horizontally scrolling list!

2. The first version of this blog post recommended using pointer-events: none to toggle the zoom mode on or off. It turns out that this breaks right-clicking to download an image. So it seems better to just remove or add the <pinch-zoom> element to toggle it.