mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
LibWeb: Parse the scroll-timeline shorthand CSS property
The remaining failing tests in scroll-timeline-shorthand.html are due to either: a) incorrect tests, see web-platform-tests/wpt#56181 or; b) a wider issue where we collapse coordinating value list longhand properties to a single value when we shouldn't.
This commit is contained in:
parent
992b0a4dc6
commit
13ce2d1857
Notes:
github-actions[bot]
2025-11-28 13:26:23 +00:00
Author: https://github.com/Calme1709
Commit: 13ce2d1857
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6912
Reviewed-by: https://github.com/AtkinsSJ ✅
8 changed files with 261 additions and 3 deletions
|
|
@ -499,6 +499,7 @@ private:
|
||||||
RefPtr<StyleValue const> parse_position_visibility_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_position_visibility_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_quotes_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_quotes_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_single_repeat_style_value(PropertyID, TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_single_repeat_style_value(PropertyID, TokenStream<ComponentValue>&);
|
||||||
|
RefPtr<StyleValue const> parse_scroll_timeline_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_scrollbar_color_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_scrollbar_color_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_scrollbar_gutter_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_scrollbar_gutter_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_shadow_value(TokenStream<ComponentValue>&, ShadowStyleValue::ShadowType);
|
RefPtr<StyleValue const> parse_shadow_value(TokenStream<ComponentValue>&, ShadowStyleValue::ShadowType);
|
||||||
|
|
|
||||||
|
|
@ -745,6 +745,8 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
||||||
return parse_all_as(tokens, [this](auto& tokens) { return parse_translate_value(tokens); });
|
return parse_all_as(tokens, [this](auto& tokens) { return parse_translate_value(tokens); });
|
||||||
case PropertyID::Scale:
|
case PropertyID::Scale:
|
||||||
return parse_all_as(tokens, [this](auto& tokens) { return parse_scale_value(tokens); });
|
return parse_all_as(tokens, [this](auto& tokens) { return parse_scale_value(tokens); });
|
||||||
|
case PropertyID::ScrollTimeline:
|
||||||
|
return parse_all_as(tokens, [this](auto& tokens) { return parse_scroll_timeline_value(tokens); });
|
||||||
case PropertyID::ScrollTimelineAxis:
|
case PropertyID::ScrollTimelineAxis:
|
||||||
case PropertyID::ScrollTimelineName:
|
case PropertyID::ScrollTimelineName:
|
||||||
return parse_all_as(tokens, [this, property_id](auto& tokens) { return parse_simple_comma_separated_value_list(property_id, tokens); });
|
return parse_all_as(tokens, [this, property_id](auto& tokens) { return parse_simple_comma_separated_value_list(property_id, tokens); });
|
||||||
|
|
@ -5182,6 +5184,73 @@ RefPtr<StyleValue const> Parser::parse_scale_value(TokenStream<ComponentValue>&
|
||||||
return TransformationStyleValue::create(PropertyID::Scale, TransformFunction::Scale3d, { maybe_x.release_nonnull(), maybe_y.release_nonnull(), maybe_z.release_nonnull() });
|
return TransformationStyleValue::create(PropertyID::Scale, TransformFunction::Scale3d, { maybe_x.release_nonnull(), maybe_y.release_nonnull(), maybe_z.release_nonnull() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand
|
||||||
|
RefPtr<StyleValue const> Parser::parse_scroll_timeline_value(TokenStream<ComponentValue>& tokens)
|
||||||
|
{
|
||||||
|
// [ <'scroll-timeline-name'> <'scroll-timeline-axis'>? ]#
|
||||||
|
StyleValueVector names;
|
||||||
|
StyleValueVector axes;
|
||||||
|
|
||||||
|
auto transaction = tokens.begin_transaction();
|
||||||
|
|
||||||
|
do {
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
|
||||||
|
auto maybe_name = parse_css_value_for_property(PropertyID::ScrollTimelineName, tokens);
|
||||||
|
|
||||||
|
if (!maybe_name)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
names.append(maybe_name.release_nonnull());
|
||||||
|
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
|
||||||
|
if (tokens.next_token().is(Token::Type::Comma)) {
|
||||||
|
axes.append(KeywordStyleValue::create(Keyword::Block));
|
||||||
|
tokens.discard_a_token();
|
||||||
|
|
||||||
|
// Disallow trailing commas
|
||||||
|
if (!tokens.has_next_token())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tokens.has_next_token()) {
|
||||||
|
axes.append(KeywordStyleValue::create(Keyword::Block));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybe_axis = parse_css_value_for_property(PropertyID::ScrollTimelineAxis, tokens);
|
||||||
|
|
||||||
|
if (!maybe_axis)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
axes.append(maybe_axis.release_nonnull());
|
||||||
|
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
|
||||||
|
if (tokens.next_token().is(Token::Type::Comma)) {
|
||||||
|
tokens.discard_a_token();
|
||||||
|
|
||||||
|
// Disallow trailing commas
|
||||||
|
if (!tokens.has_next_token())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens.has_next_token())
|
||||||
|
return nullptr;
|
||||||
|
} while (tokens.has_next_token());
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
return ShorthandStyleValue::create(PropertyID::ScrollTimeline,
|
||||||
|
{ PropertyID::ScrollTimelineName, PropertyID::ScrollTimelineAxis },
|
||||||
|
{ StyleValueList::create(move(names), StyleValueList::Separator::Comma), StyleValueList::create(move(axes), StyleValueList::Separator::Comma) });
|
||||||
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-scrollbars/#propdef-scrollbar-color
|
// https://drafts.csswg.org/css-scrollbars/#propdef-scrollbar-color
|
||||||
RefPtr<StyleValue const> Parser::parse_scrollbar_color_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<StyleValue const> Parser::parse_scrollbar_color_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3440,6 +3440,16 @@
|
||||||
"affects-layout": false,
|
"affects-layout": false,
|
||||||
"affects-stacking-context": true
|
"affects-stacking-context": true
|
||||||
},
|
},
|
||||||
|
"scroll-timeline": {
|
||||||
|
"affects-layout": false,
|
||||||
|
"inherited": false,
|
||||||
|
"initial": "none block",
|
||||||
|
"multiplicity": "coordinating-list",
|
||||||
|
"longhands": [
|
||||||
|
"scroll-timeline-name",
|
||||||
|
"scroll-timeline-axis"
|
||||||
|
]
|
||||||
|
},
|
||||||
"scroll-timeline-axis": {
|
"scroll-timeline-axis": {
|
||||||
"affects-layout": false,
|
"affects-layout": false,
|
||||||
"animation-type": "none",
|
"animation-type": "none",
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
||||||
return { value.release_nonnull() };
|
return { value.release_nonnull() };
|
||||||
};
|
};
|
||||||
|
|
||||||
auto const coordinating_value_list_shorthand_to_string = [&](StringView entry_when_all_longhands_initial) {
|
auto const coordinating_value_list_shorthand_to_string = [&](StringView entry_when_all_longhands_initial, Vector<PropertyID> required_longhands = {}) {
|
||||||
auto entry_count = style_value_as_value_list(longhand(m_properties.sub_properties[0])).size();
|
auto entry_count = style_value_as_value_list(longhand(m_properties.sub_properties[0])).size();
|
||||||
|
|
||||||
// If we don't have the same number of values for each longhand, we can't serialize this shorthand.
|
// If we don't have the same number of values for each longhand, we can't serialize this shorthand.
|
||||||
|
|
@ -86,10 +86,15 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
||||||
return ""_string;
|
return ""_string;
|
||||||
|
|
||||||
// We should serialize a longhand if:
|
// We should serialize a longhand if:
|
||||||
|
// - The longhand is required
|
||||||
// - The value is not the initial value
|
// - The value is not the initial value
|
||||||
// - Another longhand value which will be included later in the serialization is valid for this longhand.
|
// - Another longhand value which will be included later in the serialization is valid for this longhand.
|
||||||
auto should_serialize_longhand = [&](size_t entry_index, size_t longhand_index) {
|
auto should_serialize_longhand = [&](size_t entry_index, size_t longhand_index) {
|
||||||
auto longhand_id = m_properties.sub_properties[longhand_index];
|
auto longhand_id = m_properties.sub_properties[longhand_index];
|
||||||
|
|
||||||
|
if (required_longhands.contains_slow(longhand_id))
|
||||||
|
return true;
|
||||||
|
|
||||||
auto longhand_value = style_value_as_value_list(longhand(longhand_id))[entry_index];
|
auto longhand_value = style_value_as_value_list(longhand(longhand_id))[entry_index];
|
||||||
|
|
||||||
if (!longhand_value->equals(style_value_as_value_list(property_initial_value(longhand_id))[0]))
|
if (!longhand_value->equals(style_value_as_value_list(property_initial_value(longhand_id))[0]))
|
||||||
|
|
@ -815,6 +820,10 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
||||||
case PropertyID::PlaceItems:
|
case PropertyID::PlaceItems:
|
||||||
case PropertyID::PlaceSelf:
|
case PropertyID::PlaceSelf:
|
||||||
return positional_value_list_shorthand_to_string(m_properties.values);
|
return positional_value_list_shorthand_to_string(m_properties.values);
|
||||||
|
case PropertyID::ScrollTimeline:
|
||||||
|
// NB: We don't need to specify a value to use when the entry is empty as all values are initial since
|
||||||
|
// scroll-timeline-name is always included
|
||||||
|
return coordinating_value_list_shorthand_to_string(""sv, { PropertyID::ScrollTimelineName });
|
||||||
case PropertyID::TextDecoration: {
|
case PropertyID::TextDecoration: {
|
||||||
// The rule here seems to be, only print what's different from the default value,
|
// The rule here seems to be, only print what's different from the default value,
|
||||||
// but if they're all default, print the line.
|
// but if they're all default, print the line.
|
||||||
|
|
|
||||||
|
|
@ -694,6 +694,8 @@ All supported properties and their default values exposed from CSSStylePropertie
|
||||||
'rx': 'auto'
|
'rx': 'auto'
|
||||||
'ry': 'auto'
|
'ry': 'auto'
|
||||||
'scale': 'none'
|
'scale': 'none'
|
||||||
|
'scrollTimeline': 'none'
|
||||||
|
'scroll-timeline': 'none'
|
||||||
'scrollTimelineAxis': 'block'
|
'scrollTimelineAxis': 'block'
|
||||||
'scroll-timeline-axis': 'block'
|
'scroll-timeline-axis': 'block'
|
||||||
'scrollTimelineName': 'none'
|
'scrollTimelineName': 'none'
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 272 tests
|
Found 274 tests
|
||||||
|
|
||||||
266 Pass
|
268 Pass
|
||||||
6 Fail
|
6 Fail
|
||||||
Pass accent-color
|
Pass accent-color
|
||||||
Pass border-collapse
|
Pass border-collapse
|
||||||
|
|
@ -241,6 +241,8 @@ Pass row-gap
|
||||||
Pass rx
|
Pass rx
|
||||||
Pass ry
|
Pass ry
|
||||||
Pass scale
|
Pass scale
|
||||||
|
Pass scroll-timeline-axis
|
||||||
|
Pass scroll-timeline-name
|
||||||
Pass scrollbar-color
|
Pass scrollbar-color
|
||||||
Pass scrollbar-gutter
|
Pass scrollbar-gutter
|
||||||
Pass scrollbar-width
|
Pass scrollbar-width
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 50 tests
|
||||||
|
|
||||||
|
47 Pass
|
||||||
|
3 Fail
|
||||||
|
Pass e.style['scroll-timeline'] = "none block" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "none inline" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc x" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc inline" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--aBc inline" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--inline inline" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--inline block" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--block block" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--y block" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--x block" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--a, --b, --c" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--a inline, --b block, --c y" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--auto" should set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "" should not set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc --abc" should not set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "block none" should not set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "inline --abc" should not set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "default" should not set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = "," should not set the property value
|
||||||
|
Pass e.style['scroll-timeline'] = ",,block,," should not set the property value
|
||||||
|
Pass Property scroll-timeline value 'none block'
|
||||||
|
Pass Property scroll-timeline value '--abc inline'
|
||||||
|
Pass Property scroll-timeline value 'none y'
|
||||||
|
Pass Property scroll-timeline value '--abc x'
|
||||||
|
Pass Property scroll-timeline value '--y y'
|
||||||
|
Pass Property scroll-timeline value '--abc'
|
||||||
|
Pass Property scroll-timeline value '--inline block'
|
||||||
|
Pass Property scroll-timeline value '--block block'
|
||||||
|
Pass Property scroll-timeline value '--y block'
|
||||||
|
Pass Property scroll-timeline value '--x block'
|
||||||
|
Pass Property scroll-timeline value '--a, --b, --c'
|
||||||
|
Pass Property scroll-timeline value '--a inline, --b block, --c y'
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc y" should set scroll-timeline-axis
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc y" should set scroll-timeline-name
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc y" should not set unrelated longhands
|
||||||
|
Pass e.style['scroll-timeline'] = "--inline x" should set scroll-timeline-axis
|
||||||
|
Pass e.style['scroll-timeline'] = "--inline x" should set scroll-timeline-name
|
||||||
|
Pass e.style['scroll-timeline'] = "--inline x" should not set unrelated longhands
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc y, --def" should set scroll-timeline-axis
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc y, --def" should set scroll-timeline-name
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc y, --def" should not set unrelated longhands
|
||||||
|
Fail e.style['scroll-timeline'] = "--abc, --def" should set scroll-timeline-axis
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc, --def" should set scroll-timeline-name
|
||||||
|
Pass e.style['scroll-timeline'] = "--abc, --def" should not set unrelated longhands
|
||||||
|
Pass Shorthand contraction of scroll-timeline-name:--abc:undefined;scroll-timeline-axis:inline:undefined
|
||||||
|
Pass Shorthand contraction of scroll-timeline-name:--a, --b:undefined;scroll-timeline-axis:inline, block:undefined
|
||||||
|
Pass Shorthand contraction of scroll-timeline-name:none, none:undefined;scroll-timeline-axis:block, block:undefined
|
||||||
|
Fail Shorthand contraction of scroll-timeline-name:--a, --b, --c:undefined;scroll-timeline-axis:inline, inline:undefined
|
||||||
|
Fail Shorthand contraction of scroll-timeline-name:--a, --b:undefined;scroll-timeline-axis:inline, inline, inline:undefined
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../css/support/computed-testcommon.js"></script>
|
||||||
|
<script src="../../css/support/parsing-testcommon.js"></script>
|
||||||
|
<script src="../../css/support/shorthand-testcommon.js"></script>
|
||||||
|
<div id="target"></div>
|
||||||
|
<script>
|
||||||
|
test_valid_value('scroll-timeline', 'none block', 'none');
|
||||||
|
test_valid_value('scroll-timeline', 'none inline');
|
||||||
|
test_valid_value('scroll-timeline', '--abc x');
|
||||||
|
test_valid_value('scroll-timeline', '--abc inline');
|
||||||
|
test_valid_value('scroll-timeline', '--aBc inline');
|
||||||
|
test_valid_value('scroll-timeline', '--inline inline');
|
||||||
|
test_valid_value('scroll-timeline', '--abc');
|
||||||
|
|
||||||
|
test_valid_value('scroll-timeline', '--inline block', '--inline');
|
||||||
|
test_valid_value('scroll-timeline', '--block block', '--block');
|
||||||
|
test_valid_value('scroll-timeline', '--y block', '--y');
|
||||||
|
test_valid_value('scroll-timeline', '--x block', '--x');
|
||||||
|
|
||||||
|
test_valid_value('scroll-timeline', '--a, --b, --c');
|
||||||
|
test_valid_value('scroll-timeline', '--a inline, --b block, --c y', '--a inline, --b, --c y');
|
||||||
|
test_valid_value('scroll-timeline', '--auto');
|
||||||
|
|
||||||
|
test_invalid_value('scroll-timeline', '');
|
||||||
|
test_invalid_value('scroll-timeline', '--abc --abc');
|
||||||
|
test_invalid_value('scroll-timeline', 'block none');
|
||||||
|
test_invalid_value('scroll-timeline', 'inline --abc');
|
||||||
|
test_invalid_value('scroll-timeline', 'default');
|
||||||
|
test_invalid_value('scroll-timeline', ',');
|
||||||
|
test_invalid_value('scroll-timeline', ',,block,,');
|
||||||
|
|
||||||
|
test_computed_value('scroll-timeline', 'none block', 'none');
|
||||||
|
test_computed_value('scroll-timeline', '--abc inline');
|
||||||
|
test_computed_value('scroll-timeline', 'none y');
|
||||||
|
test_computed_value('scroll-timeline', '--abc x');
|
||||||
|
test_computed_value('scroll-timeline', '--y y');
|
||||||
|
test_computed_value('scroll-timeline', '--abc');
|
||||||
|
test_computed_value('scroll-timeline', '--inline block', '--inline');
|
||||||
|
test_computed_value('scroll-timeline', '--block block', '--block');
|
||||||
|
test_computed_value('scroll-timeline', '--y block', '--y');
|
||||||
|
test_computed_value('scroll-timeline', '--x block', '--x');
|
||||||
|
test_computed_value('scroll-timeline', '--a, --b, --c');
|
||||||
|
test_computed_value('scroll-timeline', '--a inline, --b block, --c y', '--a inline, --b, --c y');
|
||||||
|
|
||||||
|
test_shorthand_value('scroll-timeline', '--abc y',
|
||||||
|
{
|
||||||
|
'scroll-timeline-name': '--abc',
|
||||||
|
'scroll-timeline-axis': 'y',
|
||||||
|
});
|
||||||
|
test_shorthand_value('scroll-timeline', '--inline x',
|
||||||
|
{
|
||||||
|
'scroll-timeline-name': '--inline',
|
||||||
|
'scroll-timeline-axis': 'x',
|
||||||
|
});
|
||||||
|
test_shorthand_value('scroll-timeline', '--abc y, --def',
|
||||||
|
{
|
||||||
|
'scroll-timeline-name': '--abc, --def',
|
||||||
|
'scroll-timeline-axis': 'y, block',
|
||||||
|
});
|
||||||
|
test_shorthand_value('scroll-timeline', '--abc, --def',
|
||||||
|
{
|
||||||
|
'scroll-timeline-name': '--abc, --def',
|
||||||
|
'scroll-timeline-axis': 'block, block',
|
||||||
|
});
|
||||||
|
|
||||||
|
function test_shorthand_contraction(shorthand, longhands, expected) {
|
||||||
|
let longhands_fmt = Object.entries(longhands).map((e) => `${e[0]}:${e[1]}:${e[2]}`).join(';');
|
||||||
|
test((t) => {
|
||||||
|
t.add_cleanup(() => {
|
||||||
|
for (let shorthand of Object.keys(longhands))
|
||||||
|
target.style.removeProperty(shorthand);
|
||||||
|
});
|
||||||
|
for (let [shorthand, value] of Object.entries(longhands))
|
||||||
|
target.style.setProperty(shorthand, value);
|
||||||
|
assert_equals(target.style.getPropertyValue(shorthand), expected, 'Declared value');
|
||||||
|
assert_equals(getComputedStyle(target).getPropertyValue(shorthand), expected, 'Computed value');
|
||||||
|
}, `Shorthand contraction of ${longhands_fmt}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_shorthand_contraction('scroll-timeline', {
|
||||||
|
'scroll-timeline-name': '--abc',
|
||||||
|
'scroll-timeline-axis': 'inline',
|
||||||
|
}, '--abc inline');
|
||||||
|
|
||||||
|
test_shorthand_contraction('scroll-timeline', {
|
||||||
|
'scroll-timeline-name': '--a, --b',
|
||||||
|
'scroll-timeline-axis': 'inline, block',
|
||||||
|
}, '--a inline, --b');
|
||||||
|
|
||||||
|
test_shorthand_contraction('scroll-timeline', {
|
||||||
|
'scroll-timeline-name': 'none, none',
|
||||||
|
'scroll-timeline-axis': 'block, block',
|
||||||
|
}, 'none, none');
|
||||||
|
|
||||||
|
// Longhands with different lengths:
|
||||||
|
|
||||||
|
test_shorthand_contraction('scroll-timeline', {
|
||||||
|
'scroll-timeline-name': '--a, --b, --c',
|
||||||
|
'scroll-timeline-axis': 'inline, inline',
|
||||||
|
}, '--a inline, --b inline, --c inline');
|
||||||
|
|
||||||
|
test_shorthand_contraction('scroll-timeline', {
|
||||||
|
'scroll-timeline-name': '--a, --b',
|
||||||
|
'scroll-timeline-axis': 'inline, inline, inline',
|
||||||
|
}, '--a inline, --b inline');
|
||||||
|
</script>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue