Home  >  Q&A  >  body text

Google Chrome uses Flexbox viewport to anchor expansion direction

<p>There is an issue in Google Chrome where when an element is placed inside a Flexbox container that has <em>adjacent</em> Flex items with <code>spaces</code Expand/collapse> or <code>center</code> align content in different directions relative to the viewport. </p> <p>This is not a problem in Firefox, IE11, Edge, or Safari because elements always expand downwards. </p> <p>I’m curious:</p> <ul> <li>Does Chrome behave according to certain specifications? If so, which one? </li> <li>If not, why would you do it in Chrome? (IMHO, clicking a trigger that randomly disappears off-screen is a terrible user experience.) </li> <li>Is it possible to modify or disable Chrome's behavior in some way? For example. Via CSS or meta tags? </li> </ul> <p><strong>Update 1: If possible, I have submitted issue #739860 on the chromium bug tracker to seek insight/explanation from the Chromium developers. </strong></p> <hr> <p>Two examples are inserted below. The full test suite describing the problem can be found with this pen: https://codepen.io/jameswilson/full/xrpRPg/ I chose to use slipToggle in this example so that the unfold/fold movement is animated and eye-catching. The same behavior happens with the details tab, but there's no cross-browser support yet, and the expand/collapse is too janky.</p> <p><strong>示例 1:Chrome 针对对齐 Flexbox 之间的空格的展开/折叠行为</strong></p> <p> <pre class="brush:js;toolbar:false;">$('button').click(function() { $(this).next().slideToggle(); })</pre> <pre class="brush:css;toolbar:false;">body { margin: 30px; font-family: sans-serif; } aside, aside div, summary, main, button, details p, button p { background: rgba(0,0,0,.09); border: none; padding: 20px; margin: 0; } .flexcontainer { display: flex; } aside { flex: 1; position: relative; max-width: 25%; background: mintcream; display: flex; flex-direction: column; position: relative; } aside.space-between { justify-content: space-between; } aside.center { justify-content: center; } main { flex: 3; position: relative; max-width: 75%; background: aliceblue; vertical-align: top; height: 100%; } main > * * { margin-top: 20px; } button p { display: none; }</pre> <pre class="brush:html;toolbar:false;"><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section class="flexcontainer"> <aside class="space-between"> <div>Top Sidebar</div> <div>Bottom Sidebar</div> </aside> <main> <div> <button>slideToggle</button> <p>Other browsers: always expands downward.<br> Chrome: Should always expand downward because Top Sidebar is always visible.</p> </div> <div> <button>slideToggle (usually expands down)</button> <p>Other browsers: always expands downward.<br> Chrome: Should expand downward while Bottom Sidebar and Top Sidebar are both visible. But will expand upward if you scroll down far enough so that Top Sidebar is off-screen.</p> </div> <div> <button>slideToggle (usually expands down)</button> <p>Other browsers: always expands downward.<br> Chrome: Should expand downward while Bottom Sidebar and Top Sidebar are both visible. But will expand upward if you scroll down far enough so that Top Sidebar is off-screen.</p> </div> </main> </section></pre> </p> <p><strong>示例 2:Chrome 对居中对齐的 Flexbox 的展开/折叠行为</strong></p> <p> <pre class="brush:js;toolbar:false;">$('button').click(function() { $(this).next().slideToggle(); })</pre> <pre class="brush:css;toolbar:false;">body { margin: 30px; font-family: sans-serif; } aside, aside div, summary, main, button, details p, button p { background: rgba(0,0,0,.09); border: none; padding: 20px; margin: 0; } .flexcontainer { display: flex; } aside { flex: 1; position: relative; max-width: 25%; background: mintcream; display: flex; flex-direction: column; position: relative; } aside.space-between { justify-content: space-between; } aside.center { justify-content: center; } main { flex: 3; position: relative; max-width: 75%; background: aliceblue; vertical-align: top; height: 100%; } main > * * { margin-top: 20px; } button p { display: none; }</pre> <pre class="brush:html;toolbar:false;"><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section class="flexcontainer"> <aside class="center"> <div>Center Sidebar</div> </aside> <main> <div> <button>slideToggle (usually expands downwards)</button> <p>Other browsers: always expands downward.<br> Chrome: Usually expands downwards. Expands in both directions when the top-edge of the container scrolls out of the viewport.</p> </div> <div> <button>slideToggle</button> <p>Other browsers: always expands downward.<br> Chrome: Usually expands downwards. Expands in both directions when the top-edge of the container scrolls out of the viewport.</p> </div> <div> <button>slideToggle (usually expands downwards)</button> <p>Other browsers: always expands downward.<br> Chrome: Usually expands downwards. Expands in both directions when the top-edge of the container scrolls out of the viewport, but then resumes expanding downwards again when Center Sidebar scrolls out of view.</p> </div> </main> </section></pre> </p>
P粉852578075P粉852578075444 days ago549

reply all(1)I'll reply

  • P粉283559033

    P粉2835590332023-08-26 12:21:55

    Add this code to your Flex container:

    • Overflow Anchor: None

    This disables a feature in Chrome called "scroll anchoring" that causes the box to expand upwards (Revised Code Pen).


    In Chrome, the up/down direction of the expandable box is determined by the scroll position in the viewport, not the layout itself.

    In order to improve the user experience, Chrome has taken a unique approach to this behavior.

    Basically, they bind a DOM element to the current scroll position. Movement of this specific ("anchor") element on the screen will determine adjustments to the scroll position (if any).

    They call this method "scroll anchoring". The algorithm is explained on this page: https://github.com/WICG/ScrollAnchoring/blob/master/explainer.md

    This behavior is currently unique to Chrome, but Google is pushing for standardization.

    According to the scroll anchor documentation, applying overflow-anchor: none to the appropriate element will disable scroll anchor adjustments.

    More information:

    reply
    0
  • Cancelreply