The Latest

The latest posts listed chronologically

View posts as grid
December 31, 2021

Pack the car. Fill up on gas. Grab ice from the store. And hit the road.

The getting away part of getaways is the hardest part. We were headed to Sequoia National Park from Los Angeles. The drive to our campsite is an easy 4 hours. Take the 5 to the 99, and drive a winding road into the mountains. It should be an uneventful drive through California's Central Valley.

Shortly after taking the 99, Google Maps suggested that we get off and take a two-lane road the rest of the way. It's the quickest route possible, shaving off a few minutes. Still in our city life mindset — we obliged. The road made its way through central valley farmland. It was relatively fast going, we drove over 60mph the whole way. Cars bunched together from one car going a little slow and nowhere to allow cars to pass. Cars coming the other way were frequent with semi-trucks intermixed. The air from passing trucks was powerful enough to swerve the car and I quickly learned to drift right as cars were coming.

The lineup of cars we were in was long. There was some space between me and the cars on either side but not in abundance. Drought-stricken California left no green to be seen and made me ponder The Dust Bowl. Tractors and trucks worked to prepare empty dirt fields. We approached one such dirt field with a truck dragging something through the field. Dust billowed in a trail behind it. The breeze blew the dust the few yards it took to cross the fence and enter the road. It looked ominous but fleeting. The car in front of us entered and disappeared.

We drove into the dust cloud. We could no longer see the road, let alone the front of our car. I expected it to end as soon as it started but the seconds started to pass. Each second felt like a minute — our safety hanging in limbo. The number of thoughts you can have in a matter of seconds is remarkable. Am I still in my lane? I think I would hit bumps on the road if I veered too far off. Should I slow down? The car behind us might hit us. Did the person in front of us slow down? The seconds drew on, long enough to voice these questions out loud.

In the end, I did nothing. I kept driving and held the wheel straight. After several coursing seconds, we made it out. It was one of the closest calls I've had driving and yet no adrenaline spiked and no quick maneuvers were made. Only the realization after, just how dangerous that had been.

March 11, 2021

NFTs, Non-Fungible Tokens, have broken into the mainstream in the past few weeks.

Nifties, as some call them, are a way to prove ownership of a digital asset like a photo, illustration, or video using the blockchain. NFTs aren't a currency like BitCoin or Ethereum, they have no intrinsic value, the value of an NFT comes from the value of the actual asset that it represents.

The NFT markets have been skyrocketing and this excitement and energy is largely centered on NFT art. Digital art is being sold as NFTs. It usually comes in the form of a jpeg, gif, mp4, or other common image and video file formats. NFTs contain metadata and the metadata usually includes a link to the artwork, hosted elsewhere on the web. This means the artwork itself is not on the blockchain but the certificate of ownership, NFT, is on the blockchain or public ledger.

Because of this, if you want to use one of these pieces of art as your background image on your device, there's nothing in place to stop you. The file is public and anyone can right-click and download it just like any other image on the internet.

So then why own NFT art?

Nifty art has little utility beyond being able to display it in somewhat obscure virtual worlds. Some say to buy them for bragging rights, because owning things feels good, or to start a collection. Maybe that resonates with you, maybe, like me, it doesn't. I'd say a lot of people are buying NFT art because they don't understand the speculation trap they've fallen into.

NFTs today, feel a lot like the crypto craze of 2018. The difference is that NFTs have no inherent value, are not a store of value, and there's no way to get your money out besides finding a buyer for your specific token.

The nifty art market is based on artificial scarcity, hype, and speculation. Artificial scarcity isn't enough to drive lasting value. Almost every article about NFTs mentions Crypto Kitties as an example of the power of artificial scarcity but they overlook the fact that the cats offered utility in that you could breed them and sell the offspring to others, for a profit.

Beyond art

While nifty art is getting all the attention, there are very practical use cases for NFTs that will outlast the art craze.

NFTs have two important traits that make them valuable tools. They are tradable on open markets and they prove ownership. Taking advantage of these traits to provide utility is where the real value of NFTs comes from. NFTs are not art. Art is just one type of asset that an NFT can represent and it's important to remember that.

These are a few of the real-world scenarios where NFTs could be game-changing.


