cssflexboxcss-gridcontainer-queries

How to apply container query depending on column size?


I'm facing a problem where i need a card class to have different layout depending on the column size they are in but it seems container queries can't use %-ge values? Below is a example of what i have so far, is there any way to achieve this? Or do i have to for a somewhat of a magic value situation?

Also the following solution the @container (min-width: 50px) isnt working, what am i missing here?

*,
*::before,
*::after {
  box-sizing: border-box;
}

.content-grid {
  --padding-inline: 1rem;
  --content-max-width: 900px;
  --breakout-max-width: 1200px;

  --breakout-size: calc((var(--breakout-max-width) - var(--content-max-width)) / 2);

  display: grid;
  grid-template-columns:
    [full-width-start] minmax(var(--padding-inline), 1fr) [breakout-start] minmax(0, var(--breakout-size)) [content-start] min(100% - (var(--padding-inline) * 2),
      var(--content-max-width)) [content-end] minmax(0, var(--breakout-size)) [breakout-end] minmax(var(--padding-inline), 1fr) [full-width-end];
  row-gap: 2rem;
}

.content-grid> :not(.breakout, .full-width),
.full-width> :not(.breakout, .full-width) {
  grid-column: content;
}

.content-grid>.breakout {
  grid-column: breakout;
}

.content-grid>.full-width {
  grid-column: full-width;

  display: grid;
  grid-template-columns: inherit;
}

html {
  color-scheme: dark;
}

.primary-header {
  padding-block: 1rem;
  margin-block-end: 3rem;
  background: mistyrose;
  color: black;
}

.primary-header__layout {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: max(5vw, 1rem);
}

nav a {
  color: inherit;
  text-decoration: none;
}

nav a:hover,
nav a:focus {
  color: darkblue;
  text-decoration: underline;
}

.even-columns {
  display: flex;
  gap: 1rem;
}

.row {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  column-gap: 2rem;
}

.col {
  container: inline-size;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

.col-4 {
  flex: 0 0 calc(100% / (12 / 4) - 2rem);
}

.col-6 {
  flex: 0 0 calc(100% / (12 / 6) - 2rem);
}

.col-12 {
  flex: 0 0 calc(100% / (12 / 12) - 2rem);
}

.card {
  background: red;
  padding: 4rem;
}

@container (inline-size > 50px) {
  .card {
    background: blue;
    padding: 4rem;
  }
}

@container (min-width: calc(100% / (12 / 6)) - 2rem) {
  .card {
    background: green;
  }
}

@container (min-width: calc(100% / (12 / 12)) - 2rem) {
  .card {
    background: yellow;
  }
}
<header class="primary-header content-grid">
  <div class="primary-header__layout breakout">
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Blog</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
    </nav>
  </div>
</header>
<main class="content-grid">
  <div class="row">
    <div class="col col-4">
      <article class="card"></article>
    </div>
    <div class="col col-4">
      <article class="card"></article>
    </div>
    <div class="col col-4">
      <article class="card"></article>
    </div>
  </div>
  <div class="row">
    <div class="col col-6">
      <article class="card"></article>
    </div>
    <div class="col col-6">
      <article class="card"></article>
    </div>
  </div>
  <div class="row">
    <div class="col col-12">
      <article class="card"></article>
    </div>
  </div>
</main>


Solution

  • You are using the wrong CSS property. A container has context (the properties that it tracks), and can also have an optional name, so you can identify which container to use when there are multiple containers.

    The container property allows you to just define the name for the container - container: name; (container: column;) or the name and the context: container: name / context; (container: column / inline-size;). In your case using container: inline-size; defines the container name as inline-size, but doesn't define a context.

    Using container your rule should be container: column / inline-size;.

    To define just the context use container-type - container-type: inline-size;.

    To create an @container rule that is based on the inline size of the parent, define the parent as a container, for example:

    .content-grid {
      container: grid / inline-size;
    }
    

    And set the the rule on the column using the Container query length units, for example:

    @container column (inline-size > 40cqw) {
      .card {
        background: blue;
        padding: 4rem;
      }
    }
    

    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }
    
    .content-grid {
      --padding-inline: 1rem;
      --content-max-width: 900px;
      --breakout-max-width: 1200px;
    
      --breakout-size: calc((var(--breakout-max-width) - var(--content-max-width)) / 2);
    
      display: grid;
      grid-template-columns:
        [full-width-start] minmax(var(--padding-inline), 1fr) [breakout-start] minmax(0, var(--breakout-size)) [content-start] min(100% - (var(--padding-inline) * 2),
          var(--content-max-width)) [content-end] minmax(0, var(--breakout-size)) [breakout-end] minmax(var(--padding-inline), 1fr) [full-width-end];
      row-gap: 2rem;
    }
    
    .content-grid> :not(.breakout, .full-width),
    .full-width> :not(.breakout, .full-width) {
      grid-column: content;
    }
    
    .content-grid>.breakout {
      grid-column: breakout;
    }
    
    .content-grid>.full-width {
      grid-column: full-width;
    
      display: grid;
      grid-template-columns: inherit;
    }
    
    html {
      color-scheme: dark;
    }
    
    .primary-header {
      padding-block: 1rem;
      margin-block-end: 3rem;
      background: mistyrose;
      color: black;
    }
    
    .primary-header__layout {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    
    nav ul {
      list-style: none;
      margin: 0;
      padding: 0;
      display: flex;
      flex-wrap: wrap;
      gap: max(5vw, 1rem);
    }
    
    nav a {
      color: inherit;
      text-decoration: none;
    }
    
    nav a:hover,
    nav a:focus {
      color: darkblue;
      text-decoration: underline;
    }
    
    .even-columns {
      display: flex;
      gap: 1rem;
    }
    
    .content-grid {
      container: grid / inline-size;
    }
    
    .row {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      column-gap: 2rem;
    }
    
    .col {
      container: column / inline-size;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
    }
    
    .col-4 {
      flex: 0 0 calc(100% / (12 / 4) - 2rem);
    }
    
    .col-6 {
      flex: 0 0 calc(100% / (12 / 6) - 2rem);
    }
    
    .col-12 {
      flex: 0 0 calc(100% / (12 / 12) - 2rem);
    }
    
    .card {
      background: red;
      padding: 4rem;
    }
    
    @container column (inline-size > 40cqw) {
      .card {
        background: blue;
        padding: 4rem;
      }
    }
    
    @container column (min-width: calc(100% / (12 / 6)) - 2rem) {
      .card {
        background: green;
      }
    }
    
    @container column (min-width: calc(100% / (12 / 12)) - 2rem) {
      .card {
        background: yellow;
      }
    }
    <header class="primary-header content-grid">
      <div class="primary-header__layout breakout">
        <nav>
          <ul>
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Blog</a></li>
            <li><a href="#">Contact</a></li>
          </ul>
        </nav>
      </div>
    </header>
    <main class="content-grid">
      <div class="row">
        <div class="col col-4">
          <article class="card"></article>
        </div>
        <div class="col col-4">
          <article class="card"></article>
        </div>
        <div class="col col-4">
          <article class="card"></article>
        </div>
      </div>
      <div class="row">
        <div class="col col-6">
          <article class="card"></article>
        </div>
        <div class="col col-6">
          <article class="card"></article>
        </div>
      </div>
      <div class="row">
        <div class="col col-12">
          <article class="card"></article>
        </div>
      </div>
    </main>