Search code examples
htmlcssgrid-layout

How do I use calc() with min-content?


I have a grid layout which can be simplified like this.

What I want to achieve is the .side should take whatever space the content needs to by default using min-content, but user can enlarge it by increasing the --size custom css property.

I tried calc(min-content + var(--size)) but it doesn't work. I can't assign a specific value like calc(100px + var(--size)) since the original size should be determined by its content.

What is the best approach to achieve such a feature?

* {
  box-sizing: border-box;
}

body {
  overflow: hidden;
  margin: 0;
}

.container {
  --size: 10px;

  width: 100vw;
  height: 100vh;
  display: grid;
  grid-template-areas: 
    "l t"
    "l b";
  
  /* doesn't work */
  /* grid-template-columns: calc(min-content + var(--size)) 1fr; */
  
  grid-template-columns: min-content 1fr;
  grid-template-rows: 1fr 1fr;
}

.container > * {
  border: solid 1px black;
}

.side {
  grid-area: l;
}

.top {
  grid-area: t;
}

.bottom {
  grid-area: b;
}
<section class="container">
  <div class="side">This should have a 10px gutter on the right</div>
  <div class="top">Top</div>
  <div class="bottom">Bottom</div>
</section>


Solution

  • Use width:calc(100% + var(--size)) for the grid item. This will create an overflow that you can rectify by adding a gap:

    * {
      box-sizing: border-box;
    }
    
    body {
      overflow: hidden;
      margin: 0;
    }
    
    .container {
      --size: 20px;
    
      height: 100vh;
      display: grid;
      grid-template-areas: 
        "l t"
        "l b";
      
      /* doesn't work */
      /* grid-template-columns: calc(min-content + var(--size)) 1fr; */
      
      grid-template-columns: min-content 1fr;
      grid-template-rows: 1fr 1fr;
      column-gap:var(--size);
    }
    
    .container > * {
      border: solid 1px black;
    }
    
    .side {
      grid-area: l;
      width:calc(100% + var(--size));
    }
    
    .top {
      grid-area: t;
    }
    
    .bottom {
      grid-area: b;
    }
    <section class="container">
      <div class="side">This should have a 10px gutter on the right</div>
      <div class="top">Top</div>
      <div class="bottom">Bottom</div>
    </section>