Crying Foul  

Elliot Condon, founder of the wildly popular Advanced Custom Fields plugin for WordPress:

The honest truth: WordPress 5.0 is not ready, and neither is ACF. Hats off to all the amazing web developers working on updates to their plugins, themes and client projects when they should be enjoying some well earned time off with family and friends. ❤️👨‍💻👩‍💻

That’s not something to celebrate.1


  1. It’s telling that Matt Mullenweg felt the need to respond. ↩︎

Goodbye, EdgeHTML  

Chris Beard, writing at the Mozilla blog:

Microsoft is officially giving up on an independent shared platform for the internet. By adopting Chromium, Microsoft hands over control of even more of online life to Google.

[…]

We compete with Google not because it’s a good business opportunity. We compete with Google because the health of the internet and online life depend on competition and choice.

There’s a minority of people who are concerned about Microsoft’s announcement. Everyone web developer I know who actually has to comply with browser standards is very happy to hear it though. In a perfect world, there would be one open source browser with 100% market share.

How to Turn Off macOS Mojave Screenshot Preview Thumbnails  

I’ve been intending to disable this ever since I upgraded to macOS Mojave. Today I finally found the time.1

The first thing I had to do was go to System Preferences -> Keyboard -> Shortcuts -> Screenshots and check the checkbox that says Screenshot and recording options, which was disabled apparently by default for whatever reason. After that, you can actually do the Shift-Command (⌘)-5 combo and follow the tutorial in Tek Revenue. (Its tl;dr is to simply un-select the Show Floating Thumbnail value in the screenshot utility options dropdown.)


  1. I logged 64 hours on my computer last week. Been busy! ↩︎

A Technical Explanation of How the `event-stream` Vulnerability Occurred  

Zach Schneider:

If you work with JavaScript at all, you probably saw a ton of noise yesterday about a vulnerability in the event-stream npm package. Unfortunately, the actual forensic analysis of the issue is buried under 600+ comments on the GitHub issue, most of which are just people flaming about the state of npm, open source, etc. I thought that was a shame, because the vulnerability was actually exceptionally clever and technically interesting, and teaches some important lessons about maintaining security in JavaScript applications. So I decided to write an explainer detailing what happened, how the attack worked, and how the JavaScript community can better defend against similar attacks in the future.

My bitcoin has lost 80¢ to the dollar since I bought it, so I don’t know why anybody would bother stealing it.1 But the technical write-up by Zach on exactly how the developer pulled this heist off is fascinating.


  1. Just kidding. I get it. Twenty cents is still twenty cents! ↩︎

How to Type a Non-Breaking Space on macOS  

It’s not obvious from looking, but in the HTML below, “Hello world” will be on one line even though there’s not enough room for it to all fit within the constrained body width:

<body>
  Hello world
</body>

<style>
body {
  font-size: 20px;
  width: 80px;
}
</style>

This is because the whitespace between “Hello” and “world” isn’t a normal whitespace. It’s a non-breaking whitespace. Normally when we want to write a non-breaking whitespace in HTML, we can do this with &nbsp; (and for reading clarity, this is the approach I recommend).1 But you don’t have to explicitly type out &nbsp;. You can type a non-breaking white space using the macOS key combination OPTION + SPACE and it will result in the same thing. If you load up the above HTML document in Chrome and inspect it, you can see in the Elements tab that it implicitly converts the space between “Hello” and “world” to &nbsp;.


  1. Or, if you want an entire line to be forced onto a single line, or if your content is dynamically coming from a database or elsewhere, you could also use white-space: nowrap;. ↩︎

How Much Are Walt Mossberg’s Old MacBook Airs Worth?  

It’s common knowledge that Walt Mossberg, in a disparaging fear that Apple would forever discontinue the MacBook Air, stocked up on a good 4-5 and stuck them in his closet for safekeeping a couple years back. He didn’t want to run the risk of ever being in a situation in which he did not have a working MacBook Air. His idea was that the stockpile should get him through the end of his life.

As soon as I heard the news that Apple was coming out with a new MacBook Air this year, I thought of Moss and those MacBook Airs in his closet. So did Kyle Leclair a week ago:

