如何在超过指定宽度后居中对齐main网格容器?
问题:网格容器水平居中导致布局崩溃的解决方法
我有一个main网格,它的子项同时也是容器(container-type: inline-size),可根据自身宽度实现多样内部布局。当main超过特定宽度后,如何实现水平居中?
给main设置justify-self: center或margin: 0 auto都会导致整个布局崩溃,取消下方代码片段中这两行的注释即可查看问题;在main或body上设置justify-content: center也会出现同样问题。调整视口大小可看到,当main超过设置的max-width时会始终靠左显示。我需要实现其水平居中,但尝试的所有方法都会导致布局崩溃。
复现代码
JavaScript
addEventListener('input', e => {document.body.style = `--${e.target.id}: 1`})
CSS
/* basic reset, grid everything */ * { margin: 0; padding: 0 } html, body, main, section, div, ul, figure { display: grid } html { min-height: 100% } body { /* body stle may override these two; * they're mutually exclusive */ /* 1 if images are _N_ext to each other, 0 otherwise */ --_n: var(--n, 0); /* 1 if images are _S_tacked, 0 otherwise */ --_s: var(--s, 0); font: clamp(.75em, 3.375vw, 1.25em)/ 1.25 sans-serif; } main { grid-gap: .5em; align-self: center; /* need this, but it collapses layout */ /* justify-self: center; /* same happens with this */ /* margin: 0 auto; /* */ padding: .5em; max-width: 800px } /* CSS variable indices for similar items */ :is(input, label, li, figure):nth-of-type(1) { --i: 0 } :is(input, label, li, figure):nth-of-type(2) { --i: 1 } :is(input, label, li, figure):nth-of-type(3) { --i: 2 } :is(input, label, li, figure):nth-of-type(4) { --i: 3 } .ctr { grid-gap: inherit; padding: inherit; background: gainsboro; } div { grid-gap: inherit } .one, .two, .res { container-type: inline-size; * { /* a bunch of container size cases */ --_cs0: var(--cs0, 1); --_cs1: var(--cs1, calc(1 - var(--_cs0))); --_cs2: var(--cs2, calc(1 - (var(--_cs0) + var(--_cs1)))); } } /* SECTION 1 */ .boo, .foo { @container (min-width: 23em) { --cs0: 0 } @container (min-width: 32em) { --cs1: 0 } } .boo { grid-column: calc(2 - var(--_cs1))/ span calc(1 + var(--_cs1)) } li { grid-column: calc(1 + var(--_cs1)*var(--i)) } .foo { grid-area: calc(1 + var(--_cs1))/ 1; grid-template-columns: repeat(2, max-content) } .xtra { overflow: hidden; width: calc((1 - var(--_cs0))*9em) } /* SECTION 2 */ [name='c'], [for] { grid-area: calc(1 + var(--i)*var(--_cs0))/ calc(1 + var(--i)*var(--_cs1)); @container (min-width: 20em) { --cs0: 0 } } /* SECTION 4 */ figure { grid-area: calc(1 + var(--_cs0)*var(--i)*var(--_n))/ calc(1 + var(--_cs1)*var(--i)*var(--_n)); max-width: 400px; aspect-ratio: 2/ calc(2 + var(--_s) + var(--_cs1)*var(--_n)); @container (min-width: 20em) { --cs0: 0 } } img { width: 100%; height: 100%; object-fit: cover; object-position: var(--pos) }
HTML
<body style="--n: 1"> <main> <section class="ctr one"> <ul class="boo"> <li>listitem</li> <li>listitem</li> <li>listitem</li> <li>listitem</li> </ul> <div class="foo"> <div class="xtra">superfluous</div> <div class="main"> <div>some</div> <div>essential</div> <div>shit</div> <div>keep it!</div> </div> </div> </section> <section class="ctr two"> <input id="n" type="radio" name="c" checked="checked"/> <label for="n">side by side</label> <input id="s" type="radio" name="c"/> <label for="s">stacked</label> </section> <section class="ctr tre"> <div>more stuff</div> </section> <section class="res"> <figure><img src="https://images.unsplash.com/photo-1705630547844-29adf8323f28?w=800"/></figure> <figure><img src="https://images.unsplash.com/photo-1705630547844-29adf8323f28?w=800"/></figure> </section> </main> </body>
解决方案
直接给main设置居中会改变它的宽度计算逻辑——原本main作为grid子项会占满父容器可用宽度,设置居中后宽度会收缩为内容宽度,导致子容器的container-type: inline-size查询条件混乱,进而触发布局崩溃。
解决思路是让外层容器负责居中,同时保持main的宽度逻辑不变,有两种实现方式:
方式1:新增外层容器(推荐)
修改HTML,给main套一层容器:
<body style="--n: 1"> <div class="main-wrapper"> <main> <!-- 原有内容不变 --> </main> </div> </body>
添加并修改CSS:
.main-wrapper { display: grid; place-items: center; /* 实现水平+垂直居中 */ min-height: 100vh; /* 确保占满视口高度 */ } main { grid-gap: .5em; padding: .5em; max-width: 800px; width: 100%; /* 让main占满外层容器的可用宽度,最大不超过max-width */ }
方式2:直接修改body样式(无需改动HTML)
调整body和main的CSS:
body { /* 原有样式保留,新增以下两行 */ place-items: center; min-height: 100vh; } main { grid-gap: .5em; padding: .5em; max-width: 800px; width: 100%; /* 关键:让main占满body的可用宽度 */ }
两种方式都能让main在超过max-width后水平居中,同时保证子容器的容器查询逻辑正常工作,不会导致布局崩溃。
内容的提问来源于stack exchange,提问作者Ana
相关产品推荐
相关产品推荐

