Closed Bug 627559 Opened 13 years ago Closed 13 years ago

-moz-transition-duration: 0 results in an error (requires a unit to work)

Categories

(Core :: CSS Parsing and Computation, defect)

x86
macOS
defect
Not set
minor

Tracking

()

RESOLVED INVALID

People

(Reporter: dion, Unassigned)

Details

When debugging a CSS transitions bug in an application, I happened into the problem.

Code was setting -moz-transition-duration to 0, and that resulted in:

Error in parsing value for '-moz-transition-duration'.  Declaration dropped.

The same was being given to -webkit-transition-duration. I haven't seen what the spec says, but I always feel strange adding a unit to 0, since 0s === 0ms === 0any other time unit.
Yeah, 0 is unit-free in other property cases.

/be
CSS requires units for times and angles (but yes, as you note, not for lengths, for various historical reasons).  Compare the second paragraph of http://www.w3.org/TR/CSS21/syndata.html#length-units to http://dev.w3.org/csswg/css3-values/#lttimegt (which has no such exception for 0).

So as far as I can tell this is invalid...
You may also want to read the thread starting at http://lists.w3.org/Archives/Public/www-style/2010Oct/0551.html
This is per-spec, and matches what the spec has said since 1998.

http://www.w3.org/TR/1998/REC-CSS2-19980512/syndata.html#values specifically says lengths can have unitless '0' (4.3.2), but does not say the same for angles (4.3.7), times (4.3.8), or frequencies (4.3.9).

If the spec changes, I'm willing to fix this, but I'm not going to advocate for such a spec change.  (And such a change would either require that switch to the updated gradient syntax proposal and drop support for what we currently support or that we exclude gradients from such a change until we do; I'm not sure if I really want to do that before we're ready to drop the -moz- prefix.)
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → INVALID
I does seem strange to not grok 0 for some units, but I see that it is a pain to go back and fix it.

On the one hand: chances are that most people do '0s', or use libraries that set it all up.
On the other hand: -webkit-* properties have been in the wild for a lot longer than the -moz-* properties, and since a pure 0 works there, I bet some apps won't work on Firefox.

At the least, this is an example where it would be nice to give more info in the console:

Instead of:

Error in parsing value for '-moz-transition-duration'.  Declaration dropped.