*opens closet*

Old MacBooks Air, your watch has ended.

Laf.

“Your Username Is OG. Do You Know What That Means?”  

Here’s a jaw-dropping blockbuster episode from Reply All. Stop what you’re doing and listen to it. And when you’re done, remove every 2FA you have that uses SMS. That sort of 2FA makes you much less safe than no 2FA whatsoever.

Bringing Experience to a Spec Fight  

It’s worth hearing this episode of Rene Ritchie and Tom Boger (Senior Director of Mac Product Marketing) just to hear Rene say this:

At a certain point Apple just decided to bring experience to a spec fight.

I assume that if product A has fewer specs than product B, it’s probably better, and it’s the one I want. I don’t even bother to seriously engage with people who come to the table with the presupposition that the spec checklist is the primary — or worse, the sole — determinant for which of two products is better. Bringing experience to a spec fight is equivalent to bringing a gun to a knife fight.

CSS Querying for Dark Mode in macOS Mojave  

Paul Miller:

Safari 12 that shipped with Mojave does not have a way to detect whether a user has a dark mode or not.

The good news is: Safari Tech Preview 68 supports Dark Mode! And Safari 12.1 might support it in a few months too. The CSS itself is very simple.

As soon as Safari supports this media query, I’m switching Drinking Caffeine to using this as the determinant for whether you get light mode or dark mode. Until then, you can adjust it at the settings page.

How to Have a Sticky Footer in Flexbox  

Last night I threw together a quick repo to show just how crazy simple it is to have a sticky footer in CSS. I also changed out the footer here on DrinkingCaffeine.com to use this method.

Rest in Peace, the Ryan Fait Sticky Footer. You served us well for nearly a decade.

Addy Osmani on the State of Javascript  

I watch very little video but I highly recommend these 13 minutes. My favorite part is when Addy mentions “React, Vue, AngularJS…” in that order. You can quibble over whether React or Vue should come first, but Angular is undeniably lagging third.

How to Sequentially Resolve a Group of Javascript Promises  

Save this link in your quiver. Learn its reduce algorithm, and never again use nested timeouts.

This:

setTimeout(() => {
  console.log('hello');

  setTimeout(() => {
    console.log('world');
  }, 1000);
}, 1000);

Becomes this:

const messages = ['hello', 'world'];

const promises = messages.map(message => () => new Promise(resolve => {
  setTimeout(() => {
    console.log(message);
    resolve();
  }, 1000);
}));

promises.reduce((promise, func) => promise.then(func), Promise.resolve());

This example looks silly (“you’ve introduced needless complexity!”) but when you have a large set of promises that need to be linearly resolved, you’ll be glad you had this.

Ills of the Graphics Interchange Format

The Graphics Interchange Format1 might be useful for people who love sharing cats and 3-second movie clips. These people certainly think they’re useful, and I won’t take that away from them. But they have no place in the professional developer environment.

In the building of UIs, it often becomes necessary to share a brief clip that demonstrates the user experience. When it comes to this, you have two choices: you can use a MPEG-4 Part 144 uploaded to a service like Screencast, or you can use the Graphics Interchange Format uploaded to a service like CloudApp. The former choice is the better one. The problems with the Graphics Interchange Format are legion. I’ll enumerate the more burdensome.

  1. It takes longer to begin watching a clip in this format than in a standard video format. The reason is because you must load the entire resource before you can begin it. There is no concept of “buffering” or “streaming.”
  2. Not only does it take longer, but because there is no “play” button, you are not in control of when it starts playing. The resource begins playing as soon as it is ready to do so, not when you are ready to do so. What this means is that you must sit there idly waiting for the resource, rather than doing something else whilst you wait. You dare not switch tabs because the file will begin playing at a time you think not.
  3. Likewise, because there is no “pause” button and no ability to scrub, if you want to revisit a certain piece of a 30-second clip, or if your impatience gets the better of you in the previous bullet and you miss the start, you must wait the duration of the clip. This is egregious.
  4. The determination of whether the file loops or not is determined by the creator of the file, not by the consumer of the file. More often than not, the author chooses to loop, which means you have a hideous distraction before your eyes after the first or second viewing.
  5. In order to avoid said distraction, Slack has made it possible to disable the animation of Graphics Interchange Format files in settings. Because of this, sharing such a file is no guarantee that the recipient will actually receive what the sender intended — they might instead receive a static image frozen on the first frame. On the contrary, when you share a proper video, you have a guarantee that the recipient gets what you sent and nothing less.
  6. The colors are limited.
  7. The frame count is limited.

