diff --git a/components/style/properties/shorthands/box.mako.rs b/components/style/properties/shorthands/box.mako.rs index 4beef9a0d95..b056b58c69c 100644 --- a/components/style/properties/shorthands/box.mako.rs +++ b/components/style/properties/shorthands/box.mako.rs @@ -189,11 +189,11 @@ macro_rules! try_parse_one { sub_properties="animation-name animation-duration animation-timing-function animation-delay animation-iteration-count animation-direction - animation-fill-mode animation-play-state" + animation-fill-mode animation-play-state animation-timeline" rule_types_allowed="Style" spec="https://drafts.csswg.org/css-animations/#propdef-animation"> <% - props = "name duration timing_function delay iteration_count \ + props = "name timeline duration timing_function delay iteration_count \ direction fill_mode play_state".split() %> % for prop in props: @@ -234,6 +234,9 @@ macro_rules! try_parse_one { try_parse_one!(context, input, fill_mode, animation_fill_mode); try_parse_one!(context, input, play_state, animation_play_state); try_parse_one!(context, input, name, animation_name); + if static_prefs::pref!("layout.css.scroll-linked-animations.enabled") { + try_parse_one!(context, input, timeline, animation_timeline); + } parsed -= 1; break @@ -280,22 +283,46 @@ macro_rules! try_parse_one { // If any value list length is differs then we don't do a shorthand serialization // either. - % for name in props[1:]: + % for name in props[2:]: if len != self.animation_${name}.0.len() { return Ok(()) } % endfor + // If the preference of animation-timeline is disabled, `self.animation_timeline` is + // None. + if self.animation_timeline.map_or(false, |v| len != v.0.len()) { + return Ok(()); + } + for i in 0..len { if i != 0 { dest.write_str(", ")?; } - % for name in props[1:]: + % for name in props[2:]: self.animation_${name}.0[i].to_css(dest)?; dest.write_str(" ")?; % endfor + self.animation_name.0[i].to_css(dest)?; + + // Based on the spec, the default values of other properties must be output in at + // least the cases necessary to distinguish an animation-name. The serialization + // order of animation-timeline is always later than animation-name, so it's fine + // to not serialize it if it is the default value. It's still possible to + // distinguish them (because we always serialize animation-name). + // https://drafts.csswg.org/css-animations-1/#animation + // https://drafts.csswg.org/css-animations-2/#typedef-single-animation + // + // Note: it's also fine to always serialize this. However, it seems Blink + // doesn't serialize default animation-timeline now, so we follow the same rule. + if let Some(ref timeline) = self.animation_timeline { + if !timeline.0[i].is_auto() { + dest.write_char(' ')?; + timeline.0[i].to_css(dest)?; + } + } } Ok(()) } diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index c81a3913b54..7d5543cf7fc 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -794,6 +794,11 @@ impl AnimationTimeline { pub fn auto() -> Self { Self::Auto } + + /// Returns true if it is auto (i.e. the default value). + pub fn is_auto(&self) -> bool { + matches!(self, Self::Auto) + } } impl Parse for AnimationTimeline {