<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Color Level 4: Computation of colors using RGB notation</title>
<link rel="help" href="https://drafts.csswg.org/css-color-4/#rgb-functions">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#resolving-sRGB-values">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#serializing-sRGB-values">
<link rel="author" title="Chris Nardi" href="mailto:[email protected]">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
</head>
<body>
<div id="container">
<div id="target"></div>
</div>
<style>
:root {
--high: 500;
--negative: -100;
}
#container {
color: rgb(255, 0, 0);
}
</style>
<script>
tests = [
["rgb(none none none)", "rgb(0, 0, 0)"],
["rgb(none none none / none)", "rgba(0, 0, 0, 0)"],
["rgb(128 none none)", "rgb(128, 0, 0)"],
["rgb(128 none none / none)", "rgba(128, 0, 0, 0)"],
["rgb(none none none / .5)", "rgba(0, 0, 0, 0.5)"],
["rgb(20% none none)", "rgb(51, 0, 0)"],
["rgb(20% none none / none)", "rgba(51, 0, 0, 0)"],
["rgb(none none none / 50%)", "rgba(0, 0, 0, 0.5)"],
["rgba(none none none)", "rgb(0, 0, 0)"],
["rgba(none none none / none)", "rgba(0, 0, 0, 0)"],
["rgba(128 none none)", "rgb(128, 0, 0)"],
["rgba(128 none none / none)", "rgba(128, 0, 0, 0)"],
["rgba(none none none / .5)", "rgba(0, 0, 0, 0.5)"],
["rgba(20% none none)", "rgb(51, 0, 0)"],
["rgba(20% none none / none)", "rgba(51, 0, 0, 0)"],
["rgba(none none none / 50%)", "rgba(0, 0, 0, 0.5)"],
["rgb(2.5, 3.4, 4.6)", ["rgb(3, 3, 5)", "rgb(2.5, 3.4, 4.6)"], "Tests that RGB channels are rounded appropriately"],
["rgb(00, 51, 102)", "rgb(0, 51, 102)", "Valid numbers should be parsed"],
["r\\gb(00, 51, 102)", "rgb(0, 51, 102)", "Correct escape sequences should still parse"],
["r\\67 b(00, 51, 102)", "rgb(0, 51, 102)", "Correct escape sequences should still parse"],
["RGB(153, 204, 255)", "rgb(153, 204, 255)", "Capitalization should not affect parsing"],
["rgB(0, 0, 0)", "rgb(0, 0, 0)", "Capitalization should not affect parsing"],
["rgB(0, 51, 255)", "rgb(0, 51, 255)", "Capitalization should not affect parsing"],
["rgb(0,51,255)", "rgb(0, 51, 255)", "Lack of whitespace should not affect parsing"],
["rgb(0\t, 51 ,255)", "rgb(0, 51, 255)", "Whitespace should not affect parsing"],
["rgb(/* R */0, /* G */51, /* B */255)", "rgb(0, 51, 255)", "Comments should be allowed within function"],
["rgb(-51, 306, 0)", "rgb(0, 255, 0)", "Invalid values should be clamped to 0 and 255 respectively"],
["rgb(42%, 3%, 50%)", "rgb(107, 8, 128)", "Valid percentages should be parsed"],
["RGB(100%, 100%, 100%)", "rgb(255, 255, 255)", "Capitalization should not affect parsing"],
["rgB(0%, 0%, 0%)", "rgb(0, 0, 0)", "Capitalization should not affect parsing"],
["rgB(10%, 20%, 30%)", "rgb(26, 51, 77)", "Capitalization should not affect parsing"],
["rgb(10%,20%,30%)", "rgb(26, 51, 77)", "Whitespace should not affect parsing"],
["rgb(10%\t, 20% ,30%)", "rgb(26, 51, 77)", "Whitespace should not affect parsing"],
["rgb(/* R */ 10%, /* G */ 20%, /* B */ 30%)", "rgb(26, 51, 77)", "Comments should not affect parsing"],
["rgb(-12%, 110%, 1400%)", "rgb(0, 255, 255)", "Invalid values should be clamped to 0 and 255 respectively"],
["rgb(0, 0, 0, 0)", "rgba(0, 0, 0, 0)", "RGB and RGBA are synonyms"],
["rgb(0%, 0%, 0%, 0%)", "rgba(0, 0, 0, 0)", "RGB and RGBA are synonyms"],
["rgb(0%, 0%, 0%, 0)", "rgba(0, 0, 0, 0)", "RGB and RGBA are synonyms"],
["rgba(0, 0, 0, 0)", "rgba(0, 0, 0, 0)", "Valid numbers should be parsed"],
["rgba(204, 0, 102, 0.3)", "rgba(204, 0, 102, 0.3)", "Valid numbers should be parsed"],
["RGBA(255, 255, 255, 0)", "rgba(255, 255, 255, 0)", "Capitalization should not affect parsing"],
["rgBA(0, 51, 255, 1)", "rgb(0, 51, 255)", "Capitalization should not affect parsing"],
["rgba(0, 51, 255, 1.1)", "rgb(0, 51, 255)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(0, 51, 255, 37)", "rgb(0, 51, 255)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(0, 51, 255, 0.42)", "rgba(0, 51, 255, 0.42)", "Valid numbers should be parsed"],
["rgba(0, 51, 255, 0)", "rgba(0, 51, 255, 0)", "Valid numbers should be parsed"],
["rgba(0, 51, 255, -0.1)", "rgba(0, 51, 255, 0)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(0, 51, 255, -139)", "rgba(0, 51, 255, 0)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["RGBA(100%, 100%, 100%, 0)", "rgba(255, 255, 255, 0)", "Capitalization should not affect parsing"],
["rgba(42%, 3%, 50%, 0.3)", "rgba(107, 8, 128, 0.3)", "Valid percentages should be parsed"],
["rgBA(0%, 20%, 100%, 1)", "rgb(0, 51, 255)", "Capitalization should not affect parsing"],
["rgba(0%, 20%, 100%, 1.1)", "rgb(0, 51, 255)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(0%, 20%, 100%, 37)", "rgb(0, 51, 255)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(0%, 20%, 100%, 0.42)", "rgba(0, 51, 255, 0.42)", "Valid percentages should be parsed"],
["rgba(0%, 20%, 100%, 0)", "rgba(0, 51, 255, 0)", "Valid percentages should be parsed"],
["rgba(0%, 20%, 100%, -0.1)", "rgba(0, 51, 255, 0)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(0%, 20%, 100%, -139)", "rgba(0, 51, 255, 0)", "Invalid alpha values should be clamped to 0 and 1 respectively"],
["rgba(255, 255, 255, 0%)", "rgba(255, 255, 255, 0)", "Percent alpha values are accepted in rgb/rgba"],
["rgba(0%, 0%, 0%, 0%)", "rgba(0, 0, 0, 0)", "Percent alpha values are accepted in rgb/rgba"],
["rgba(0%, 0%, 0%)", "rgb(0, 0, 0)", "RGB and RGBA are synonyms"],
["rgba(0, 0, 0)", "rgb(0, 0, 0)", "RGB and RGBA are synonyms"],
// rgb are in the range [0, 255], alpha is in the range [0, 1].
// calc(infinity) resolves to the upper bound while calc(-infinity) and calc(NaN) resolves the lower bound.
// See: https://github.com/w3c/csswg-drafts/issues/8629
["rgb(calc(infinity), 0, 0)", "rgb(255, 0, 0)", "Red channel resolves positive infinity to 255"],
["rgb(0, calc(infinity), 0)", "rgb(0, 255, 0)", "Green channel resolves positive infinity to 255"],
["rgb(0, 0, calc(infinity))", "rgb(0, 0, 255)", "Blue channel resolves positive infinity to 255"],
["rgba(0, 0, 0, calc(infinity))", "rgb(0, 0, 0)", "Alpha channel resolves positive infinity to fully opaque"],
["rgb(calc(-infinity), 0, 0)", "rgb(0, 0, 0)", "Red channel resolves negative infinity to zero"],
["rgb(0, calc(-infinity), 0)", "rgb(0, 0, 0)", "Green channel resolves negative infinity to zero"],
["rgb(0, 0, calc(-infinity))", "rgb(0, 0, 0)", "Blue channel resolves negative infinity to zero"],
["rgba(0, 0, 0, calc(-infinity))", "rgba(0, 0, 0, 0)", "Alpha channel resolves negative infinity to fully transparent"],
["rgb(calc(NaN), 0, 0)", "rgb(0, 0, 0)", "Red channel resolves NaN to zero"],
["rgb(0, calc(NaN), 0)", "rgb(0, 0, 0)", "Green channel resolves NaN to zero"],
["rgb(0, 0, calc(NaN))", "rgb(0, 0, 0)", "Blue channel resolves NaN to zero"],
["rgba(0, 0, 0, calc(NaN))", "rgba(0, 0, 0, 0)", "Alpha channel resolves NaN to zero"],
["rgb(calc(0 / 0), 0, 0)", "rgb(0, 0, 0)", "Red channel resolves NaN equivalent calc statements to zero"],
["rgb(0, calc(0 / 0), 0)", "rgb(0, 0, 0)", "Green channel resolves NaN equivalent calc statements to zero"],
["rgb(0, 0, calc(0 / 0))", "rgb(0, 0, 0)", "Blue channel resolves NaN equivalent calc statements to zero"],
["rgba(0, 0, 0, calc(0 / 0))", "rgba(0, 0, 0, 0)", "Alpha channel resolves NaN equivalent calc statements to zero"],
["rgb(var(--high), 0, 0)", "rgb(255, 0, 0)", "Variables above 255 get clamped to 255."],
["rgb(var(--negative), 64, 128)", "rgb(0, 64, 128)", "Variables below 0 get clamped to 0."],
];
for (const test of tests) {
test_computed_value("color", test[0], test[1], test[2] ? `[${test[2]}]` : undefined);
}
</script>
</body>
</html>