[css-pseudo] Support animations and transitions in ::marker
As resolved in https://github.com/w3c/csswg-drafts/issues/4814, allow
::marker to have animations or transitions. But only for the properties
that apply to ::marker.
TEST=external/wpt/css/css-animations/Document-getAnimations.tentative.html
TEST=external/wpt/css/css-animations/animationevent-marker-pseudoelement.html
TEST=external/wpt/css/css-animations/event-order.tentative.html
TEST=external/wpt/css/css-pseudo/parsing/marker-supported-properties.html
TEST=external/wpt/css/css-pseudo/parsing/marker-supported-properties-in-animation.html
TEST=external/wpt/css/css-transitions/Document-getAnimations.tentative.html
TEST=external/wpt/css/css-transitions/non-rendered-element-004.tentative.html
BUG=1054509
Change-Id: Ie86aeb42d4d311264fd5810c1ad89c0fa7b93ab0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2119518
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753752}
diff --git a/css/css-pseudo/parsing/marker-supported-properties-in-animation.html b/css/css-pseudo/parsing/marker-supported-properties-in-animation.html
new file mode 100644
index 0000000..faf7c90
--- /dev/null
+++ b/css/css-pseudo/parsing/marker-supported-properties-in-animation.html
@@ -0,0 +1,292 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Pseudo-Elements Test: Supported properties in ::marker animations</title>
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
+<link rel="help" href="https://drafts.csswg.org/css-animations-1/#keyframes">
+<link rel="help" href="https://drafts.csswg.org/css-transitions-1/#transitions">
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<meta name="assert" content="This test checks ::marker supports animations and transitions, but only for the properties that apply to ::marker." />
+<style id="style"></style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<ul>
+ <li id="target">target</li>
+</ul>
+<script>
+const interpolationTests = [
+ // ::marker supports all font properties.
+ {
+ property: "font",
+ from: "oblique normal 100 ultra-condensed 5px / 20px serif",
+ to: "italic small-caps 900 ultra-expanded 25px / 50px Ahem",
+ midPoint: ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"],
+ },
+ {
+ property: "font-family",
+ from: "serif",
+ to: "Ahem",
+ midPoint: "Ahem",
+ },
+ {
+ property: "font-feature-settings",
+ from: "'c2sc'",
+ to: "'smcp'",
+ midPoint: "\"smcp\"",
+ },
+ {
+ property: "font-kerning",
+ from: "normal",
+ to: "none",
+ midPoint: "none",
+ },
+ {
+ property: "font-size",
+ from: "5px",
+ to: "25px",
+ midPoint: "15px",
+ },
+ {
+ property: "font-size-adjust",
+ from: "1",
+ to: "3",
+ midPoint: "2",
+ },
+ {
+ property: "font-stretch",
+ from: "ultra-condensed",
+ to: "ultra-expanded",
+ midPoint: ["expanded", "125%"],
+ },
+ {
+ property: "font-style",
+ from: "oblique",
+ to: "italic",
+ midPoint: "italic",
+ },
+ {
+ property: "font-synthesis",
+ from: "weight",
+ to: "none",
+ midPoint: "none",
+ },
+ {
+ property: "font-variant",
+ from: "unicase",
+ to: "small-caps",
+ midPoint: "small-caps",
+ },
+ {
+ property: "font-variant-caps",
+ from: "unicase",
+ to: "small-caps",
+ midPoint: "small-caps",
+ },
+ {
+ property: "font-variant-east-asian",
+ from: "proportional-width",
+ to: "full-width",
+ midPoint: "full-width",
+ },
+ {
+ property: "font-variant-ligatures",
+ from: "no-historical-ligatures",
+ to: "historical-ligatures",
+ midPoint: "historical-ligatures",
+ },
+ {
+ property: "font-variant-numeric",
+ from: "ordinal",
+ to: "slashed-zero",
+ midPoint: "slashed-zero",
+ },
+ {
+ property: "font-variant-position",
+ from: "super",
+ to: "sub",
+ midPoint: "sub",
+ },
+ {
+ property: "font-weight",
+ from: "100",
+ to: "900",
+ midPoint: "500",
+ },
+
+ // ::marker supports `white-space`
+ {
+ property: "white-space",
+ from: "pre-line",
+ to: "nowrap",
+ midPoint: "nowrap",
+ },
+
+ // ::marker supports `color`
+ {
+ property: "color",
+ from: "rgb(0, 100, 200)",
+ to: "rgb(100, 200, 0)",
+ midPoint: "rgb(50, 150, 100)",
+ },
+
+ // ::marker supports `text-combine-upright`, `unicode-bidi` and `direction`,
+ // but they are not animatable.
+ {
+ property: "text-combine-upright",
+ from: "all",
+ to: "all",
+ midPoint: null,
+ },
+ {
+ property: "unicode-bidi",
+ from: "embed",
+ to: "plaintext",
+ midPoint: null,
+ },
+ {
+ property: "direction",
+ from: "rtl",
+ to: "rtl",
+ midPoint: null,
+ },
+
+ // ::marker supports `content`
+ {
+ property: "content",
+ from: "'foo'",
+ to: "'bar'",
+ midPoint: "\"bar\"",
+ },
+
+ // ::marker does NOT support layout properties
+ {
+ property: "display",
+ from: "flex",
+ to: "none",
+ midPoint: ["block", "inline", "inline-block"],
+ },
+ {
+ property: "position",
+ from: "fixed",
+ to: "absolute",
+ midPoint: "static",
+ },
+ {
+ property: "float",
+ from: "left",
+ to: "right",
+ midPoint: "none",
+ },
+
+ // ::marker does NOT support list properties despite being affected by them,
+ // they apply to the list item instead.
+ {
+ property: "list-style",
+ from: "inside url('foo') square",
+ to: "inside url('bar') decimal",
+ midPoint: "outside none disc",
+ },
+ {
+ property: "list-style-image",
+ from: "url('foo')",
+ to: "url('bar')",
+ midPoint: "none",
+ },
+ {
+ property: "list-style-position",
+ from: "inside",
+ to: "inside",
+ midPoint: "outside",
+ },
+ {
+ property: "list-style-type",
+ from: "square",
+ to: "decimal",
+ midPoint: "disc",
+ },
+
+ // ::marker does NOT support `line-height` because, despite being a
+ // longhand of `font`, it's not a font property.
+ {
+ property: "line-height",
+ from: "20px",
+ to: "50px",
+ midPoint: "normal",
+ },
+];
+
+const target = document.getElementById("target");
+const styleElement = document.getElementById("style");
+const markerStyle = getComputedStyle(target, "::marker");
+
+function check({property, from, to, midPoint}) {
+ assert_true(property in markerStyle, property + " doesn't seem to be supported in the computed style");
+ assert_true(CSS.supports(property, from), `'${from}' is a supported value for ${property}.`);
+ assert_true(CSS.supports(property, to), `'${to}' is a supported value for ${property}.`);
+ const computed = markerStyle.getPropertyValue(property);
+ if (Array.isArray(midPoint)) {
+ assert_in_array(computed, midPoint);
+ } else {
+ assert_equals(computed, midPoint);
+ }
+}
+
+function testAnimations(interpolationTests) {
+ styleElement.textContent = `
+ ::marker {
+ animation: anim 2s -1s paused linear;
+ }
+ @keyframes anim {
+ from {}
+ to {}
+ }
+ `;
+ const keyframes = styleElement.sheet.cssRules[1];
+ const fromStyle = keyframes.cssRules[0].style;
+ const toStyle = keyframes.cssRules[1].style;
+ for (let {property, from, to, midPoint} of interpolationTests) {
+ fromStyle.cssText = "";
+ toStyle.cssText = "";
+ if (midPoint == null) {
+ midPoint = markerStyle.getPropertyValue(property);
+ }
+ fromStyle.setProperty(property, from);
+ toStyle.setProperty(property, to);
+ test(() => {
+ check({property, from, to, midPoint});
+ }, `Animation of ${property} in ::marker`);
+ }
+}
+
+function testTransitions(interpolationTests) {
+ styleElement.textContent = `
+ .transition::marker {
+ transition: all 2s -1s linear;
+ }
+ .from::marker {}
+ .to::marker {}
+ `;
+ const fromStyle = styleElement.sheet.cssRules[1].style;
+ const toStyle = styleElement.sheet.cssRules[2].style;
+ for (let {property, from, to, midPoint} of interpolationTests) {
+ fromStyle.cssText = "";
+ toStyle.cssText = "";
+ if (midPoint == null) {
+ midPoint = to;
+ }
+ fromStyle.setProperty(property, from);
+ toStyle.setProperty(property, to);
+ target.className = "from";
+ markerStyle.width;
+ target.classList.add("transition");
+ markerStyle.width;
+ target.classList.add("to");
+ test(() => {
+ check({property, from, to, midPoint});
+ }, `Transition of ${property} in ::marker`);
+ }
+}
+
+testAnimations(interpolationTests);
+testTransitions(interpolationTests);
+</script>
diff --git a/css/css-pseudo/parsing/marker-supported-properties.html b/css/css-pseudo/parsing/marker-supported-properties.html
index 7f8eacb..e27decc 100644
--- a/css/css-pseudo/parsing/marker-supported-properties.html
+++ b/css/css-pseudo/parsing/marker-supported-properties.html
@@ -45,6 +45,24 @@
// ::marker supports `content`
test_pseudo_computed_value("::marker", "content", "\"foo\"");
+// ::marker supports animation properties.
+test_pseudo_computed_value("::marker", "animation", "1s linear 2s infinite alternate forwards paused anim");
+test_pseudo_computed_value("::marker", "animation-delay", "1s");
+test_pseudo_computed_value("::marker", "animation-direction", "alternate");
+test_pseudo_computed_value("::marker", "animation-duration", "2s");
+test_pseudo_computed_value("::marker", "animation-fill-mode", "forwards");
+test_pseudo_computed_value("::marker", "animation-iteration-count", "infinite");
+test_pseudo_computed_value("::marker", "animation-name", "anim");
+test_pseudo_computed_value("::marker", "animation-play-state", "paused");
+test_pseudo_computed_value("::marker", "animation-timing-function", "linear");
+
+// ::marker supports transition properties.
+test_pseudo_computed_value("::marker", "transition", "display 1s linear 2s");
+test_pseudo_computed_value("::marker", "transition-delay", "1s");
+test_pseudo_computed_value("::marker", "transition-duration", "2s");
+test_pseudo_computed_value("::marker", "transition-property", "display");
+test_pseudo_computed_value("::marker", "transition-timing-function", "linear");
+
// ::marker does NOT support layout properties
test_pseudo_computed_value("::marker", "display", "none", ["block", "inline", "inline-block"]);
test_pseudo_computed_value("::marker", "position", "absolute", "static");