The Graphics Interchange Format robs mankind of everything that is decent and noble in frame sharing. Do not use this format for professional use.


  1. You’ll pardon the verbosity. I’m still recovering from the use of acronyms during my 4-month stint earlier this year in corporate America. ↩︎

The Actual Purpose of the Document Base URL Element  

The only time I think I’ve seen the piece of markup below used in real life is in the context of a Single Page Application:

<base href="/">

What I hadn’t realized, until yesterday, is that if you’re at a page like this:

https://example.com/user/12335/edit

And there’s a relative image referenced in the DOM like this:

<img src="avatar.png">

Then that will normally resolve in an HTTP request to https://example.com/user/12335/edit/avatar.png but if you have <base> element defined like above, then that will resolve in an HTTP request to https://example.com/avatar.png. It’s always a funny feeling when you learn something fundamental about something you’ve been familiar with for ages but haven’t given any thought to.

The Tesla Model 3 Is the Top Selling Car by Revenue in the US  

It’s also the 5th best selling car by units. This is incredible when you consider that a Model 3 costing $10,000 less is coming out in early 2019. If the Model 3 is performing this well with a $45,000 starting price, what will it be then? Tesla has gone from being a company that sells cars to rich coastal elites to being a company that sells cars to average American consumer.

As I was driving to work today I was struck by how arbitrarily noisy the highway is. A day may come where that noise is looked upon as the mark of an era that came and went.

Because the average energy cost per mile of an electric car is a third the cost of a gas car, why wouldn’t you want to enjoy the higher precision of an electric motor when the up-front cost is comparable? It’s a objectively superior technology. Through irrefutable, unstoppable math, the automotive industry is getting disrupted in an way unparalleled since its inception. The Tesla Model 3 is to cars what the iPhone is to phones. Honda and Toyota, heretofore the defining American automotive staples, are the new Research In Motion.1


  1. (That’s RIM, the company behind the BlackBerry.) ↩︎

The iPhone Browser That Ignores Responsive Design  

When you long-press the reload button in Safari for iOS and select “Request Desktop Website,” all you’re doing is changing your user agent. This doesn’t do anything for most websites, because most websites offer their mobility via responsive CSS. Responsive CSS pays no attention to the user agent — instead it looks at the viewport width. And in Safari there’s no way to customize your viewport width. That’s where the Desktop Browser for iOS comes in. It somehow modifies things so responsive websites think you’re using a browser that’s wider than it really is. Desktop Browser might be achieving this by simply removing the viewport meta tag from the head of the document. That tag often looks something like this:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1" />

The more I think about it, that’s probably how Desktop Browser is achieving this.1 However it’s doing it, it works consistently, and I love it.


  1. When you visit a viewport revealer in Desktop Browser that programmatically shows your viewport width, it registers as the correct one (375 pixel width on an iPhone XS). That’s why I don’t think Desktop Browser is spoofing the viewport width. ↩︎

You Needn’t SCSS or LESS to Create CSS Variables  

I didn’t know about native CSS variables until this week. Internet Explorer doesn’t support them, but nobody cares about IE.1

The only real reason left to use SCSS or LESS is for scoping. But nested CSS isn’t the right solution to scoping. The real solution is having CSS that’s scoped or modularized by its very nature. If you’re using a JavaScript framework, you can approximate this with CSS Modules (e.g. here is its port to VueJS). But the long term solution is the Shadow DOM.

SCSS and LESS will be extinct in a decade.


  1. I get a rush when I see people building websites that bring IE to its knees in hopeless, permanent incompatibility. ↩︎

How to Adjust the Brightness of an External Display on macOS Mojave  

