Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /css/css-properties-values-api/determine-registration.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/utils.js"></script>
<div id=outer>
<div id=div></div>
</div>
<script>
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '1px'
}, (name) => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '1px');
}, '@property determines the registration when uncontested');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '2px'
}, (name) => {
CSS.registerProperty({
name: name,
syntax: '<color>',
inherits: false,
initialValue: 'green'
});
assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(0, 128, 0)');
}, 'CSS.registerProperty wins over @property');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '3px'
}, (name1) => {
with_at_property({
name: name1,
syntax: '"<integer>"',
inherits: false,
initialValue: '6'
}, (name2) => {
assert_equals(name1, name2);
assert_equals(getComputedStyle(div).getPropertyValue(name2), '6');
});
}, '@property later in document order wins');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '10px'
}, (name1) => {
with_at_property({
name: name1,
syntax: '"<length>"',
inherits: true,
initialValue: '20px'
}, (name2) => {
assert_equals(name1, name2);
assert_equals(getComputedStyle(div).getPropertyValue(name2), '20px');
});
}, '@property later in document order wins (overridding definition with inherits=true)');
test_with_at_property({
syntax: '"<length>"',
inherits: true,
initialValue: '10px'
}, (name1) => {
with_at_property({
name: name1,
syntax: '"<length>"',
inherits: false,
initialValue: '20px'
}, (name2) => {
assert_equals(name1, name2);
assert_equals(getComputedStyle(div).getPropertyValue(name2), '20px');
});
}, '@property later in document order wins (overridding definition with inherits=false)');
test(() => {
let name = generate_name();
with_style_node(`
@property ${name} {
syntax: "<length>";
inherits: false;
initial-value: 4px;
}
@property ${name} {
syntax: "<color>";
inherits: false;
initial-value: red;
}
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(255, 0, 0)');
});
}, '@property later in stylesheet wins');
test(() => {
let name = generate_name();
CSS.registerProperty({
name: name,
syntax: '<color>',
inherits: false,
initialValue: 'green'
});
assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(0, 128, 0)');
}, 'CSS.registerProperty determines the registration when uncontested');
test(() => {
let name = generate_name();
// ${name} is initially not registered, hence has no initial value.
assert_equals(getComputedStyle(div).getPropertyValue(name), '');
with_at_property({
name: name,
syntax: '"<length>"',
inherits: false,
initialValue: '10px'
}, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '10px');
});
// When the style node is removed, ${name} should be unregistered again.
assert_equals(getComputedStyle(div).getPropertyValue(name), '');
}, '@property registrations are cleared when rule removed');
test(() => {
let name = generate_name();
with_style_node(`div { ${name}: calc(1px + 1px); }`, () => {
// ${name} should be a token sequence at this point.
assert_equals(getComputedStyle(div).getPropertyValue(name), 'calc(1px + 1px)');
with_at_property({
name: name,
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, () => {
// ${name} is now a <length>, hence the calc() should be simplified.
assert_equals(getComputedStyle(div).getPropertyValue(name), '2px');
});
// ${name} should be a token sequence again.
assert_equals(getComputedStyle(div).getPropertyValue(name), 'calc(1px + 1px)');
});
}, 'Computed value becomes token sequence when @property is removed');
test(() => {
let name = generate_name();
with_style_node(`#outer { ${name}: 10px; }`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '10px');
with_at_property({
name: name,
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, () => {
// ${name} is no longer inherited
assert_equals(getComputedStyle(div).getPropertyValue(name), '0px');
});
assert_equals(getComputedStyle(div).getPropertyValue(name), '10px');
});
}, 'Inherited status is reflected in computed styles when @property is removed');
test(() => {
let name = generate_name();
with_style_node(`
@property ${name} {
syntax: "<length>";
inherits: false;
initial-value: 1px;
}
@property ${name} {
inherits: false;
initial-value: green;
}
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '1px');
});
}, 'Invalid @property rule (missing syntax) does not overwrite previous valid rule');
test(() => {
let name = generate_name();
with_style_node(`
@property ${name} {
syntax: "<length>";
inherits: false;
initial-value: 1px;
}
@property ${name} {
syntax: "<color>";
initial-value: green;
}
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '1px');
});
}, 'Invalid @property rule (missing inherits descriptor) does not overwrite previous valid rule');
test(() => {
let name = generate_name();
with_style_node(`
@property ${name} {
syntax: "<length>";
inherits: false;
initial-value: 1px;
}
@property ${name} {
syntax: "<color>";
inherits: false;
}
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '1px');
});
}, 'Invalid @property rule (missing initial-value) does not overwrite previous valid rule');
test(() => {
let name = generate_name();
with_style_node(`
@property ${name} {
syntax: "<color>";
inherits: false;
}
@property ${name} {
syntax: "<length>";
inherits: false;
initial-value: 1px;
}
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '1px');
});
}, 'Previous invalid rule does not prevent valid rule from causing registration');
test(() => {
let name = generate_name();
with_style_node(`
@property ${name} {
syntax: "<length>";
inherits: false;
initial-value: 1px;
quite-unknown: 200;
}
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '1px');
});
}, 'Unknown descriptors are ignored and do not invalidate rule');
</script>