CSS Grid: Make grid-cell only as wide as max-content, but never wider than 1fr. Or would display: flex be able to solve this?

Viewed 480

How do I make it so a cell in a grid is only as wide as its max-content, but never overflows the parent grid container?

Check this example:

.grid {
  border: 1px dotted blue;
  display: grid;
  gap: 5px;
  grid-template-columns: min-content max-content;
  width: 120px;
}

label {
  background-color: yellow;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<div class="grid">
  <input type="checkbox" id="foo" /><label for="foo">foo label, must not overflow parent grid!</label>
</div>

<div class="grid">
  <input type="checkbox" id="bar" /><label for="bar">bar label</label>
</div>

The code sample also shows my real-world use case. I need it so the label is restricted to the parent element, while also not being any wider than necessary, because I don't want white-space to the right side of the label be part of the clickable area.

If I set it to 1fr instead of max-content, the label covers the whole rest of the container, which is unwanted because now you can toggle the checkbox clicking the whitespace right of the label.

.grid {
  border: 1px dotted blue;
  display: grid;
  gap: 5px;
  grid-template-columns: min-content 1fr;
  width: 120px;
}

label {
  background-color: yellow;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<div class="grid">
  <input type="checkbox" id="foo" /><label for="foo">foo label, must not overflow parent grid!</label>
</div>

<div class="grid">
  <input type="checkbox" id="bar" /><label for="bar">bar label</label>
</div>

CSS would offer a solution here

min(max-content, 1fr)

but unfortunately max-content cannot be used in the min()-function.

2 Answers

You can use fit-content(100%) ref

.grid {
  border: 1px dotted blue;
  display: grid;
  gap: 5px;
  grid-template-columns: min-content fit-content(100%);
  width: 120px;
}

label {
  background-color: yellow;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<div class="grid">
  <input type="checkbox" id="foo" /><label for="foo">foo label, must not overflow parent grid!</label>
</div>

<div class="grid">
  <input type="checkbox" id="bar" /><label for="bar">bar label</label>
</div>

With flexbox it's a trivial task because all you need is to make the element a flexbox container:

.grid {
  border: 1px dotted blue;
  display: flex;
  gap: 5px;
  width: 120px;
}

label {
  background-color: yellow;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<div class="grid">
  <input type="checkbox" id="foo" /><label for="foo">foo label, must not overflow parent grid!</label>
</div>

<div class="grid">
  <input type="checkbox" id="bar" /><label for="bar">bar label</label>
</div>

Playing around with the snippet, I found a working solution, using

justify-self: start;
max-width: 100%;

alongside with 1fr for the label column:

.grid {
  border: 1px dotted blue;
  display: grid;
  gap: 5px;
  grid-template-columns: min-content 1fr;
  width: 120px;
}

label {
  background-color: yellow;
  justify-self: start;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<div class="grid">
  <input type="checkbox" id="foo" /><label for="foo">foo label, must not overflow parent grid!</label>
</div>

<div class="grid">
  <input type="checkbox" id="bar" /><label for="bar">bar label</label>
</div>

Related