studio1902 / statamic-peak

Statamic Peak is an opinionated starter kit for all your Statamic sites.
GNU General Public License v3.0
611 stars 102 forks source link

Fluid grid #373

Closed robdekort closed 10 months ago

robdekort commented 11 months ago

This concept of a fluid-grid aims to replace fluid-container and should be used in conjunction with the recently introduced stack-* utilities. Stacks take care of vertical spacing and this new fluid grid handles horizontal spacing on a block level.

The fluid grid is a horizontal block that spans from browser edge to browser edge to give you the ability to create full bleed containers or something in between. For example an image that has to start on the middle of the page but extend to the browser edge. This isn't possible with the current solution.

The CSS used looks like this:

.fluid-grid {
    --padding-left: clamp(calc(env(safe-area-inset-left, 0rem) + 1rem), 2vw, calc(env(safe-area-inset-left, 0rem) + 2rem));
    --padding-right: clamp(calc(env(safe-area-inset-right, 0rem) + 1rem), 2vw, calc(env(safe-area-inset-right, 0rem) + 2rem));
    --col-gap: clamp(1rem, 3vw, 4rem);
    --col-width: calc((min(calc(100% - var(--padding-left) - var(--padding-right) - 2 * var(--col-gap)), theme('screens.xl')) - 11 * var(--col-gap)) / 12);
    --side-width: minmax(0, 1fr);

    display: grid;
    column-gap: var(--col-gap);
    grid-template-columns: 
      [full-start] var(--side-width) 
      [content-start col-1] var(--col-width)
      [col-2] var(--col-width)
      [col-3] var(--col-width)
      [col-4] var(--col-width)
      [col-5] var(--col-width)
      [col-6] var(--col-width)
      [col-7] var(--col-width)
      [col-8] var(--col-width)
      [col-9] var(--col-width)
      [col-10] var(--col-width)
      [col-11] var(--col-width)
      [col-12] var(--col-width) [content-end] 
      var(--side-width) [full-end];
}

This is the grid it creates:

| full-start | content-start col-1 | col-2 | col-3 | col-4 | col-5 | col-6 | col-7 | col-8 | col-9 | col-10 | col-11 | col-12 content-end | full-end |

Together with the stack utilities you can create layouts that look like this:

Screenshot_2023-12-22_at_20 22 32

You can use custom utilities or arbitrary values to place items on the grid. E.g: md:col-start-[col-3] md:col-span-8.

I've tried letting direct children fall on the content area by default, but this immediately introduces specificity issues as this has a higher specificity then span-full:

.fluid-grid > *:not(.absolute, .fixed, .sticky): {
   grid-column: 'content'
}

We could wrap it in a :where pseudo selector to remove the specificity, but I think I prefer the explicitness of us being in control of grid placement and not to have automagic defaults. Not sure though.

The following utilities are present to use for spanning items on the grid. In our case they will be used on Bard sets like: text, image, table, video and pull quote and they can be customised on a per-site basis.

.span-content .span-md, .span-lg, .span-xl {
  grid-column: content
}
.span-full {
  grid-column: full
}
@media screen('md') {
  .span-md {
    grid-column: col 3 / span 8
  }
  .span-lg {
    grid-column: col 2 / span 10
  }
  .span-xl {
    grid-column: col 1 / span 12
  }
}
@media screen('lg') {
  .span-md {
    grid-column: col 4 / span 6
  }
  .span-lg {
    grid-column: col 3 / span 8
  }
  .span-xl {
    grid-column: col 2 / span 10
  }
}

The Custom Property col-gap is added to the Tailwind spacing scale so you can use the gap size of fluid grid. For example when you want to nest grids but don't want to rely on the subgrid spec yet:

<section class="fluid-grid">
    <div class="span-content grid grid-cols-12 gap-fluid-grid-gap">
        // Children will fall on a new 12 column that perfectly aligns with the parent fluid grid.
    </div>
</section

With subgrid you could use:

<section class="fluid-grid">
    <div class="span-content grid grid-cols-subgrid">
        // Children will fall on a new 12 column that perfectly aligns with the parent fluid grid.
    </div>
</section

You can use the fluid-grid-gap everywhere. For example with stacks should you want to: stack-fluid-grid-gap or margins: mb-fluid-grid-gap.

The full width grid concept is inspired by @marcorieser.