csslayoutcss-gridcontainer-queries

How do I middle align a container parent?


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>


Solution

  • @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!