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
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:
CSS:
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:
Apparently you’ll have to accept that o1 and o2 will always be same width.
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:
This however will only work if the
t1
element is smaller then 60% total grid width!