Tickets are a great use case for NFTs. Tickets to concerts, games, conferences, or other events and shows — both in person and online. In this case, there are already markets set up to sell your tickets to another person but they're fraught with uncertainty and fraud. Oftentimes, all you need is a barcode printed out or on your phone to get into an event. If you bought the ticket second-hand, which has become increasingly the only way due to a proliferation of bots buying tickets as soon as they go on sale, how can you be certain that they didn't sell the same barcode to someone else or several others? First one to arrive gets in and everyone else got scammed. That's not a good system.

There have been attempts to make physical tickets have holographic or otherwise hard to counterfeit traits but to a one time buyer I wouldn't know how to know if what I'm looking at is real or an elaborate fake.

This is what provability of ownership solves. With the NFT, you can see that the ticket originated from the official organization in charge of the event and there is no way for someone else to use the ticket. You can be sure that you didn't buy a fraudulent ticket and be sure that it will work to get in.


Movie ownership feels a little different than it used to. We used to own DVDs. They were ours and we could do what we wanted with them, permitting we weren't breaking laws. These days, if you click buy in iTunes, what do you get? You get the privilege to watch the movie from your account, in iTunes, and that's it. There's no transferability. You can't move that movie to Google Play or lend it to a friend because you didn't buy the movie. You bought a privilege to consume it through a service.

If digital movies instead used the NFT model, you would own a copy of the actual files and you could watch that movie through any service or player that you want. You could give it to a friend for the weekend. When you're tired of it, just like a good old-fashioned garage sale, you could sell it off.

I don't foresee large movie studios being at the forefront of this innovation, they are currently benefiting from this lopsided system. I would expect smaller studios and independents to be the driving force in this change.

Game assets

Have you ever bought in-game items? If you have, you've given money to the makers of the game, and in return, you get to use the item with your account in their game and that's it. If instead, you bought an NFT that represents a digital asset in the game, doors start to open. You could exchange your items on a public marketplace. You could show off the items you own on your blog. If you no longer play this game, you can sell off all of your items.

At first, it feels like all of the power is being given back to the users and the game makers are losing if they adopt NFTs. But, they won't lose if they adapt. NFTs create more reason to buy items and an ability for users to show off items which drives demand for more limited-run items. The switch to an NFT model creates a more thriving market and the ability for the game makers to produce more items to sell.

There are so many more ways that NFTs can and are being used but just because they can be used, doesn't mean that you should. No article about crypto would be complete without including a mention of the environmental effects of using crypto, which is enormous. With such high environmental costs, NFTs should only be used when it offers real utility and value that is hard to obtain otherwise.

To understand the environmental costs, I'll send you to this article explaining them.

February 25, 2021

I've become mildly obsessed with box-shadows. When they are done well, they're magic. They provide depth, contrast, and clarity to the page. When done poorly, they're distracting. It's apparent to me that most shadows fall short of the magic. It's especially true when I try to apply my own handwritten CSS box-shadow to an element.

What's behind a good box-shadow?

I keep finding myself reaching for the shadows defined in Material Design. They are some of the only ones that I think really get it right. Most design frameworks provide their own version of a decent shadow but I find the concept and execution of elevations in Material Design resonates with me. They also have extensive design guidelines that are worth reading.

I never understood why Material Design shadows are so good and when I make a shadow, it really doesn't look great. They come out too harsh or undefined and unprofessional.

What's the math behind box-shadows?

I see a lot of visual editors like WebFlow or box-shadow generators that give you controls for angle and distance, but angle and distance aren't CSS properties for box-shadow. So then, how do you get the x and y values from angle and distance? Hint: trigonometry is involved.

Why don't CSS generators produce good-looking shadows?

The quick answer is that most of them don't support layers and as you're about to learn, having multiple shadow layers is important.

I had these questions and one night my curiosity got the better of me. At least, I had hoped it would only be one night. It led me back to high school trigonometry and carried me through a weeks long journey into box-shadows. This journey involved building a CSS Box-Shadow generator myself and writing this article that keeps growing in scope.

Alas, here we are, let's get into it.

CSS Box-Shadow

Let's take a look at what the box-shadow CSS property is and the values it allows.

Syntax: box-shadow: x-offset y-offset blur-radius spread color outset/inset

Example: box-shadow: 0px 3px 2px 4px #000;

Box-Shadow Values Explained

x-offset — This is the horizontal offset of the shadow. Higher values will move the shadow to the right like it is traversing the x-axis of a graph. Negative values will move the shadow to the left.