Maybe some context? Show the value that was passed in, and of course ideally.... say why 0 isn't accepted.
@David Baron: The spec says that it is to be combined with the CSS 2.1 specification, and is to be backwards compatible (stated as such in both the status of the document, and in module interactions (1.1).  The CSS 2.1 specification states that not having a unit is valid for angles (A.2.1 Angles) and time types (A.2.2 Times), so CSS 3 must infer those as well.

Appendix A of CSS 2.1 specification: http://www.w3.org/TR/2011/REC-CSS2-20110607/aural.html#aural-media-group

Additionally, all other major browsers (IE, Safari, Chrome) currently support 0 with no time unit for times.
Robert, David is a CSS working group member and has a pretty good idea of what the spec says.  For example, the entirety of CSS2.1 Appendix A is informative, not normative.  As in, it's not actually a specification, just explanatory text.  And if it happens to contradict actual specifications, those take precedence, because no one actually proofreads informative text that carefully to make sure it's correct, sadly.

The actual normative specification defining <time> values as of today is either the REC cited in comment 4 or the CR at http://www.w3.org/TR/2012/CR-css3-values-20120828/#time depending on the maturity level you want and both disallow "0" as a <time> value.

Further, supporting 0 with no unit for times is not compatible with various existing functionality (e.g. it makes it impossible to unambiguously parse the "animation" shorthand).
Boris, I'm sure he has a good idea of what the spec says, and there are many others who do as well, including Sylvain Galineau who is also on the CSS working group who made the exact same suggestion, but perhaps his position has/had changed, I don't know.

Further, IE, Safari, and Chrome all accept 0 with no unit for time in the animation property, which is where I ran across the issue.  Unfortunately, I ran across it because the default Microsoft CSS minifier in the ASP.NET framework also removes the "s" on 0 valued times, and only firefox was breaking in production.  Other popular CSS minification utilities do as well, but not all.

As for the animation shorthand, there is already (possibly?) two different time values present, so I'm not sure how this makes it impossible since they would already be forced to be given in a particular order to distinguish between them, but I'll leave that up to the experts who know better than I.  There might have been some ambiguity in prior gradient properties that someone has mentioned, but I just don't see it in the current incarnation either, but again, the experts would know better.
Robert, I understand the compat issue.  That seems like something to bring up in the working group to get the spec changed or with the other implementations and the minifier to follow the spec...

> so I'm not sure how this makes it impossible since they would already be forced to be
> given in a particular order

The two times have to be given in a particular order.  The spec clearly says this:

   the first value that can be parsed as a <time> is assigned to the animation-duration,
   and the second value that can be parsed as a <time> is assigned to animation-delay. 

However a single bare 0 could be either of two things: the duration or the iteration count.  The spec as currently written doesn't allow disambiguating those two cases.

(There was also ambiguity in gradients for angles, but of course not for times, since gradients don't have times in them.)
Thanks for the clarification Boris.

As per the spec as currently written, and assuming a bare 0 would be valid for a <time>, I don't see how it would be ambiguous, although it would be nice if it was explicitly mentioned.

No matter the combination or order, if you take the rules that the first value that can be parsed as a <time> is assigned to the animation-duration, and the second as animation-delay, while not clear, it's not ambiguous.

All possible combinations
0 0 <number>[s|ms] would be <time> <time> <time> - INVALID
0 <number>[s|ms] 0 would be <time> <time> <length>
0 <number>[s|ms] <number>[s|ms] would be <time> <time> <time> - INVALID
<number>[s|ms] 0 0 would be <time> <time> <length>
<number>[s|ms] 0 <number>[s|ms] would be <time> <time> <time> - INVALID
<number>[s|ms] <number>[s|ms] 0 would be <time> <time> <length>
<number>[s|ms] <number>[s|ms] <number>[s|ms] would be <time> <time> <time> - INVALID
0 0 would be <time> <time>
0 <number>[s|ms] would be <time> <time>
<number>[s|ms] 0 would be <time> <time>
1[s|ms] 1[s|ms] would be <time> <time>
0 would be <time>
1[s|ms] would be <time>

As for the ambiguity of <angles> in gradients, I don't see it either.  I'm probably missing it, could you explain that one to me?
Sorry, I forgot the following combination:
0 0 0 would be <time> <time> <length>
(In reply to Robert McKee from comment #10)
> 0 <number>[s|ms] <number>[s|ms] would be <time> <time> <time> - INVALID

This combination is valid today, though, as <number> <time> <time>.

(I'm not sure how <length> got involved.)

> 0 <number>[s|ms] would be <time> <time>

Today this is <number> <time> (animation-iteration-count, animation-duration).

> <number>[s|ms] 0 would be <time> <time>

And today this is <time> <number> (animation-duration, animation-iteration-count).

> 0 would be <time>

Today this is <number> (animation-iteration-count).
Sorry, I was using <length> where <number> should have been used.

Rewritten as the properties:
0 0 0 would be <duration> <delay> <iteration-count>
0 0 <number>[s|ms] would be <duration> <delay> <time> - INVALID
0 <number>[s|ms] 0 would be <duration> <delay> <iteration-count>
0 <number>[s|ms] <number>[s|ms] would be <duration> <delay> <time> - INVALID
<number>[s|ms] 0 0 would be <duration> <delay> <iteration-count>
<number>[s|ms] 0 <number>[s|ms] would be <duration> <delay> <time> - INVALID
<number>[s|ms] <number>[s|ms] 0 would be <duration> <delay> <iteration-count>
<number>[s|ms] <number>[s|ms] <number>[s|ms] would be <duration> <delay> <time> - INVALID
0 0 would be <duration> <delay>
0 <number>[s|ms] would be <duration> <delay>
<number>[s|ms] 0 would be <duration> <delay>
1[s|ms] 1[s|ms] would be <duration> <delay>
0 would be <duration>
1[s|ms] would be <duration>

Although not according to spec as written, the following would make some sense as well:

0 0 0 would be <duration> <delay> <iteration-count>
0 0 <number>[s|ms] would be <duration> <iteration-count> <delay> - ?
0 <number>[s|ms] 0 would be <duration> <delay> <iteration-count>
0 <number>[s|ms] <number>[s|ms] would be <iteration-count> <duration> <delay> - ?
<number>[s|ms] 0 0 would be <duration> <delay> <iteration-count>
<number>[s|ms] 0 <number>[s|ms] would be <duration> <iteration-count> <delay> - ?
<number>[s|ms] <number>[s|ms] 0 would be <duration> <delay> <iteration-count>
<number>[s|ms] <number>[s|ms] <number>[s|ms] would be <duration> <delay> <time> - INVALID
0 0 would be <duration> <delay>
0 <number>[s|ms] would be <duration> <delay>
<number>[s|ms] 0 would be <duration> <delay>
1[s|ms] 1[s|ms] would be <duration> <delay>
0 would be <duration>
1[s|ms] would be <duration>

As per animation: 0 being shorthand for animation-iteration-count, IE 10, and webkit treats animation:0 as being a shorthand for animation-duration:0, exactly as I suggested it should be.  I'll test the others combinations.
Here's the source script I ran:
    <script>
        $(function () {
            $('body').append('<div>').attr('id', 'results');
            var tests = ["unset - garbage 1s 1s 1s", "0", "1s",
                "0 0", "0 1s", "1s 0", "1s 1s",
                "0 0 0", "0 0 1s", "0 1s 0", "0 1s 1s", "1s 0 0", "1s 0 1s", "1s 1s 0", "1s 1s 1s"];

            tests.forEach(function(test) {
                var div = $('<div>').css('animation-duration', '2s').css('animation-delay', '3s').css('animation-iteration-count', 4).css("animation", test);
                $('#results').append("<br />Test: " + test + " ");
                if (div.css('animation-duration') == '2s') {
                    $('#results').append('INVALID<br/>');
                } else {
                    $('#results').append('VALID<br/>');
                    var styleProps = ["animation", "animation-duration", "animation-delay", "animation-iteration-count"];
                    styleProps.forEach(function(prop) {
                        $('#results').append(prop + ':' + div.css(prop) + '<br />');
                    });
                }
            });
        });
    </script>

Firefox results:
Test: unset - garbage 1s 1s 1s INVALID

Test: 0 VALID
animation:0s ease 0s normal none 0 none
animation-duration:0s
animation-delay:0s
animation-iteration-count:0

Test: 1s VALID
animation:1s ease 0s normal none 1 none
animation-duration:1s
animation-delay:0s
animation-iteration-count:1

Test: 0 0 INVALID

Test: 0 1s VALID
animation:1s ease 0s normal none 0 none
animation-duration:1s
animation-delay:0s
animation-iteration-count:0

Test: 1s 0 VALID
animation:1s ease 0s normal none 0 none
animation-duration:1s
animation-delay:0s
animation-iteration-count:0

Test: 1s 1s VALID
animation:1s ease 1s normal none 1 none
animation-duration:1s
animation-delay:1s
animation-iteration-count:1

Test: 0 0 0 INVALID

Test: 0 0 1s INVALID

Test: 0 1s 0 INVALID

Test: 0 1s 1s VALID
animation:1s ease 1s normal none 0 none
animation-duration:1s
animation-delay:1s
animation-iteration-count:0

Test: 1s 0 0 INVALID

Test: 1s 0 1s VALID
animation:1s ease 1s normal none 0 none
animation-duration:1s
animation-delay:1s
animation-iteration-count:0

Test: 1s 1s 0 VALID
animation:1s ease 1s normal none 0 none
animation-duration:1s
animation-delay:1s
animation-iteration-count:0

Test: 1s 1s 1s INVALID

----

Test: unset - garbage 1s 1s 1s INVALID

Test: 0 VALID
animation:none
animation-duration:0s
animation-delay:0s
animation-iteration-count:1

Test: 1s VALID
animation:1s
animation-duration:1s
animation-delay:0s
animation-iteration-count:1

Test: 0 0 VALID
animation:none
animation-duration:0s
animation-delay:0s
animation-iteration-count:1

Test: 0 1s VALID
animation:0s 1s
animation-duration:0s
animation-delay:1s
animation-iteration-count:1

Test: 1s 0 VALID
animation:1s
animation-duration:1s
animation-delay:0s
animation-iteration-count:1

Test: 1s 1s VALID
animation:1s 1s
animation-duration:1s
animation-delay:1s
animation-iteration-count:1

Test: 0 0 0 VALID
animation:0s 0s 0
animation-duration:0s
animation-delay:0s
animation-iteration-count:0

Test: 0 0 1s INVALID

Test: 0 1s 0 VALID
animation:0s 1s 0
animation-duration:0s
animation-delay:1s
animation-iteration-count:0

Test: 0 1s 1s INVALID

Test: 1s 0 0 VALID
animation:1s 0s 0
animation-duration:1s
animation-delay:0s
animation-iteration-count:0

Test: 1s 0 1s INVALID

Test: 1s 1s 0 VALID
animation:1s 1s 0
animation-duration:1s
animation-delay:1s
animation-iteration-count:0

Test: 1s 1s 1s INVALID

----

Test: unset - garbage 1s 1s 1s INVALID

Test: 0 VALID
animation:0ms
animation-duration:0ms
animation-delay:initial
animation-iteration-count:initial

Test: 1s VALID
animation:1s
animation-duration:1s
animation-delay:initial
animation-iteration-count:initial

Test: 0 0 VALID
animation:0ms 0ms
animation-duration:0ms
animation-delay:0ms
animation-iteration-count:initial

Test: 0 1s VALID
animation:0ms 1s
animation-duration:0ms
animation-delay:1s
animation-iteration-count:initial

Test: 1s 0 VALID
animation:1s 0ms
animation-duration:1s
animation-delay:0ms
animation-iteration-count:initial

Test: 1s 1s VALID
animation:1s 1s
animation-duration:1s
animation-delay:1s
animation-iteration-count:initial

Test: 0 0 0 VALID
animation:0ms 0ms 0
animation-duration:0ms
animation-delay:0ms
animation-iteration-count:0

Test: 0 0 1s INVALID

Test: 0 1s 0 VALID
animation:0ms 1s 0
animation-duration:0ms
animation-delay:1s
animation-iteration-count:0

Test: 0 1s 1s INVALID

Test: 1s 0 0 VALID
animation:1s 0ms 0
animation-duration:1s
animation-delay:0ms
animation-iteration-count:0

Test: 1s 0 1s INVALID

Test: 1s 1s 0 VALID
animation:1s 1s 0
animation-duration:1s
animation-delay:1s
animation-iteration-count:0

Test: 1s 1s 1s INVALID
Sorry, the first test was firefox, the second was IE 10, and the third Chrome.
Although, I don't like the change in spec, and think it'll cause more issues than it solves, I've filed bug reports with Microsoft for Internet Explorer 10, webkit on bugzilla, Chrome, Microsoft's bundling and minification team, but I couldn't find contact information for some of the other online CSS minifiers, most only appear to officially support CSS 2.1 anyhow.
You need to log in before you can comment on or make changes to this bug.