| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>content-visibility and layout containment</title> |
| <link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> |
| <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1765615"> |
| <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/common/rendering-utils.js"></script> |
| <meta name="assert" content="content-visibility: auto and elements skipping their content change the used value of the contain property to turn on layout containment."> |
| <style> |
| /* Selectors for content-visibility */ |
| #spacer_for_far_to_viewport { |
| height: 300vh; |
| } |
| .content_visibility { |
| /* Dynamic modification of content-visibility may change whether style |
| containment is applied, which in turn may cause drastic invalidations |
| (e.g. rebuilding counters). Make the test more robust by forcing |
| style containment to always apply. */ |
| contain: style; |
| } |
| #visible .content_visibility { |
| content-visibility: visible; |
| } |
| #hidden .content_visibility { |
| content-visibility: hidden; |
| } |
| #auto_far .content_visibility { |
| content-visibility: auto; |
| } |
| #auto_close .content_visibility { |
| content-visibility: auto; |
| } |
| #visible_to_hidden .content_visibility { |
| content-visibility: visible; |
| } |
| #hidden_to_visible .content_visibility { |
| content-visibility: hidden; |
| } |
| #visible_to_auto .content_visibility { |
| content-visibility: visible; |
| } |
| #auto_to_visible .content_visibility { |
| content-visibility: auto; |
| } |
| |
| /* Selectors for testing baseline */ |
| .flex { |
| display: inline-flex; |
| align-items: baseline; |
| } |
| .rect { |
| background: black; |
| width: 50px; |
| height: 100px; |
| } |
| </style> |
| <body> |
| <div id="log"></div> |
| |
| <div id="visible"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="hidden"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="auto_close"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="visible_to_hidden"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="hidden_to_visible"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="visible_to_auto"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="auto_to_visible"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <div id="spacer_for_far_to_viewport"></div> |
| |
| <div id="auto_far"> |
| <div class="flex"> |
| <div class="rect"></div> |
| <div class="content_visibility rect">X</div> |
| </div> |
| </div> |
| |
| <script> |
| function layoutContainmentApplied(id) { |
| let container = document.getElementById(id); |
| let content_visibility = container.getElementsByClassName("content_visibility")[0]; |
| |
| // To verify layout containment, we test baseline suppression. |
| // See contain-layout-dynamic-001.html for more details. |
| let item1 = content_visibility; |
| let item2 = item1.previousElementSibling; |
| return Math.abs(item1.getBoundingClientRect().top - item2.getBoundingClientRect().top) <= 1; |
| } |
| |
| function setContentVisibility(id, value) { |
| let container = document.getElementById(id); |
| let content_visibility = container.getElementsByClassName("content_visibility")[0]; |
| content_visibility.style.contentVisibility = value; |
| } |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| assert_false(layoutContainmentApplied("visible")); |
| }, "content-visibility: visible"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| assert_true(layoutContainmentApplied("hidden")); |
| }, "content-visibility: hidden"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| await waitForAtLeastOneFrame(); |
| assert_true(layoutContainmentApplied("auto_far")); |
| }, "content-visibility: auto (far from viewport)"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| await waitForAtLeastOneFrame(); |
| assert_true(layoutContainmentApplied("auto_close")); |
| }, "content-visibility: auto (close from viewport)"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| setContentVisibility("visible_to_hidden", "hidden"); |
| assert_true(layoutContainmentApplied("visible_to_hidden")); |
| }, "switching content-visibility from visible to hidden"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| setContentVisibility("hidden_to_visible", "visible"); |
| assert_false(layoutContainmentApplied("hidden_to_visible")); |
| }, "switching content-visibility from hidden to visible"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| setContentVisibility("visible_to_auto", "auto"); |
| await waitForAtLeastOneFrame(); |
| assert_true(layoutContainmentApplied("visible_to_auto")); |
| }, "switching content-visibility from visible to auto"); |
| |
| promise_test(async () => { |
| await document.fonts.ready; |
| setContentVisibility("auto_to_visible", "visible"); |
| assert_false(layoutContainmentApplied("auto_to_visible")); |
| }, "switching content-visibility from auto to visible"); |
| </script> |
| </body> |