One of the glaring bugs of macOS Mojave’s initial release is that you can’t adjust the brightness of an external display using the brightness keys. Nor can you do it from System Preferences. But you can adjust it by downloading Brightness Slider from the App Store. It’s free and it works. Hat tip to Jreinhal.

The Essential Symbiosis of Algorithm and Heuristic

In his book Creative Selection, which I recommend very highly, Ken Kocienda talks about the importance of having software that takes heuristics into account. Much of computer software is algorithmically deduced. But not everything can be initially derived from algorithms. Some things require experimentation, trial and error, heuristic. Some of Ken’s examples:

  • Determining the proper size of icons on the iOS home screen so that they’re consistently tappable.
  • Determining how deep “pinch to zoom” should take you when looking at a photo.
  • Skewing the touch event to be higher than your touch’s placement so you feel like the tip of your finger is what interacted with the screen.

The only way to really get to these decisions is by heuristically using the software and finding what works best, and then extracting an algorithm from your findings. In addition to this, Ken said, “Sometimes we used heuristics to temper algorithms.” As an example, he talked about how they tweaked the auto-correction algorithm on the iOS keyboard to accommodate human behaviors and real-life situations that they hadn’t previously considered.

In contrast to this approach, we gaze upon the newly designed Pearsonified.com website, which continues to make heavy use of the Golden Ratio Typography Calculator and not much else. Chris has said, “I use math—not whimsy—to inform my designs.”1 But whimsy is just a despondent term for heuristic. What Chris is really saying here is this: “I have little patience for heuristic when determining web design.” The Golden Ratio Typography Calculator has always bothered me, frankly, because it tries to remove this essential heuristic ingredient from the equation.2 It blames anyone who comes up with their own typography numbers as “whimsical.”

I’m glad the iPhone wasn’t designed with this dogma. Life’s too short to use software that was built purely by heuristic-barren algorithms. Long live informed whimsy and the liberal arts.


  1. As of about a week ago, this oft-seen maxim at the old site is now only viewable at web.archive.org. Its underpinning ideology is still alive and well at the new site, however. ↩︎
  2. While I’m slaying sacred cows, I’ll go on the record for saying that the results don’t even look that good. The line height is invariably too much. ↩︎

Why Primitive Parameters Are Bad

Consider the following JavaScript function call:

fetchUser(true);

As you can see, we’re passing an argument of true. That’s a primitive type, and as such, it’s not clear what it’s doing. Now imagine if the referenced function were rewritten to take an object parameter instead. Calling it would then look something like this:

fetchUser({ forceReload: true });

This is much more clear. We can reasonably deduce that by passing true, we’re telling the code to ignore local cache and do a hard HTTP call to a server.

As a general rule, named parameters are better than simple boolean parameters. I’ve gotten to where I hardly ever write function definitions that have simple primitives as parameters, even if the function only has one parameter. Never underestimate the value of code readability.

A second reason why primitive parameters are bad is this: they make future extensibility harder. When it does come time to add a second parameter, you have to worry about changing the order of them. If you’re working with a team, you’ll soon be debating which parameters should come first. A lot of drama and intricacy can surround this. Usually developers want the most important parameters to go first. Once they’ve agreed on the order of importance, there’s still the debate about which parameters should have default values and which ones should be required. It especially gets messy if some of the more important parameters have logical defaults while some of the less important ones don’t. Once everyone’s finally agreed on how it should work in an ideal world, then there’s the debate about whether it’s worth refactoring every place that calls this method. Should you refactor, or just tack on the new parameter at the end with a default value as a less-than-ideal solution to avoid “busywork”? Remember, Chris has an unrelated work-in-progress branch that is touching this code a lot already, and he’d have to deal with a bunch of conflicts if the function signature were to get changed upstream. He’s ok with the change, but can it wait a couple weeks until his thing is done? There are so many opportunities for confusion and disagreement and frustration and subtle procrastination in all of this.

This whole debacle dissipates by simply using an object as your parameter. With named parameters, order doesn’t matter, because object properties are ordered alphabetically. And the best part? Thanks to object destructuring, you don’t even have to change the body of your function. If your function definition used to look like this:

const fetchUser = (forceReload = false) => {
  // function body that references `forceReload` boolean
};

