skip to Main Content

I have a CSS grid layout with a specific template for the columns, for example:

.layout {
    display: grid;
    grid-template-columns: [t1] 40% [t2] 20% [o1] 1fr [o2] 1fr;
    grid-template-rows: 1fr 1fr;
}
.layout > div {
    border: 1px solid #000;
}
.layout > div:first-child {
    grid-row: 1/span 2;
}
<div class="layout">
    <div>Content t1 1</div>
    <div>Content t2 1</div>
    <div>Content o1 1</div>
    <div>Content o2 1</div>
    <div>Content t2 2</div>
    <div>Content o1 2</div>
    <div>Content o2 2</div>
</div>

In the example, the sum of [t1] and [t2] is 60%.

What I want to achieve is that the width of [t2] fits its content but is at maximum 20% (e.g., with fit-content(20%)) and that [t1] increases or decreases depending on the width of [t2] so that the sum of [t1] and [t2] is still and always remains by 60%. For example, if [t2] is 10%, [t1] should be 50%.

The part [o1] 1fr [o2] 1fr is flexible and sum up to the rest (40% in this example).

Is there a way without JS to achieve this with a CSS Grid layout?

I tried different combinations of auto, minmax, fit-content, and calc. They do not solve the problem.

I expect something like calc(60% - [t2]) but have no hope that there is something similar.

A CSS Flexbox layout is not an option because one cell spans over more than one row.

2

Answers


  1. I think, these kind of calculations/assumptions are not possible with pure CSS. Im pretty sure you already got the idea yourself, but I would wrap the first two and the last two columns in an extra grid like this:

    <div class="layout-wrapper">
        <div class="layout">
            <div>Content t1 Content t1 Content t1 Content t1 Content t1 Content t1 Content t1 Content t1</div>
        <div>Content t2</div>
      </div>
      <div class="layout">
          <div>Content o1</div>
          <div>Content o2</div>
      </div>
    </div>
    

    CSS:

    .layout-wrapper {
       display: grid;
       grid-template-columns: 3fr 2fr;
    }
    .layout {
       display: grid;
       grid-template-columns: minmax(min-content, auto) minmax(min-content, auto);
    }
    .layout div {
      border: 1px solid #444444
    }
    

    I know this i not very elegant and might be complicated to use with programmatic for-loops. However, it will maintain the 60-40 ratio.

    UPDATE:

    If wrapping the columns is not an option, you might try is this way with your original example:

    grid-template-columns: minmax(min-content, 3fr) minmax(min-content, 3fr) 2fr 2fr;
    

    Apparently you’ll have to accept that o1 and o2 will always be same width.

    Login or Signup to reply.
  2. You approach it the wrong way.

    The last 2 columns (o1 + o2) are not 1fr but specifically, 20% as both should have the same width while being a total of 40% width.

    The 1 column should occupy the remaining space which requires the width of auto.

    The last column t2 should be as large as it is which could be done with min-content

    So the rule should be: grid-template-columns: min-content auto 20% 20%;

    EDIT: As you said you want a variable amount of "o" columns, you can simply use a CSS variable and combine it with `repeat to calculate the with of the o-columns to equal 40% together:

    * {
      box-sizing: border-box;
    }
    
    section {
      display: grid;
      --o-columns: 2;
      grid-template-columns: auto minmax(min-content, 20%) repeat(var(--o-columns), calc(40% / var(--o-columns)));
    }
    
    div {
      border: 2px dashed red;
    }
    <h4>100px width for T2</h4>
    <section>
      <div>T1</div>
      <div style="min-width: 100px">T2</div>
      <div>O1</div>
      <div>01</div>
    </section>
    
    <h4>30vw width for T2</h4>
    <section>
      <div>T1</div>
      <div style="min-widthwidth: 30vw">T2</div>
      <div>O1</div>
      <div>01</div>
    </section>
    
    <h4>9em width for T2</h4>
    <section>
      <div>T1</div>
      <div style="min-width: 9em">T2</div>
      <div>O1</div>
      <div>01</div>
    </section>

    This however will only work if the t1 element is smaller then 60% total grid width!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search