I have a main
grid. Its grid items are also containers (container-type: inline-size
), which helps with giving them various internal layouts depending on their width.
How can I middle align main
once it passes a certain width? Both justify-self: center
and margin: 0 auto
on main
make the whole thing break - you can see this by uncommenting those two lines in the snippet below. Same happens with justify-content: center
(on main
or on the body
).
Expand the snippet below and resize the viewport to see what happens above the max-width
set for main
: it stays on the left. I want it middle aligned horizontally, but everything I've tried makes it collapse.
addEventListener('input', e => {
document.body.style = `--${e.target.id}: 1`
})
/* 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)
}
<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>
@deEr. leaving a comment about giving main
a width
gave me an idea. main
needs to be flexible up to a certain point, so it gets a max-width
to prevent it from growing above that point.
Buuut... it could also get a width: min(100%, 800px)
instead of that max-width
. With an added box-sizing: border-box
to prevent overflow since it has a padding
.
Then all the methods I've tried before and didn't work suddenly work!