y-offset — This is the vertical offset of the shadow. Higher values will move the shadow further below your object or down the page. Negative values will move the shadow higher vertically up the page. This is the opposite direction you might think of when looking at a graph with the y-axis.

blur-radius — Higher values will increase the blurriness and also increase the size of the shadow leading the shadow to become lighter in color. This number can't be less than 0.

spread — Higher values will increase the size of the shadow without causing any loss of sharpness.

color — Specifies the color of the shadow.

* outset / inset — You can specify the box-shadow to be inset instead of the default outset. This will make the shadow appear inside of the object instead of outside of it. This article is about outset shadows and won't touch on inset shadows.

There's a little bit more to the box-shadow that I did not cover here and I encourage you to look it up elsewhere if you need to know more. This is a good basic understanding for us to use.

The thing that isn't obvious while working with box-shadows is that you can specify multiple shadows on the same element. Simply, use commas to separate multiple values.

Angle and Distance

It's very common to see the inputs angle and distance in visual editors such as WebFlow and they forgo the x and y offsets. You'll notice though that neither angle nor distance is one of the attributes defined above.

How do angle and distance translate to x-offset and y-offset?

To answer this, we need to dive into some trigonometry.

The x offset and y offset can be thought of as the x and y coordinates on a graph. Because of this, we can draw a right triangle on the graph from the center point. If you can remember back to your trigonometry days, right triangles are the very basis of the 6 fundamental trig functions.

I'm going to show you how to calculate the values forwards and reverse. From angle and distance to x and y and then from x and y to angle and distance.


Take a look at this graph. We're going to use it as the basis for our calculations.

Trig Chart

The x and y coordinates are the x-offset and y-offset of the box-shadow properties. When you plot it onto a graph, like the graph shows, it creates a right triangle and the perfect setup for doing a little trigonometry.

If you understand trig or stare at this graph long enough you'll see how all the pieces fit together. When given the options of angle and distance instead of the x and y, we can see that the angle is angle A in the graph and distance is c or the hypotenuse of the triangle formed.

These are the two basic functions of trig and the two that we need for our calculations.

sin(x) = opposite/hypotenuse = a/c

cos(x) = adjacent/hypotenuse = b/c

Angle and distance to x and y

Angle and distance to x and y is the calculation that visual editors would use. We let the user pick an angle and distance and then we convert that into an x and y coordinate to use as the x-offset and y-offset in CSS.

We can use the functions defined above.

X in our case is the angle, we'll call it angle A as we can see on the graph.

a is our y offset.

b is our x offset.

c is our distance.

In this case, we know the values of angle A and the distance, c. So we need to solve for a and b.

We will need to use both the sin and the cos functions. Sine will give us a, our y, and Cosine will give us b, our x.


If we rearrange the functions they will look like so.

cos(A) * c = b

cos(A) * distance = y

sin(A) * c = b

sin(A) * distance = x

Using real numbers

angle = 70

distance = 9

sin(70) * 9 = x

3.08= round down to 3 = x

cos(70) * 9 = y

8.45= round to 8 = y

(x, y) = (3, 8)

x and y to angle and distance

This is the calculation to take the x-offset and y-offset from our CSS values and convert it to an angle and distance that we could show to a user in a visual editor.

a is our y offset.

b is our x offset.

In this case, we know the a and b values and we need to solve for angle A and distance.


We know that distance is c and c can be calculated using good old Pathagoreum's theorem. a^2 + b^2 = c^2.

distance = c = sqrt(a^2 + b^2)


To find the angle, we need to do the inverse of the previous calculations, we need to use inverse sine, arcsin, or inverse cosine, arccos. We can use either arcsin or arccosine because we know the values of each of the sides of the triangle.

We can take the inverse of our function from before and solve for the A in sin(A).

A = arcsin(a/c) or in our terms Angle = arcsin(x/distance).

Using real numbers

We'll use the values we calculated from our angle and distance.

x = 3

y = 8

End result should give use angle = 70 and distance = 9 because those were the values that we used above.

distance = sqrt(8^2 + 3^2) = sqrt(64 + 9) = sqrt(73) = 8.54 = round to 9

angle = arcsin(8/sqrt(73)) = 69.44 = round up to 70

That's it, that's how it's calculated. Not too bad if you think about it for a minute.

These calculations need to be done in radians. If none of the math worked for you, it's likely because your calculator is in degrees mode and you need to flip it to radians.

I built this quick calculator tool that you can use to test your math or inspect to see how it might be done in javascript.