It can now look like this:

const fetchUser = ({ forceReload = false }) => {
  // body remains unchanged
};

Never did an opening and closing bracket solve so many problems so effortlessly.

The Senseless Requirement for Having a Custom Avatar at the Apple Support Communities  

Roger Wilmut1, clarifying what it takes to upload a custom avatar in the Apple Support Communities:

You need to get to level 3 - 500 points: 50 ‘solved’ or 100 ‘helpful’ or a combination thereof. Welcome to the forums: I hope you enjoy answering peoples questions and hopefully gaining points (and karma) by helping them.

This is bonkers. I’ve never seen any other forum work this way. On Stack Overflow, an immensely more important website than discussions.apple.com, you get to use a custom avatar right out the gate. Same for every other major site I’ve ever seen.

I’m sure Apple has a reason for this restriction. There’s always a “good” reason, just like there’s always a perfectly rational explanation for walking around in white socks, crocks, cargo pants, and a fanny pack, with a side of wispy beard. But the fact that this problem has been solved by other communities proves that it doesn’t have to be this way. Apple should want as many people at its community to have custom avatars as possible. Default avatars are McDonald’s; custom avatars bring culture. It makes no sense to me why Apple restricts customer avatars to the 1%.

How to Hide Recent Apps From the Dock in macOS Mojave  

Until Mojave, if you quit an app that did not have “Keep in Dock” enabled, it disappeared from the dock immediately. Mojave changed that. Now it sticks around for a while. That’s irksome; I thought it was a bug until I realized it was a new Mojave feature. You can undo this feature by going into System Preferences -> Dock and disabling the checkbox labeled, “Show recent applications in Dock.” As a developer who builds new features for a living, I’m aware that developers love forcing their new code on users. But from a user’s standpoint, disruptive changes like this should be disabled by default.

Complexity

There will always be a reason why the complexity is needed; why it’s an improvement, how it helps things. We as developers are attracted to complexity like a magnet, like a bug attracted to a deadly electric zapper. It’s a rite of passage; complexity means we’re smart, that we thought of it, and that we can handle it. But every time we introduce complexity, we don’t realize until later the complications we’ve added with it. The edge case bugs. The half dozen oh-I-hadn’t-thought-about-that problems.

Sometimes complexity is the only way to achieve the desired result. But often it’s not. Often you have a choice. Choose to keep it simple.

SMS Not Working on Mojave  

User rhettf, writing at the Apple Support Community:

Since updating to Mojave, iMessage on Mac is no longer able to send or receive SMS messages. You get the red exclamation point. I tried signing out of iMessage on the Mac. And also toggling the Text Forwarding to device on the iPhone. Is anyone else experiencing this problem?

My experience is a bit more nuanced than this on Mojave. When I send a text message to an Android user from my Mac on macOS 10.14, the message goes through — the recipient receives it successfully. But the Mac doesn’t recognize this as occurring. It eventually shows an error in the form of a red exclamation mark, as rhettf describes. Moreover, when the recipient replies, I get the reply on my iPhone but I do not get the reply on my Mac.

In other words, on Mojave, sending an SMS technically works, but receiving does not, and neither of these things work from a UI standpoint.

Update: I found a fix that works for my computer. As you can tell in the link, a lot of people have this bug still so my solution isn’t the canonical answer, but it did fix it for me. SMS messages now forward correctly to my Mac on Mojave. The secret was signing out of Messages on the Mac (Messages -> Preferences -> iMessage -> Sign Out) and on my iPhone (Settings -> Messages -> Send & Receive -> Apple ID: {email} -> Sign Out). After that, I signed back in, taking care to use the same email address everywhere. Technically I have a total of 3 different email addresses associated with iCloud, all with the same account, but you have to log in using the primary email address everywhere, and then it works. If you’re not sure which is your primary email address, you can view it here. The reason that it appeared that this problem began occurring on Mojave is because somehow my email address for Messages got changed to a different one. Maybe I messed that up when upgrading to an iPhone XS. In fact in hindsight, I’m not sure if the problem was upgrading to Mojave or getting a new iPhone. I did them both just a few days apart.