mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Update web-platform-tests to revision b'ee6da9d71d0268d7fdb04e8e5b26858f46ee0cc4'
This commit is contained in:
parent
4401622eb1
commit
b77ad115f6
16832 changed files with 270819 additions and 87621 deletions
|
@ -8,7 +8,6 @@
|
|||
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#all-shorthand">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#all-shorthand">
|
||||
<link rel="match" href="all-prop-001-ref.html">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="Test passes if 'all' resets properties other than 'direction' and 'unicode-bidi'.">
|
||||
<style>
|
||||
.test {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#all-shorthand">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#all-shorthand">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="all:inherit should cause display:inherit so the red divs will display inline/horizontal (like their parent span) rather than block/vertical (like the default UA style for a div).">
|
||||
<style>
|
||||
.inline {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<title>CSS Cascade: "color" property preceded by "all: initial"</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
|
||||
<link rel="match" href="reference/ref-green-text.html">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="Own 'color', preceded by 'all: inherit', overrides inherited 'color'.">
|
||||
<style>
|
||||
.outer {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<title>CSS Cascade: "color" property preceded by "all: initial"</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
|
||||
<link rel="match" href="reference/ref-green-text.html">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="Own 'color', preceded by 'all: initial', overrides inherited 'color'.">
|
||||
<style>
|
||||
.outer {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<title>CSS Cascade: "color" property preceded by "all: revert"</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
|
||||
<link rel="match" href="reference/ref-green-text.html">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="Own 'color', preceded by 'all: revert', overrides inherited 'color'.">
|
||||
<style>
|
||||
.outer {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<title>CSS Cascade: "color" property preceded by "all: unset"</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
|
||||
<link rel="match" href="reference/ref-green-text.html">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="Own 'color', preceded by 'all: unset', overrides inherited 'color'.">
|
||||
<style>
|
||||
.outer {
|
||||
|
|
36
tests/wpt/web-platform-tests/css/css-cascade/idlharness.html
Normal file
36
tests/wpt/web-platform-tests/css/css-cascade/idlharness.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
<!doctype html>
|
||||
<title>CSS Cascade Layers IDL tests</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layer-apis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/WebIDLParser.js"></script>
|
||||
<script src="/resources/idlharness.js"></script>
|
||||
|
||||
<style>
|
||||
@layer bar, baz;
|
||||
@import url('data:text/css,') layer(qux);
|
||||
@layer foo { }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
idl_test(
|
||||
['css-cascade'],
|
||||
['cssom'],
|
||||
idl_array => {
|
||||
try {
|
||||
self.statement = document.styleSheets[0].cssRules.item(0);
|
||||
self.layeredImport = document.styleSheets[0].cssRules.item(1);
|
||||
self.block = document.styleSheets[0].cssRules.item(2);
|
||||
} catch (e) {
|
||||
// Will be surfaced when any rule is undefined below.
|
||||
}
|
||||
|
||||
idl_array.add_objects({
|
||||
CSSLayerBlockRule: ['block'],
|
||||
CSSLayerStatementRule: ['statement'],
|
||||
CSSImportRule: ['layeredImport']
|
||||
});
|
||||
}
|
||||
);
|
||||
</script>
|
|
@ -8,7 +8,6 @@
|
|||
<link rel="help" href="https://drafts.csswg.org/css-cascade/#importance">
|
||||
<link rel="match" href="important-prop-ref.html">
|
||||
<meta name="assert" content="Test passes if normal rules are overridden by animations, important rules override animations, and !important declarations are ignored in animations.">
|
||||
<meta name="flags" content="">
|
||||
<style>
|
||||
@keyframes override {
|
||||
from, to {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#initial">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#initial">
|
||||
<link rel="match" href="initial-color-background-001-ref.html">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="initial is not the same as inherit. color:initial results in non-red. background-color:initial results in transparent.">
|
||||
<style>
|
||||
body {
|
||||
|
|
|
@ -26,9 +26,9 @@ var testCases = [
|
|||
{
|
||||
title: 'A2 Anonymous layers',
|
||||
style: `
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
|
@ -36,9 +36,9 @@ var testCases = [
|
|||
title: 'A3 Anonymous layers',
|
||||
style: `
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -56,12 +56,11 @@ var testCases = [
|
|||
title: 'A5 Anonymous layers',
|
||||
style: `
|
||||
@layer {
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
}
|
||||
target { color: red; }
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -69,11 +68,10 @@ var testCases = [
|
|||
style: `
|
||||
@layer {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
}
|
||||
target { color: red; }
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -87,9 +85,9 @@ var testCases = [
|
|||
}
|
||||
@layer {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
|
@ -106,9 +104,9 @@ var testCases = [
|
|||
}
|
||||
@layer {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
|
@ -124,10 +122,10 @@ var testCases = [
|
|||
@layer {
|
||||
@layer {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
}
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
|
@ -143,9 +141,9 @@ var testCases = [
|
|||
title: 'B2 Named layers',
|
||||
style: `
|
||||
@layer A {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -157,7 +155,6 @@ var testCases = [
|
|||
@layer A {
|
||||
target { color: green; }
|
||||
}
|
||||
target { color: red; }
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -178,9 +175,9 @@ var testCases = [
|
|||
title: 'B5 Named layers',
|
||||
style: `
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
@layer A {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
@ -365,11 +362,11 @@ var testCases = [
|
|||
style: `
|
||||
@layer A {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
}
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
|
@ -508,11 +505,10 @@ var testCases = [
|
|||
},
|
||||
];
|
||||
|
||||
for (var i = 0; i < testCases.length; ++i) {
|
||||
var testCase = testCases[i];
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
for (let testCase of testCases) {
|
||||
const styleElement = document.createElement('style');
|
||||
styleElement.textContent = testCase['style'];
|
||||
document.head.append(styleElement);
|
||||
|
||||
test(function () {
|
||||
var targets = document.querySelectorAll('target');
|
||||
|
@ -521,7 +517,7 @@ for (var i = 0; i < testCases.length; ++i) {
|
|||
testCase['title'] + ", target '" + target.classList[0] + "'");
|
||||
}, testCase['title']);
|
||||
|
||||
document.head.removeChild(documentStyle)
|
||||
styleElement.remove();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Resolving @counter-style name conflicts with cascade layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#target, #reference {
|
||||
font-family: monospace;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
#reference::before {
|
||||
content: '0000';
|
||||
}
|
||||
|
||||
@counter-style three {
|
||||
system: cyclic;
|
||||
symbols: '000';
|
||||
}
|
||||
|
||||
@counter-style four {
|
||||
system: cyclic;
|
||||
symbols: '0000';
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul>
|
||||
<li id="target"></li>
|
||||
<li id="reference"></li>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
// In all tests, #target::before should have 4 characters, same as #reference.
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: '@counter-style unlayered overrides layered',
|
||||
style: `
|
||||
#target::before {
|
||||
content: counter(dont-care, custom-counter-style);
|
||||
}
|
||||
|
||||
@counter-style custom-counter-style {
|
||||
system: extends four;
|
||||
}
|
||||
|
||||
@layer {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends three;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@counter-style override between layers',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target::before {
|
||||
content: counter(dont-care, custom-counter-style);
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends four;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends three;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@counter-style override update with appended sheet 1',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target::before {
|
||||
content: counter(dont-care, custom-counter-style);
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends four;
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer base {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends three;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@counter-style override update with appended sheet 2',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target::before {
|
||||
content: counter(dont-care, custom-counter-style);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends three;
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer override {
|
||||
@counter-style custom-counter-style {
|
||||
system: extends four;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
|
||||
var appendedStyle;
|
||||
if (testCase['append']) {
|
||||
document.body.offsetLeft; // Force style update
|
||||
appendedStyle = document.createElement('style');
|
||||
appendedStyle.appendChild(document.createTextNode(testCase['append']));
|
||||
document.head.appendChild(appendedStyle);
|
||||
}
|
||||
|
||||
test(function () {
|
||||
assert_equals(getComputedStyle(target).width,
|
||||
getComputedStyle(reference).width);
|
||||
}, testCase['title']);
|
||||
|
||||
if (appendedStyle)
|
||||
appendedStyle.remove();
|
||||
documentStyle.remove();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,190 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: at-rule and style invalidation on layer order changes</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="stylesheet" href="/fonts/ahem.css">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#reference {
|
||||
color: green;
|
||||
font: 20px/1 ahem;
|
||||
width: max-content;
|
||||
--foo: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id=target>Lorem ipsum</div>
|
||||
<div id=reference>Lorem ipsum</div>
|
||||
|
||||
<script>
|
||||
const testCases = [
|
||||
{
|
||||
title: 'Insert layer invalidates style',
|
||||
sheets: [
|
||||
'',
|
||||
`
|
||||
@layer first {
|
||||
#target { color: green; }
|
||||
}
|
||||
@layer second {
|
||||
#target { color: red; }
|
||||
}
|
||||
`,
|
||||
],
|
||||
update: function(sheets) {
|
||||
sheets[0].insertRule('@layer second {}', 0);
|
||||
},
|
||||
property: 'color',
|
||||
},
|
||||
{
|
||||
title: 'Delete layer invalidates style',
|
||||
sheets: [
|
||||
'@layer second {}',
|
||||
`
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
`,
|
||||
],
|
||||
update: function(sheets) {
|
||||
sheets[0].deleteRule(0);
|
||||
},
|
||||
property: 'color',
|
||||
},
|
||||
{
|
||||
title: 'Insert layer invalidates @font-face',
|
||||
sheets: [
|
||||
'',
|
||||
`
|
||||
@layer first {
|
||||
@font-face {
|
||||
font-family: custom;
|
||||
src: local('Ahem'), url('/fonts/Ahem.ttf');
|
||||
}
|
||||
}
|
||||
@layer second {
|
||||
@font-face {
|
||||
font-family: custom;
|
||||
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
|
||||
}
|
||||
}
|
||||
#target { font: 20px/1 custom; width: max-content; }
|
||||
`,
|
||||
],
|
||||
update: async function(sheets) {
|
||||
await document.fonts.load('20px/1 ahem');
|
||||
await document.fonts.load('20px/1 custom');
|
||||
document.body.offsetLeft; // Force style recalc
|
||||
sheets[0].insertRule('@layer second {}', 0);
|
||||
await document.fonts.load('20px/1 custom');
|
||||
},
|
||||
property: 'width',
|
||||
},
|
||||
{
|
||||
title: 'Delete layer invalidates @font-face',
|
||||
sheets: [
|
||||
'@layer second {}',
|
||||
`
|
||||
@layer first {
|
||||
@font-face {
|
||||
font-family: custom;
|
||||
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
|
||||
}
|
||||
}
|
||||
@layer second {
|
||||
@font-face {
|
||||
font-family: custom;
|
||||
src: local('Ahem'), url('/fonts/Ahem.ttf');
|
||||
}
|
||||
}
|
||||
#target { font: 20px/1 custom; width: max-content; }
|
||||
`,
|
||||
],
|
||||
update: async function(sheets) {
|
||||
await document.fonts.load('20px/1 ahem');
|
||||
await document.fonts.load('20px/1 custom');
|
||||
document.body.offsetLeft; // Force style recalc
|
||||
sheets[0].deleteRule(0);
|
||||
await document.fonts.load('20px/1 custom');
|
||||
},
|
||||
property: 'width',
|
||||
},
|
||||
{
|
||||
title: 'Insert layer invalidates @property',
|
||||
sheets: [
|
||||
'',
|
||||
`
|
||||
@layer first {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: green;
|
||||
}
|
||||
}
|
||||
@layer second {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: red;
|
||||
}
|
||||
}
|
||||
`,
|
||||
],
|
||||
update: function(sheets) {
|
||||
sheets[0].insertRule('@layer second {}', 0);
|
||||
},
|
||||
property: '--foo',
|
||||
},
|
||||
{
|
||||
title: 'Delete layer invalidates @property',
|
||||
sheets: [
|
||||
'@layer second {}',
|
||||
`
|
||||
@layer first {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: red;
|
||||
}
|
||||
}
|
||||
@layer second {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: green;
|
||||
}
|
||||
}
|
||||
`,
|
||||
],
|
||||
update: function(sheets) {
|
||||
sheets[0].deleteRule(0);
|
||||
},
|
||||
property: '--foo',
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
promise_test(async test => {
|
||||
const styleElements = testCase.sheets.map(sheet => {
|
||||
const element = document.createElement('style');
|
||||
element.appendChild(document.createTextNode(sheet));
|
||||
document.head.appendChild(element);
|
||||
return element;
|
||||
});
|
||||
test.add_cleanup(() => {
|
||||
for (let element of styleElements)
|
||||
element.remove();
|
||||
});
|
||||
|
||||
const sheets = styleElements.map(element => element.sheet);
|
||||
await testCase.update(sheets);
|
||||
const actual = getComputedStyle(target).getPropertyValue(testCase.property);
|
||||
const expected = getComputedStyle(reference).getPropertyValue(testCase.property);
|
||||
assert_equals(actual, expected);
|
||||
}, testCase.title);
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,141 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Resolving @keyframe name conflicts with cascade layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#target {
|
||||
font-size: 20px;
|
||||
width: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target">Test</div>
|
||||
|
||||
<script>
|
||||
// In all tests, width of #target should be 80px.
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: '@font-face unlayered overrides layered',
|
||||
style: `
|
||||
#target {
|
||||
font-family: custom-font;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/Ahem.ttf');
|
||||
}
|
||||
|
||||
@layer {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@font-face override between layers',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
font-family: custom-font;
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/Ahem.ttf');
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@font-face override update with appended sheet 1',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
font-family: custom-font;
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/Ahem.ttf');
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer base {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@font-face override update with appended sheet 2',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
font-family: custom-font;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer override {
|
||||
@font-face {
|
||||
font-family: custom-font;
|
||||
src: url('/fonts/Ahem.ttf');
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
promise_test(async () => {
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
|
||||
var appendedStyle;
|
||||
if (testCase['append']) {
|
||||
document.body.offsetLeft; // Force style update
|
||||
appendedStyle = document.createElement('style');
|
||||
appendedStyle.appendChild(document.createTextNode(testCase['append']));
|
||||
document.head.appendChild(appendedStyle);
|
||||
}
|
||||
|
||||
await document.fonts.load('20px/1 custom-font');
|
||||
assert_equals(getComputedStyle(target).width, '80px');
|
||||
|
||||
if (appendedStyle)
|
||||
appendedStyle.remove();
|
||||
documentStyle.remove();
|
||||
}, testCase['title']);
|
||||
}
|
||||
</script>
|
|
@ -57,24 +57,24 @@ const testCases = [
|
|||
{
|
||||
title: 'A1 Layer rules with import',
|
||||
style: `
|
||||
@import url(basic-red.css);
|
||||
@import url(basic-green.css);
|
||||
@layer {
|
||||
target { color: green; }
|
||||
target { color: red; }
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'A2 Layer rules with import',
|
||||
style: `
|
||||
@import url(layer-green.css);
|
||||
target { color: red; }
|
||||
@import url(layer-red.css);
|
||||
target { color: green; }
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'A3 Layer rules with import',
|
||||
style: `
|
||||
@import url(layer-green.css);
|
||||
@import url(basic-red.css);
|
||||
@import url(basic-green.css);
|
||||
@import url(layer-red.css);
|
||||
`
|
||||
},
|
||||
{
|
||||
|
@ -92,8 +92,8 @@ const testCases = [
|
|||
{
|
||||
title: 'B1 Anonymous imports',
|
||||
style: `
|
||||
@import url(basic-green.css) layer;
|
||||
target { color: red; }
|
||||
@import url(basic-red.css) layer;
|
||||
target { color: green; }
|
||||
`
|
||||
},
|
||||
{
|
||||
|
@ -122,8 +122,8 @@ const testCases = [
|
|||
{
|
||||
title: 'C1 Named imports',
|
||||
style: `
|
||||
@import url(basic-green.css) layer(A);
|
||||
target { color: red; }
|
||||
@import url(basic-red.css) layer(A);
|
||||
target { color: green; }
|
||||
`
|
||||
},
|
||||
{
|
||||
|
@ -145,9 +145,9 @@ const testCases = [
|
|||
{
|
||||
title: 'C4 Named imports',
|
||||
style: `
|
||||
@import url(layer-green.css) layer(A);
|
||||
@import url(layer-red.css) layer(A);
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
target { color: green; }
|
||||
}
|
||||
`
|
||||
},
|
||||
|
@ -192,8 +192,8 @@ const testCases = [
|
|||
title: 'C9 Named imports',
|
||||
style: `
|
||||
@import url(basic-red.css) layer(A);
|
||||
@import url(basic-green.css) layer(B.A);
|
||||
@import url(basic-red.css) layer(B);
|
||||
@import url(basic-red.css) layer(B.A);
|
||||
@import url(basic-green.css) layer(B);
|
||||
`
|
||||
},
|
||||
{
|
||||
|
@ -252,6 +252,18 @@ const testCases = [
|
|||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'E1 Named imports establish layer even with network errors',
|
||||
style: `
|
||||
@import "nonexist.css" layer(A);
|
||||
@layer B {
|
||||
target { color: green; }
|
||||
}
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
|
@ -260,18 +272,21 @@ for (let testCase of testCases) {
|
|||
const styleText = testCase['style'].replaceAll(/url\((.+?)\)/g, (match, p1) => {
|
||||
return `url(data:text/css,${ encodeURI(imports[p1]) })`;
|
||||
});
|
||||
styleElement.appendChild(document.createTextNode(styleText));
|
||||
styleElement.textContent = styleText;
|
||||
|
||||
await new Promise(resolve => {
|
||||
styleElement.onload = resolve;
|
||||
document.head.appendChild(styleElement);
|
||||
styleElement.onerror = resolve;
|
||||
document.head.append(styleElement);
|
||||
});
|
||||
|
||||
const targets = document.querySelectorAll('target');
|
||||
for (target of targets)
|
||||
assert_equals(window.getComputedStyle(target).color, 'rgb(0, 128, 0)', testCase['title'] + ", target '" + target.classList[0] + "'");
|
||||
|
||||
document.head.removeChild(styleElement);
|
||||
try {
|
||||
const targets = document.querySelectorAll('target');
|
||||
for (target of targets)
|
||||
assert_equals(window.getComputedStyle(target).color, 'rgb(0, 128, 0)', testCase['title'] + ", target '" + target.classList[0] + "'");
|
||||
} finally {
|
||||
styleElement.remove();
|
||||
}
|
||||
}, testCase['title']);
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Resolving @keyframe name conflicts with cascade layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#target, #reference {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#reference {
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target"></div>
|
||||
<div id="reference"></div>
|
||||
|
||||
<script>
|
||||
// In all tests, background color of #target should be green, same as #reference
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: '@keyframes unlayered overrides layered',
|
||||
style: `
|
||||
#target {
|
||||
animation: anim 1s paused;
|
||||
}
|
||||
|
||||
@keyframes anim {
|
||||
from { background-color: green; }
|
||||
}
|
||||
|
||||
@layer {
|
||||
@keyframes anim {
|
||||
from { background-color: red; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@keyframes override between layers',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
animation: anim 1s paused;
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@keyframes anim {
|
||||
from { background-color: green; }
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@keyframes anim {
|
||||
from { background-color: red; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@keyframes override update with appended sheet 1',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
animation: anim 1s paused;
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@keyframes anim {
|
||||
from { background-color: green; }
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer base {
|
||||
@keyframes anim {
|
||||
from { background-color: red; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@keyframes override update with appended sheet 2',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
animation: anim 1s paused;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@keyframes anim {
|
||||
from { background-color: red; }
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer override {
|
||||
@keyframes anim {
|
||||
from { background-color: green; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
|
||||
var appendedStyle;
|
||||
if (testCase['append']) {
|
||||
document.body.offsetLeft; // Force style update
|
||||
appendedStyle = document.createElement('style');
|
||||
appendedStyle.appendChild(document.createTextNode(testCase['append']));
|
||||
document.head.appendChild(appendedStyle);
|
||||
}
|
||||
|
||||
test(function () {
|
||||
assert_equals(getComputedStyle(target).backgroundColor,
|
||||
getComputedStyle(reference).backgroundColor);
|
||||
}, testCase['title']);
|
||||
|
||||
if (appendedStyle)
|
||||
appendedStyle.remove();
|
||||
documentStyle.remove();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,169 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Cascade Layers: Media queries</title>
|
||||
<meta name="assert" content="CSS Cascade Layers nested in Media Queries">
|
||||
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
|
||||
<link rel="help" href="https://www.w3.org/TR/css-cascade-5/#layering">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe width=300 height=300 frameborder=0></iframe>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
||||
const imports = {
|
||||
"basic-green.css": `
|
||||
target { color: green; }
|
||||
`,
|
||||
"basic-red.css": `
|
||||
target { color: red; }
|
||||
`,
|
||||
"empty.css": "",
|
||||
};
|
||||
|
||||
// For 300px wide iframe the target should be red and for 500px green.
|
||||
const testCases = [
|
||||
{
|
||||
title: 'A1 Basic',
|
||||
style: `
|
||||
@layer { target { color: red } }
|
||||
@media (min-width: 500px) {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'A2 Basic',
|
||||
style: `
|
||||
@media (min-width: 500px) {
|
||||
@layer {
|
||||
target { color: green; }
|
||||
}
|
||||
}
|
||||
@media (max-width: 300px) {
|
||||
@layer {
|
||||
target { color: red; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'B1 Basic import',
|
||||
style: `
|
||||
@import url(basic-red.css) layer;
|
||||
@import url(basic-green.css) layer (min-width: 500px);
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'B2 Basic import',
|
||||
style: `
|
||||
@import url(basic-green.css) layer (min-width: 500px);
|
||||
@import url(basic-red.css) layer (max-width: 300px);
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'C1 Reordering',
|
||||
style: `
|
||||
@media (max-width: 300px) {
|
||||
@layer B {
|
||||
target { color: green; }
|
||||
}
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
}
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
}
|
||||
@layer B {
|
||||
target { color: green; }
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'C2 Reordering',
|
||||
style: `
|
||||
@media (max-width: 300px) {
|
||||
@layer B { }
|
||||
@layer A { target { color: red; } }
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
@layer A { target { color: red; } }
|
||||
@layer B { }
|
||||
}
|
||||
@layer B {
|
||||
target { color: green; }
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'C3 Reordering',
|
||||
style: `
|
||||
@media (max-width: 300px) {
|
||||
@layer B, A;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
@layer A, B;
|
||||
}
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
}
|
||||
@layer B {
|
||||
target { color: green; }
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: 'C4 Reordering',
|
||||
style: `
|
||||
@import url(empty.css) layer(B) (max-width: 300px);
|
||||
@import url(empty.css) layer(A) (max-width: 300px);
|
||||
@import url(empty.css) layer(A) (min-width: 500px);
|
||||
@import url(empty.css) layer(B) (min-width: 500px);
|
||||
@layer A {
|
||||
target { color: red; }
|
||||
}
|
||||
@layer B {
|
||||
target { color: green; }
|
||||
}
|
||||
`
|
||||
},
|
||||
];
|
||||
|
||||
let iframe = document.querySelector("iframe");
|
||||
|
||||
for (let testCase of testCases) {
|
||||
promise_test(async t => {
|
||||
const styleText = testCase['style'].replaceAll(/url\((.+?)\)/g, (match, p1) => {
|
||||
return `url(data:text/css,${ encodeURI(imports[p1]) })`;
|
||||
});
|
||||
|
||||
iframe.width = 300;
|
||||
|
||||
await new Promise(resolve => {
|
||||
iframe.onload = resolve;
|
||||
iframe.srcdoc = `
|
||||
<style>
|
||||
${styleText}
|
||||
</style>
|
||||
<target></target>
|
||||
`;
|
||||
});
|
||||
|
||||
const target = iframe.contentDocument.querySelector('target');
|
||||
assert_equals(getComputedStyle(target).color, 'rgb(255, 0, 0)', testCase['title']);
|
||||
|
||||
iframe.width = 500;
|
||||
|
||||
assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)', testCase['title']);
|
||||
}, testCase['title']);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,154 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Resolving @property name conflicts with cascade layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#target, #reference {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#reference {
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target"></div>
|
||||
<div id="reference"></div>
|
||||
|
||||
<script>
|
||||
// In all tests, background color of #target should be green, same as #reference
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: '@property unlayered overrides layered',
|
||||
style: `
|
||||
#target {
|
||||
background-color: var(--foo);
|
||||
}
|
||||
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: green;
|
||||
}
|
||||
|
||||
@layer {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: red;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@property override between layers',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
background-color: var(--foo);
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: green;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: red;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@property override update with appended sheet 1',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
background-color: var(--foo);
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: green;
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer base {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: red;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@property override update with appended sheet 2',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
background-color: var(--foo);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: red;
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer override {
|
||||
@property --foo {
|
||||
syntax: '<color>';
|
||||
inherits: false;
|
||||
initial-value: green;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
|
||||
var appendedStyle;
|
||||
if (testCase['append']) {
|
||||
document.body.offsetLeft; // Force style update
|
||||
appendedStyle = document.createElement('style');
|
||||
appendedStyle.appendChild(document.createTextNode(testCase['append']));
|
||||
document.head.appendChild(appendedStyle);
|
||||
}
|
||||
|
||||
test(function () {
|
||||
assert_equals(getComputedStyle(target).backgroundColor,
|
||||
getComputedStyle(reference).backgroundColor);
|
||||
}, testCase['title']);
|
||||
|
||||
if (appendedStyle)
|
||||
appendedStyle.remove();
|
||||
documentStyle.remove();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE html>
|
||||
<title>The CSSOM API for Cascade Layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layer-apis">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
const testCases = [
|
||||
{
|
||||
style: `@layer foo { }`,
|
||||
expectedNames: ['foo'],
|
||||
title: 'Basic layer block name',
|
||||
},
|
||||
{
|
||||
style: `@layer { }`,
|
||||
expectedNames: [''],
|
||||
title: 'Anonymous layer block name',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@layer foo;
|
||||
`,
|
||||
expectedNames: [['foo']],
|
||||
title: 'Basic layer statement name',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@layer foo, bar;
|
||||
`,
|
||||
expectedNames: [['foo', 'bar']],
|
||||
title: 'Layer statement with multiple names',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@layer outer {
|
||||
@layer foo.bar { }
|
||||
}
|
||||
@layer outer.foo.bar { }
|
||||
`,
|
||||
expectedNames: ['outer', 'foo.bar', 'outer.foo.bar'],
|
||||
title: 'Nested layer block names',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@layer outer {
|
||||
@layer foo.bar, baz;
|
||||
}
|
||||
@layer outer.foo.bar, outer.baz;
|
||||
`,
|
||||
expectedNames: ['outer', ['foo.bar', 'baz'], ['outer.foo.bar', 'outer.baz']],
|
||||
title: 'Nested layer statement name lists',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@import url('data:text/css,') layer;
|
||||
`,
|
||||
expectedNames: [''],
|
||||
title: 'Import into anonymous layer',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@import url('data:text/css,') layer(foo);
|
||||
`,
|
||||
expectedNames: ['foo'],
|
||||
title: 'Import into named layer',
|
||||
},
|
||||
{
|
||||
style: `
|
||||
@import url('data:text/css,');
|
||||
`,
|
||||
expectedNames: [null],
|
||||
title: 'Import without layer',
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
const style = document.createElement('style');
|
||||
style.appendChild(document.createTextNode(testCase.style));
|
||||
document.head.appendChild(style);
|
||||
|
||||
test(function () {
|
||||
assert_implements(window.CSSLayerBlockRule);
|
||||
assert_implements(window.CSSLayerStatementRule);
|
||||
|
||||
let index = 0;
|
||||
function compareNames(ruleOrSheet) {
|
||||
if (ruleOrSheet instanceof CSSLayerBlockRule)
|
||||
assert_equals(ruleOrSheet.name, testCase.expectedNames[index++]);
|
||||
else if (ruleOrSheet instanceof CSSImportRule)
|
||||
assert_equals(ruleOrSheet.layerName, testCase.expectedNames[index++]);
|
||||
else if (ruleOrSheet instanceof CSSLayerStatementRule)
|
||||
assert_array_equals(ruleOrSheet.nameList, testCase.expectedNames[index++]);
|
||||
if (ruleOrSheet.cssRules) {
|
||||
for (let i = 0; i < ruleOrSheet.cssRules.length; ++i)
|
||||
compareNames(ruleOrSheet.cssRules.item(i));
|
||||
}
|
||||
}
|
||||
compareNames(style.sheet);
|
||||
assert_equals(index, testCase.expectedNames.length);
|
||||
}, testCase.title);
|
||||
|
||||
style.remove();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,183 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Resolving @scroll-timeline name conflicts with cascade layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#scroller div {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
|
||||
#target, #reference {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#reference {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#target {
|
||||
animation: expand 10s linear;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="scroller">
|
||||
<div></div>
|
||||
</div>
|
||||
<div id="target"></div>
|
||||
<div id="reference"></div>
|
||||
|
||||
<script>
|
||||
// In all tests, width of #target should be 150px, same as #reference
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: '@scroll-timeline unlayered overrides layered',
|
||||
style: `
|
||||
#target {
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 50px;
|
||||
}
|
||||
|
||||
@layer {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@scroll-timeline override between layers',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@scroll-timeline override update with appended sheet 1',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
|
||||
@layer override {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 50px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer base {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
title: '@scroll-timeline override update with appended sheet 2',
|
||||
style: `
|
||||
@layer base, override;
|
||||
|
||||
#target {
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
append: `
|
||||
@layer override {
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 50px;
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
promise_test(async function() {
|
||||
assert_true(
|
||||
CSS.supports('animation-timeline', 'foo'),
|
||||
'This test requires @scroll-timeline support');
|
||||
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
|
||||
var appendedStyle;
|
||||
if (testCase['append']) {
|
||||
document.body.offsetLeft; // Force style update
|
||||
appendedStyle = document.createElement('style');
|
||||
appendedStyle.appendChild(document.createTextNode(testCase['append']));
|
||||
document.head.appendChild(appendedStyle);
|
||||
}
|
||||
|
||||
scroller.scrollTop = 25;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).width,
|
||||
getComputedStyle(reference).width);
|
||||
|
||||
if (appendedStyle)
|
||||
appendedStyle.remove();
|
||||
documentStyle.remove();
|
||||
}, testCase['title']);
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<title>::slotted rules should be associated with the correct cascade layers</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="host">
|
||||
<div id="target"></target>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const host = document.getElementById('host');
|
||||
host.attachShadow({mode: 'open'}).innerHTML = `
|
||||
<style>
|
||||
@layer {
|
||||
::slotted(*) {
|
||||
background-color: green !important;
|
||||
}
|
||||
}
|
||||
::slotted(*) {
|
||||
background-color: red !important;
|
||||
}
|
||||
</style>
|
||||
<slot></slot>
|
||||
`;
|
||||
</script>
|
|
@ -0,0 +1,190 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: Empty layer statements before import rules</title>
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="help" href="https://www.w3.org/TR/css-cascade-5/#layering">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<div id="target"></div>
|
||||
<div id="reference" style="color: green"></div>
|
||||
|
||||
<script>
|
||||
// In all test cases, the 'color' property value of #target should be green.
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: 'length and item',
|
||||
style: `
|
||||
@layer first, second;
|
||||
@import url(data:text/css,);
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
assert_equals(sheet.cssRules.length, 4);
|
||||
assert_equals(sheet.cssRules.item(0).cssText, '@layer first, second;');
|
||||
assert_equals(sheet.cssRules.item(1).cssText, `@import url("data:text/css,");`);
|
||||
assert_equals(sheet.cssRules.item(2).cssText,
|
||||
'@layer second {\n #target { color: green; }\n}');
|
||||
assert_equals(sheet.cssRules.item(3).cssText,
|
||||
'@layer first {\n #target { color: red; }\n}');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'insertRule before imports',
|
||||
style: `
|
||||
@import url(data:text/css,);
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
sheet.insertRule('@layer first, second', 0);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'insertRule after imports',
|
||||
style: `
|
||||
@layer first, second;
|
||||
@import url(data:text/css,);
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
sheet.insertRule('@layer second { #target { color: green; } }', 2);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'insert other rules to pre-import layer statements fails',
|
||||
style: `
|
||||
@layer first, second;
|
||||
@import url(data:text/css,);
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
assert_throws_dom('HierarchyRequestError',
|
||||
() => sheet.insertRule('#target { color: red !important; }', 0));
|
||||
assert_throws_dom('HierarchyRequestError',
|
||||
() => sheet.insertRule('#target { color: red !important; }', 1));
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'insert other rules before the first layer statement without imports',
|
||||
style: `
|
||||
@layer first, second;
|
||||
@layer second {
|
||||
#target { color: red !important; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
sheet.insertRule(`@layer first {
|
||||
#target { color: green !important; }
|
||||
}`, 0);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'deleteRule before imports',
|
||||
style: `
|
||||
@layer second, first;
|
||||
@import url(data:text/css,);
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
sheet.deleteRule(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'deleteRule after imports',
|
||||
style: `
|
||||
@layer first, second;
|
||||
@import url(data:text/css,);
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
#target {
|
||||
color: red;
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
sheet.deleteRule(4);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'replaceSync clears stale layer statements',
|
||||
style: `
|
||||
@layer second, first;
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
`,
|
||||
operations: function(sheet) {
|
||||
sheet.replaceSync(`
|
||||
@layer first {
|
||||
#target { color: red; }
|
||||
}
|
||||
@layer second {
|
||||
#target { color: green; }
|
||||
}
|
||||
`);
|
||||
},
|
||||
constructedStyleSheet: true
|
||||
}
|
||||
];
|
||||
|
||||
const target = document.getElementById('target');
|
||||
const reference = document.getElementById('reference');
|
||||
|
||||
for (let testCase of testCases) {
|
||||
promise_test(async t => {
|
||||
let styleElement;
|
||||
let sheet;
|
||||
if (!testCase.constructedStyleSheet) {
|
||||
styleElement = document.createElement('style');
|
||||
styleElement.textContent = testCase.style;
|
||||
await new Promise(resolve => {
|
||||
styleElement.onload = resolve;
|
||||
styleElement.onerror = resolve;
|
||||
document.head.append(styleElement);
|
||||
});
|
||||
sheet = styleElement.sheet;
|
||||
} else {
|
||||
sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync(testCase.style);
|
||||
document.adoptedStyleSheets = [sheet];
|
||||
}
|
||||
|
||||
try {
|
||||
testCase.operations(sheet);
|
||||
assert_equals(getComputedStyle(target).color, getComputedStyle(reference).color);
|
||||
} finally {
|
||||
if (styleElement)
|
||||
styleElement.remove();
|
||||
document.adoptedStyleSheets = [];
|
||||
}
|
||||
}, testCase.title);
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<title>Test important style in anonymous layers with stylesheet sharing</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="layer-stylesheet-sharing-ref.html">
|
||||
<style>
|
||||
target {
|
||||
display: block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green !important}}">
|
||||
<style>
|
||||
@layer A { target { background-color: red !important} }
|
||||
</style>
|
||||
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green !important}}">
|
||||
<target></target>
|
|
@ -0,0 +1,10 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
target {
|
||||
display: block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
<target></target>
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<title>Test anonymous layers with stylesheet sharing</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1730123">
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="match" href="layer-stylesheet-sharing-ref.html">
|
||||
<style>
|
||||
target {
|
||||
display: block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green}}">
|
||||
<style>
|
||||
@layer A { target { background-color: red } }
|
||||
</style>
|
||||
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green}}">
|
||||
<target></target>
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#cascade-sort">
|
||||
<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#target, #reference {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#reference {
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target"></div>
|
||||
<div id="reference"></div>
|
||||
|
||||
<script>
|
||||
// In all tests, #target should have green background color, same as #reference
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
title: 'Normal inline style > normal layered style',
|
||||
style: '@layer { #target { background-color: red; }}',
|
||||
inlineStyle: 'background-color: green'
|
||||
},
|
||||
{
|
||||
title: 'Normal inline style < important layered style',
|
||||
style: '@layer { #target { background-color: green !important; }}',
|
||||
inlineStyle: 'background-color: red'
|
||||
},
|
||||
{
|
||||
title: 'Important inline style > normal layered style',
|
||||
style: '@layer { #target { background-color: red; }}',
|
||||
inlineStyle: 'background-color: green !important'
|
||||
},
|
||||
{
|
||||
title: 'Important inline style > important layered style',
|
||||
style: '@layer { #target { background-color: red !important; }}',
|
||||
inlineStyle: 'background-color: green !important'
|
||||
},
|
||||
];
|
||||
|
||||
for (let testCase of testCases) {
|
||||
var documentStyle = document.createElement('style');
|
||||
documentStyle.appendChild(document.createTextNode(testCase['style']));
|
||||
document.head.appendChild(documentStyle);
|
||||
|
||||
target.style = testCase['inlineStyle'];
|
||||
|
||||
test(function () {
|
||||
assert_equals(getComputedStyle(target).backgroundColor,
|
||||
getComputedStyle(reference).backgroundColor);
|
||||
}, testCase['title']);
|
||||
|
||||
documentStyle.remove();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,79 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>@import rule with layer parsing / serialization</title>
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#at-import">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
function setupSheet(rule) {
|
||||
const style = document.createElement("style");
|
||||
document.head.append(style);
|
||||
const {sheet} = style;
|
||||
const {cssRules} = sheet;
|
||||
|
||||
assert_equals(cssRules.length, 0, "Sheet should have no rules");
|
||||
sheet.insertRule(rule);
|
||||
assert_equals(cssRules.length, 1, "Sheet should have 1 rule");
|
||||
|
||||
return {sheet, cssRules};
|
||||
}
|
||||
|
||||
function test_valid_layer_import(rule, serialized) {
|
||||
if (serialized === undefined)
|
||||
serialized = rule;
|
||||
|
||||
test(function() {
|
||||
const {sheet, cssRules} = setupSheet(rule);
|
||||
|
||||
const serialization = cssRules[0].cssText;
|
||||
assert_equals(serialization, serialized, 'serialization should be canonical');
|
||||
|
||||
const media = cssRules[0].media;
|
||||
assert_equals(media.length, 0, 'layer() should be valid');
|
||||
|
||||
sheet.deleteRule(0);
|
||||
assert_equals(cssRules.length, 0, 'Sheet should have no rule');
|
||||
sheet.insertRule(serialization);
|
||||
assert_equals(cssRules.length, 1, 'Sheet should have 1 rule');
|
||||
|
||||
assert_equals(cssRules[0].cssText, serialization, 'serialization should round-trip');
|
||||
}, rule + ' should be a valid layered import rule');
|
||||
}
|
||||
|
||||
function test_invalid_layer_import(rule) {
|
||||
test(function() {
|
||||
const {sheet, cssRules} = setupSheet(rule);
|
||||
|
||||
const media = cssRules[0].media;
|
||||
assert_not_equals(media.length, 0,
|
||||
'invalid layer declaration should be parsed as <general-enclosed> media query');
|
||||
|
||||
sheet.deleteRule(0);
|
||||
assert_equals(cssRules.length, 0, 'Sheet should have no rule');
|
||||
}, rule + ' should still be a valid import rule with an invalid layer declaration');
|
||||
}
|
||||
|
||||
test_valid_layer_import('@import url("nonexist.css") layer;');
|
||||
test_valid_layer_import('@import url("nonexist.css") layer(A);');
|
||||
test_valid_layer_import('@import url("nonexist.css") layer(A.B);');
|
||||
|
||||
test_valid_layer_import('@import url(nonexist.css) layer;',
|
||||
'@import url("nonexist.css") layer;');
|
||||
test_valid_layer_import('@import url(nonexist.css) layer(A);',
|
||||
'@import url("nonexist.css") layer(A);');
|
||||
test_valid_layer_import('@import url(nonexist.css) layer(A.B);',
|
||||
'@import url("nonexist.css") layer(A.B);');
|
||||
|
||||
test_valid_layer_import('@import "nonexist.css" layer;',
|
||||
'@import url("nonexist.css") layer;');
|
||||
test_valid_layer_import('@import "nonexist.css" layer(A);',
|
||||
'@import url("nonexist.css") layer(A);');
|
||||
test_valid_layer_import('@import "nonexist.css" layer(A.B);',
|
||||
'@import url("nonexist.css") layer(A.B);');
|
||||
|
||||
test_invalid_layer_import('@import url("nonexist.css") layer();');
|
||||
test_invalid_layer_import('@import url("nonexist.css") layer(A B);');
|
||||
test_invalid_layer_import('@import url("nonexist.css") layer(A . B);');
|
||||
test_invalid_layer_import('@import url("nonexist.css") layer(A, B, C);');
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>@layer rule parsing / serialization</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
<script>
|
||||
test_valid_rule("@layer A;");
|
||||
test_valid_rule("@layer A, B, C;");
|
||||
test_valid_rule("@layer A.A;");
|
||||
test_valid_rule("@layer A, B.C.D, C;");
|
||||
|
||||
test_invalid_rule("@layer;");
|
||||
test_invalid_rule("@layer A . A;");
|
||||
|
||||
test_valid_rule("@layer {\n}");
|
||||
test_valid_rule("@layer A {\n}");
|
||||
test_valid_rule("@layer A.B {\n}");
|
||||
test_invalid_rule("@layer A . B {\n}");
|
||||
|
||||
test_invalid_rule("@layer A, B, C {\n}");
|
||||
</script>
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#preshint">
|
||||
<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
.test {
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
#target1 {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target3 {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<img class=test id=target1 width=200>
|
||||
<img class=test id=target2 width=200 style="width: 100px">
|
||||
<img class=test id=target3 width=200>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(target1).width, '100px');
|
||||
}, 'Presentational hints have lower precedence than regular author style sheets');
|
||||
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(target2).width, '100px');
|
||||
}, 'Presentational hints have lower precedence than the style attribute');
|
||||
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(target3).width, '100px');
|
||||
}, 'Presentational hints have lower precedence than layered style');
|
||||
</script>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' from one explicit layer to another</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target { background-color: green; }
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: revert-layer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' from the implicit outer layer to explicit</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target { background-color: green; }
|
||||
}
|
||||
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: revert-layer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'all: revert-layer'</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
@layer {
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
}
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
#target {
|
||||
all: revert-layer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' to previous context</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: red;
|
||||
background-color: revert-layer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
||||
|
||||
<script>
|
||||
target.attachShadow({mode: 'open'}).innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
</script>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: important 'revert-layer'</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target { background-color: green; }
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: red !important;
|
||||
background-color: revert-layer !important;
|
||||
}
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: red !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' reverts origin when no lower priority declarations in the same origin</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#outer {
|
||||
background-color: red;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#inner {
|
||||
color: green;
|
||||
background-color: green;
|
||||
display: inline;
|
||||
display: revert-layer; /* This should behave as 'revert', setting 'display' to 'block' */
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="outer">
|
||||
<div id="inner">
|
||||
This<br>
|
||||
is<br>
|
||||
filler<br>
|
||||
text.<br>
|
||||
This<br>
|
||||
is<br>
|
||||
filler<br>
|
||||
text.
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' chain</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target { background-color: green; }
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: revert-layer;
|
||||
}
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: revert-layer;
|
||||
}
|
||||
}
|
||||
|
||||
@layer {
|
||||
#target {
|
||||
background-color: red;
|
||||
background-color: revert-layer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' triggers a smooth transition</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<style>
|
||||
@layer revert-to, revert-from;
|
||||
|
||||
@layer revert-from {
|
||||
#target {
|
||||
font-size: 10px;
|
||||
transition: font-size 2s linear -1s;
|
||||
}
|
||||
|
||||
#target.reverted {
|
||||
font-size: revert-layer;
|
||||
}
|
||||
}
|
||||
|
||||
@layer revert-to {
|
||||
#target { font-size: 20px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="target"></div>
|
||||
|
||||
<script>
|
||||
function raf() {
|
||||
return new Promise(resolve => requestAnimationFrame(resolve));
|
||||
}
|
||||
promise_test(async () => {
|
||||
const target = document.getElementById('target');
|
||||
getComputedStyle(target).getPropertyValue('font-size');
|
||||
|
||||
await raf();
|
||||
target.classList.toggle('reverted');
|
||||
|
||||
const result = getComputedStyle(target).getPropertyValue('font-size');
|
||||
assert_equals(result, '15px');
|
||||
}, "'revert-layer' should revert font-size to 20px and trigger a smooth transition");
|
||||
</script>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' from the style attribute to other style sheets</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target" style="background-color: red; background-color: revert-layer"></div>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' from animation origin to author origin</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
animation: anim linear 2s -1s paused;
|
||||
}
|
||||
|
||||
@keyframes anim {
|
||||
from { width: 50px; }
|
||||
to { width: revert-layer; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: 'revert-layer' from animation origin to author origin on custom property</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: var(--x);
|
||||
--x: 150px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
animation: anim linear 2s -1s paused;
|
||||
}
|
||||
|
||||
@property --x {
|
||||
syntax: '<length>';
|
||||
initial-value: 0px;
|
||||
inherits: false;
|
||||
}
|
||||
|
||||
@keyframes anim {
|
||||
from { --x: 50px; }
|
||||
to { --x: revert-layer; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target"></div>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Cascade Layers: important 'revert-layer' from the style attribute to other style sheets</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
|
||||
<link rel="author" href="mailto:xiaochengh@chromium.org">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
|
||||
<style>
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="target" style="background-color: red !important; background-color: revert-layer !important"></div>
|
|
@ -7,7 +7,6 @@
|
|||
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#default">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="On a <div>, display:revert should compute to display:block per the default styles for <div>s in the UA stylesheet.">
|
||||
<style>
|
||||
#outer {
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#inherit-initial">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#inherit-initial">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="color:unset is the same as color:inherit since color is an inherited property. background-color:unset is the same as background-color:initial since background-color is a non-inherited property.">
|
||||
<style>
|
||||
.square {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#inherit-initial">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#inherit-initial">
|
||||
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="display:unset should be the same as display:initial since 'display' is not an inherited property. display:unset should be the same as display:inline since 'inline' is the initial value of 'display'.">
|
||||
<style>
|
||||
.square {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue