| <!doctype html> |
| <title>CSS Container Queries Test: custom property style queries</title> |
| <link rel="help" href="https://drafts.csswg.org/css-conditional-5/#style-container"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="support/cq-testcommon.js"></script> |
| <style> |
| #outer { |
| container-name: outer; |
| --inner: false; |
| --outer: true; |
| --inner-no-space:false; |
| --outer-no-space:true; |
| --inner-space-after:false ; |
| --outer-space-after:true ; |
| } |
| #inner { |
| --inner: true; |
| --outer: false; |
| --inner-no-space:true; |
| --outer-no-space:false; |
| --inner-space-after:true ; |
| --outer-space-after:false ; |
| } |
| </style> |
| <div id="outer"> |
| <div id="inner"> |
| <div id="target"></div> |
| <div id="fliptarget"></div> |
| </div> |
| </div> |
| <script> |
| setup(() => { |
| assert_implements_style_container_queries(); |
| assert_implements_size_container_queries(); |
| }); |
| |
| const green = "rgb(0, 128, 0)"; |
| |
| function test_evaluation(name, query, expected) { |
| test((t) => { |
| let style_node = document.createElement('style'); |
| t.add_cleanup(() => { |
| style_node.remove(); |
| }); |
| style_node.innerText = ` |
| @container ${name} ${query} { #target { --applied:true; } } |
| @container ${name} not ${query} { #fliptarget { --applied:true; } } |
| `; |
| |
| assert_equals(getComputedStyle(target).getPropertyValue('--applied'), '', |
| 'Initial --applied for target'); |
| assert_equals(getComputedStyle(fliptarget).getPropertyValue('--applied'), '', |
| 'Initial --applied for fliptarget'); |
| document.head.append(style_node); |
| assert_equals(getComputedStyle(target).getPropertyValue('--applied'), expected ? 'true' : '', |
| 'Matching query for #target'); |
| assert_equals(getComputedStyle(fliptarget).getPropertyValue('--applied'), expected ? '' : 'true', |
| 'Matching negated query for #fliptarget'); |
| }, `${name} ${query}`); |
| } |
| |
| setup(() => { |
| assert_implements_style_container_queries(); |
| assert_implements_size_container_queries(); |
| }); |
| |
| test_evaluation('', 'style(--inner: true)', true); |
| test_evaluation('', 'style(--inner:true)', true); |
| test_evaluation('', 'style(--inner:true )', true); |
| test_evaluation('', 'style(--inner: true )', true); |
| test_evaluation('', 'style(--inner-no-space: true)', true); |
| test_evaluation('', 'style(--inner-no-space:true)', true); |
| test_evaluation('', 'style(--inner-no-space:true )', true); |
| test_evaluation('', 'style(--inner-no-space: true )', true); |
| test_evaluation('', 'style(--inner-space-after: true)', true); |
| test_evaluation('', 'style(--inner-space-after:true)', true); |
| test_evaluation('', 'style(--inner-space-after:true )', true); |
| test_evaluation('', 'style(--inner-space-after: true )', true); |
| test_evaluation('', 'style(--outer: true)', false); |
| test_evaluation('', 'style(--outer:true)', false); |
| test_evaluation('', 'style(--outer:true )', false); |
| test_evaluation('', 'style(--outer: true )', false); |
| test_evaluation('', 'style(--outer-no-space: true)', false); |
| test_evaluation('', 'style(--outer-no-space:true)', false); |
| test_evaluation('', 'style(--outer-no-space:true )', false); |
| test_evaluation('', 'style(--outer-no-space: true )', false); |
| test_evaluation('', 'style(--outer-space-after: true)', false); |
| test_evaluation('', 'style(--outer-space-after:true)', false); |
| test_evaluation('', 'style(--outer-space-after:true )', false); |
| test_evaluation('', 'style(--outer-space-after: true )', false); |
| test_evaluation('outer', 'style(--inner: true)', false); |
| test_evaluation('outer', 'style(--inner:true)', false); |
| test_evaluation('outer', 'style(--inner:true )', false); |
| test_evaluation('outer', 'style(--inner: true )', false); |
| test_evaluation('outer', 'style(--inner-no-space: true)', false); |
| test_evaluation('outer', 'style(--inner-no-space:true)', false); |
| test_evaluation('outer', 'style(--inner-no-space:true )', false); |
| test_evaluation('outer', 'style(--inner-no-space: true )', false); |
| test_evaluation('outer', 'style(--inner-space-after: true)', false); |
| test_evaluation('outer', 'style(--inner-space-after:true)', false); |
| test_evaluation('outer', 'style(--inner-space-after:true )', false); |
| test_evaluation('outer', 'style(--inner-space-after: true )', false); |
| test_evaluation('outer', 'style(--outer: true)', true); |
| test_evaluation('outer', 'style(--outer:true)', true); |
| test_evaluation('outer', 'style(--outer:true )', true); |
| test_evaluation('outer', 'style(--outer: true )', true); |
| test_evaluation('outer', 'style(--outer-no-space: true)', true); |
| test_evaluation('outer', 'style(--outer-no-space:true)', true); |
| test_evaluation('outer', 'style(--outer-no-space:true )', true); |
| test_evaluation('outer', 'style(--outer-no-space: true )', true); |
| test_evaluation('outer', 'style(--outer-space-after: true)', true); |
| test_evaluation('outer', 'style(--outer-space-after:true)', true); |
| test_evaluation('outer', 'style(--outer-space-after:true )', true); |
| test_evaluation('outer', 'style(--outer-space-after: true )', true); |
| </script> |
| |
| <style> |
| #important { |
| --foo: bar; |
| } |
| @container style(--foo: bar !important) { |
| #important-child { color: green; } |
| } |
| </style> |
| <div id="important"> |
| <div id="important-child"></div> |
| </div> |
| <script> |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#important-child")).color, green); |
| }, "Query custom property with !important declaration"); |
| </script> |
| |
| <style> |
| #var-query { |
| --foo: baz; |
| --bar: baz; |
| } |
| @container style(--foo: var(--bar)) { |
| #var-subst { color: green; } |
| } |
| @container not style(--foo: var(--unknown)) { |
| #var-subst-unknown { color: green; } |
| } |
| @container not style(--foo: var(--unknown, nomatch)) { |
| #var-subst-unknown-fallback { color: green; } |
| } |
| @container style(--foo: var(--unknown, baz)) { |
| #var-subst-matching-fallback { color: green; } |
| } |
| @container style(--baz: var(--unknown)) { |
| #var-subst-unknown-matching { color: green; } |
| } |
| </style> |
| <div id="var-query"> |
| <div id="var-subst"></div> |
| <div id="var-subst-unknown"></div> |
| <div id="var-subst-unknown-fallback"></div> |
| <div id="var-subst-matching-fallback"></div> |
| <div id="var-subst-unknown-matching"></div> |
| </div> |
| <script> |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#var-subst")).color, green); |
| }, "Query custom property using var()"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#var-subst-unknown")).color, green); |
| }, "Query custom property including unknown var() reference"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#var-subst-unknown-fallback")).color, green); |
| }, "Query custom property including unknown var() reference with non-matching fallback"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#var-subst-matching-fallback")).color, green); |
| }, "Query custom property including unknown var() reference with matching fallback"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#var-subst-unknown-matching")).color, green); |
| }, "Query custom property matching guaranteed-invalid values"); |
| </script> |
| |
| <style> |
| #revert { |
| --foo: revert; |
| } |
| #revert-layer { |
| --foo: revert-layer; |
| } |
| @container not style(--foo: revert) { |
| #revert-child { color: green; } |
| } |
| @container not style(--foo: revert-layer) { |
| #revert-layer-child { color: green; } |
| } |
| @container style(--foo: revert) { |
| #revert-child { color: red; } |
| } |
| @container style(--foo: revert-layer) { |
| #revert-layer-child { color: red; } |
| } |
| </style> |
| <div id="revert"> |
| <div id="revert-child"></div> |
| </div> |
| <div id="revert-layer"> |
| <div id="revert-layer-child"></div> |
| </div> |
| <script> |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#revert-child")).color, green); |
| }, "Style query with revert keyword is false"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#revert-layer-child")).color, green); |
| }, "Style query with revert-layer keyword is false"); |
| </script> |
| |
| <style> |
| #defaulting { |
| --inherit: baz; |
| --inherit-no: baz; |
| } |
| #defaulting-container { |
| --inherit-no: bar; |
| --unset-no: baz; |
| --initial-no: baz; |
| --space-no: baz; |
| --explicit-initial: initial; |
| --space: ; |
| } |
| @container style(--initial: initial) { |
| #initial { color: green; } |
| } |
| @container not style(--initial) { |
| #initial-implicit { color: green; } |
| } |
| @container not style(--initial-no: initial) { |
| #initial-no { color: green; } |
| } |
| @container style(--initial-no) { |
| #initial-no-implicit { color: green; } |
| } |
| @container style(--inherit: inherit) { |
| #inherit { color: green; } |
| } |
| @container not style(--inherit-no: inherit) { |
| #inherit-no { color: green; } |
| } |
| @container style(--explicit-initial: initial) { |
| #explicit-initial { color: green; } |
| } |
| @container not style(--explicit-initial) { |
| #explicit-initial-implicit { color: green; } |
| } |
| @container style(--space: ) { |
| #space { color: green; } |
| } |
| @container not style(--space-no: ) { |
| #space-no { color: green; } |
| } |
| @container style(--unset: unset) { |
| #unset { color: green; } |
| } |
| @container not style(--unset-no: unset) { |
| #unset-no { color: green; } |
| } |
| </style> |
| <div id="defaulting"> |
| <div id="defaulting-container"> |
| <div id="initial"></div> |
| <div id="initial-implicit"></div> |
| <div id="initial-no"></div> |
| <div id="initial-no-implicit"></div> |
| <div id="explicit-initial"></div> |
| <div id="explicit-initial-implicit"></div> |
| <div id="space"></div> |
| <div id="space-no"></div> |
| <div id="inherit"></div> |
| <div id="inherit-no"></div> |
| <div id="unset"></div> |
| <div id="unset-no"></div> |
| </div> |
| </div> |
| <script> |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#initial")).color, green); |
| }, "Style query 'initial' matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#initial-implicit")).color, green); |
| }, "Style query matching negated value-less query against initial value"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#initial-no")).color, green); |
| }, "Style query 'initial' not matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#initial-no-implicit")).color, green); |
| }, "Style query matching value-less query against non-initial value"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#explicit-initial")).color, green); |
| }, "Style query 'initial' matching (with explicit 'initial' value)"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#explicit-initial-implicit")).color, green); |
| }, "Style query matching negated value-less query against initial value (with explicit 'initial' value)"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#space")).color, green); |
| }, "Style query 'space' matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#space-no")).color, green); |
| }, "Style query 'space' not matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#inherit")).color, green); |
| }, "Style query 'inherit' matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#inherit-no")).color, green); |
| }, "Style query 'inherit' not matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#unset")).color, green); |
| }, "Style query 'unset' matching"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#unset-no")).color, green); |
| }, "Style query 'unset' not matching"); |
| </script> |
| |
| <style> |
| @property --reg-length { |
| syntax: "<length>"; |
| inherits: false; |
| initial-value: 10px; |
| } |
| |
| #registered { |
| container-type: inline-size; |
| width: 200px; |
| font-size: 20px; |
| } |
| |
| #reg-container-px { |
| --reg-length: 10px; |
| } |
| @container style(--reg-length: 10px) { |
| #reg-px { color: green; } |
| } |
| @container style(--reg-length: initial) { |
| #reg-px-initial { color: green; } |
| } |
| @container not style(--reg-length) { |
| #reg-px-initial-implicit { color: green; } |
| } |
| |
| #reg-container-font-relative { |
| --reg-length: 10px; |
| } |
| @container style(--reg-length: 0.5em) { |
| #reg-font-relative { color: green; } |
| } |
| |
| #reg-container-font-relative-2 { |
| --reg-length: 0.5em; |
| } |
| @container style(--reg-length: 10px) { |
| #reg-font-relative-2 { color: green; } |
| } |
| |
| #reg-container-container-relative { |
| width: 100px; |
| --reg-length: 100px; |
| } |
| @container style(--reg-length: 50cqi) { |
| #reg-container-relative { color: green; } |
| } |
| |
| #reg-container-initial { |
| --reg-length: 10px; |
| } |
| @container style(--reg-length: 10px) { |
| #reg-initial-value { color: green; } |
| } |
| @container style(--reg-length: initial) { |
| #reg-initial-keyword { color: green; } |
| } |
| @container not style(--reg-length) { |
| #reg-initial-implicit { color: green; } |
| } |
| </style> |
| <div id="registered"> |
| <div id="reg-container-px"> |
| <div id="reg-px"></div> |
| <div id="reg-px-initial"></div> |
| <div id="reg-px-initial-implicit"></div> |
| </div> |
| <div id="reg-container-font-relative"> |
| <div id="reg-font-relative"></div> |
| </div> |
| <div id="reg-container-font-relative-2"> |
| <div id="reg-font-relative-2"></div> |
| </div> |
| <div id="reg-container-container-relative"> |
| <div id="reg-container-relative"></div> |
| </div> |
| <div id="reg-container-initial"> |
| <div id="reg-initial-value"></div> |
| <div id="reg-initial-keyword"></div> |
| <div id="reg-initial-implicit"></div> |
| </div> |
| </div> |
| <script> |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-px")).color, green); |
| }, "Match registered <length> custom property with px."); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-px-initial")).color, green); |
| }, "Match registered <length> custom property with px via initial keyword."); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-font-relative")).color, green); |
| }, "Match registered <length> custom property with em in query."); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-font-relative-2")).color, green); |
| }, "Match registered <length> custom property with em in computed value."); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-container-relative")).color, green); |
| }, "Match registered <length> custom property with cqi unit."); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-initial-value")).color, green); |
| }, "Match registered <length> custom property with initial value."); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#reg-initial-keyword")).color, green); |
| }, "Match registered <length> custom property with initial value via initial keyword."); |
| </script> |
| |
| <style> |
| #original-text { |
| --number: 100.00; |
| --spaces: a b; |
| } |
| @container style(--number: 100.00) { |
| #original-text-number { |
| color: green; |
| } |
| } |
| @container style(--number: 100.0) { |
| #original-text-number { |
| color: red; |
| } |
| } |
| @container style(--number: 100) { |
| #original-text-number { |
| color: red; |
| } |
| } |
| @container style(--spaces: a b) { |
| #original-text-spaces { |
| color: green; |
| } |
| } |
| @container style(--spaces: a b) { |
| #original-text-spaces { |
| color: red; |
| } |
| } |
| </style> |
| <div id="original-text"> |
| <div id="original-text-number"></div> |
| <div id="original-text-spaces"></div> |
| </div> |
| <script> |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#original-text-number")).color, green); |
| }, "Should only match exact string for numbers in non-registered custom properties"); |
| |
| test(() => { |
| assert_equals(getComputedStyle(document.querySelector("#original-text-spaces")).color, green); |
| }, "Spaces should not collapse in non-registered custom properties"); |
| </script> |