Why isn’t `0` a valid time value in CSS?
Tags: css
Published: 2020-02-22 05:30:30

If you’ve ever written a CSS transition property like the one below: 

```css
.a {
    transition: translate 0 ease-out 0; 
}
```
You’ll notice that Devtools informs you that the CSS is invalid.

Rewrite that line adding the `ms` unit after the zero: 

```css
.a {
    transition: translate 0ms ease-out 0ms; 
}
```

And the CSS is fine and dandy.

## So what’s the difference between `0` and `0ms`?

The first value is a plain, unitless number (and let’s agree that zero is in fact a [real](https://www.quora.com/Is-the-number-zero-considered-a-real-number) number). In the CSS specification, numbers are referred to as **numeric data types**. The [numeric data types](https://www.w3.org/TR/css-values-3/) in CSS include the following: 

- `<length>` type - (`px`, `em`, `rem` ...there’s a tonne)  
- `<angle>` type - (`deg`, `grad`, `rad`, `turn`)
- `<frequency>` type -  (`Hz`, `kHz`)
- `<resolution>` type - `dpi`, `dpcm`, `dppx`

## On Zero

But the unitless zero isn’t mentioned in any of those! The only mention of zero in the specification is a **single line** regarding length units:

> For zero lengths the unit identifier is optional (i.e. can be syntactically represented as the [\<number\>](https://www.w3.org/TR/css-values-3/#number-value) 0).

— [CSS Values 3, lengths](https://www.w3.org/TR/css-values-3/#lengths)

So this implies that **you can only use a unitless Zero as a [\<length\>](https://www.w3.org/TR/css-values-3/#lengths) unit**. Ok... but why is that the case? 

## A bit of history

To understand why the unitless zero is only valid for length values and not others, we have to go beyond the spec and read some of the conversation around it. 

Luckily, W3C conversations around the specification are all transcribed and recorded on public mailing lists. Here’s part of a meeting of the CSS Working Group from [March 2016](https://lists.w3.org/Archives/Public/www-style/2016Mar/0205.html): 

> **glazou**: From author's perspective, **0 is 0 and you don't need a unit**.
  **glazou**: Did consider in the past.
  **glazou**: Same argument for 0 vs 0px.
  **glazou**: Should we make the same choice today?
  **glazou**: Isn't 0 the same as 0deg?

And here’s another one [from April 2017](https://lists.w3.org/Archives/Public/www-style/2017Apr/0027.html): 


> **TabAtkins**: A while back in a meeting I missed we decided to allow
             unitless 0 for all angles because there were places
             where impl allowed it. I don't think we did for all
             dimensions.
  **fantasai**: Correct.
  **TabAtkins**: Even just on length vs angle **it causes grammar
             ambiguity** in motion where the shorthand can combine a
             length and angle. In general this will become a
             problem. **Unitless 0 are a legacy mistake**. This will
             cause footguns in the future. I would like to revisit
             the decision and make it unitless 0 angles in the
             functions that allow them as a legacy thing and then
             restrict to just lengths in grammars.

Hmmm... “Unitless 0 are a legacy mistake”? That sounds interesting. Could it be that the unitless zero is just a bad idea, and it works for lengths but not other number types because lengths were implemented first? Let’s take the unitless zero for a spin and see if it causes any “ambiguity or confusion in the grammars”.

## Is unitless zero just a mistake?

Let’s take the [animation example](https://developer.mozilla.org/en-US/docs/Web/CSS/animation) from MDN: 

```css
.a {
    /* @keyframes duration | timing-function | delay | 
    iteration-count | direction | fill-mode | play-state | name */
    animation: 3s ease-in 0s 0 reverse both paused slidein;
}
```

The full animation shorthand contains an **iteration-count** value, which is a **unitless number**. If unitless zeros were allowed for time values, it would look like this: 

```css
.a {
    animation: 3a ease-in 0 0 reverse both paused slidein;
}
```

Oh yeah, that does look confusing. See the `0 0`? which is the time value and which is the iteration count?

So I guess, as Tab Atkins put it, the unitless zero in most cases is just a **footgun**.