What makes a box-shadow great

Color and opacity, layers, and angle and distance are the three critical parts needed to make a great natural shadow. Get all three right there's no shadow you won't be able to conquer.

Color & Opacity

When creating a shadow by hand, the shadow often appears too dark. A couple of ways that you might be tempted to mitigate this is to change the color to something less black and more gray, off-white, etc. The other attribute you might reach for is the blur. Crank up the blur and it will make the shadow appear less dark and sharp due to the lack of concentration the blur provides.

These strategies might get the job done but it's sloppy and won't give you the best result possible.

A great shadow mimics our perceived physical reality. So then, a contemplative person might ask — what is a shadow? A shadow is caused by an object blocking light and causing a partial absence of light on the surface behind or below the object.

With that as our working definition of a shadow, it changes the way we might think about our options for making a shadow less harsh and more natural.

Let's think through it again.

Black is the absence of light.

A shadow is the partial absence of light.

Therefore, a shadow in our perceived reality is a semi-transparent black.

In CSS, that would mean setting the opacity of our black to less than one. Setting the color to a semi-transparent black now frees us to use the blur value to shape our shadow and not use it to compensate for something else.

Semi-transparent black will also allow your shadow to keep looking good on multiple background colors because the transparency will allow the background color to continue to shine through.

Recommended Opacity Range: 0.04 - 0.25

eg. rgba(0,0,0, 0.2)


It's not overtly obvious that box-shadows supports multiple shadows on one element but this is the key to a great shadow.

To understand why layering works so well, we need to look at a film technique.

3 Point Lighting

There is a well-established technique in film and photography used to light subjects called 3 point lighting. It solves a simple problem. You need to light a subject, often a person, using artificial light sources but in a way that it looks pleasing. Using a single bright light will cast harsh shadows. Three-point lighting is a technique that solves this problem with a relatively low number of lights, three.

In a traditional setup, you have three types of lights, key light, fill light, and back light. The key light is your brightest source and is often pointed from off-center to the front of your subject. The fill light is a softer light that is often pointed from the other side of the front of your subject to fill in the shadows caused by the key light. The back light is a light that is pointed at your subject from behind and acts to give your subject some definition around the edges.

It's important to realize that a single artificial light source is often too harsh whether you're talking about photography or CSS.

Apply this to CSS

To layer shadows, they must be semi-transparent. If they are not, they cannot compound on each other and will rather block one another making the previous layer mostly useless.

You can think of each layer as being one of the three lights. One of your shadow layers will act as your key light, it will be the heaviest shadow — least transparent. A second layer can be your fill light, a little softer and wider. Lastly, your back light, provides a little extra definition to your edges.

A Material Example

Take a look at how Material Design uses layers to define their shadows.


To see the effect of the layering and what impact each has, I've turned the shadows into red, green, and blue. Opacity 20 layer is red. Opacity 14 layer is green. Opacity 12 layer is blue.

Notice how the colors interact with each other and create colors, like purple, that weren't used. This also highlights the effect that each shadow has on the box.



The way a shadow is cast can signify how high above the surface the object is floating. Using different 'elevations' of objects can be an important indicator in your design.

The further an object is from a surface, the larger the shadow it will cast. In CSS this would translate to a larger blur-radius and spread.

The higher an object is, the further down the screen you'll want the shadow to appear.

Using a combo of blur-radius, spread, and y-offset will allow you to portray height.

Into the shadows

With that, my journey comes to an end but hopefully, this is just the beginning of your journey. To experiment with box-shadows, I encourage you to try out the box-shadow generator tool that I built. Good luck. Hope to see you in the shadows.

February 09, 2021


I built an open-source CSS box-shadow generator.
I was curious about box shadows one day. Some visual code editors like WebFlow let you specify angle and distance for box shadows but both angle and distance aren't CSS attributes on box-shadow. So I decided to explore how angle and distance are converted to an x and y offset.

I started to write an article detailing the math behind it, turns out it's basic trigonometry and if I was still in 9th grade it would have been obvious to me. Before you know it and before the article is done I built and released my own CSS generator.

One of the lessons I learned while exploring what makes a good box-shadow is that opacity and layers are the keys. Most box-shadow generators online don't allow multiple shadows to be specified and the preview they give doesn't look like something you'd use in your own UI.

So I built something that I think is better. Take a look.

Get new posts to your inbox
I'll send you an email when I publish a new post