Указание содержимого, в котором ячейки расширяют области ячеек, а не в CSS Grid

Я хочу иметь ячейку в сетке с несущественной информацией, которая не заставляет другие ячейки расширяться за пределы того, что абсолютно необходимо. Его высота должна быть не больше высоты других ячеек, а ее ширина должна быть равна ширине пустой незанятой области.

Скажем, для каждого элемента у меня есть миниатюра, заголовок (одиночная строка без разворота), информация (ноль или более строк), описание (возможно, очень длинное, отображается только при наличии пустого пространства).

Я придумал это:

.list {
  display: flex;
  flex-wrap: wrap;
  font: 12px/14px Verdana;
}
.item {
  display: grid;
  grid-template-areas:
    "thumb thumb thumb thumb"
    "sl    title desc  sr   "
    "sl    info  desc  sr   ";
  grid-template-columns:
    auto auto 1fr auto;
  grid-template-rows:
    auto auto 1fr;
  min-width: calc(var(--min-item-size) + 4px);
  max-width: calc(var(--max-item-size) + 4px);
  border: dotted 2px darkblue;
  margin: 4px 2px auto 2px;
}
.item > * {
  min-width: 0;
  min-height: 0;
  border: dotted 1px dodgerblue;
  margin: 1px;
}
.thumb {
  grid-area: thumb;
  margin: auto;
  height: 100px;
  background: linear-gradient(lightskyblue, deepskyblue);
}
.title {
  grid-area: title;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.info {
  grid-area: info;
  overflow: hidden;
  text-overflow: ellipsis;
}
.desc {
  grid-area: desc;
  position: relative;
  overflow: hidden;
}
.desc-text::after {
  position: absolute; /*clean hack*/
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  content: var(--lorem-ipsum);
}
.desc-text.short::after {
  content: var(--lorem-ipsum-short);
}
:root {
  --lorem-ipsum: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
  --lorem-ipsum-short: "Lorem";
  --min-item-size: 100px;
  --max-item-size: 150px;
}
<div class="list">
  <div class="item">
    <div class="thumb" style="width: 150px">1</div>
    <div class="title">Short title</div>
    <div class="info">Short info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 150px">2</div>
    <div class="title">Very long and detailed title</div>
    <div class="info">Very long and detailed info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 50px">3</div>
    <div class="title">Short title</div>
    <div class="info">Short info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 50px">4</div>
    <div class="title">Very long and detailed title</div>
    <div class="info">Very long and detailed info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item" style="grid-template-columns: 22px auto 1fr 22px /*dirty hack*/">
    <div class="thumb" style="width: 150px">5</div>
    <div class="title">Short title</div>
    <div class="info">Short info</div>
    <div class="desc">
      <div class="desc-text short"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 150px">6</div>
    <div class="title">Very long and detailed title</div>
    <div class="info">Very long and detailed info</div>
    <div class="desc">
      <div class="desc-text short"></div>
    </div>
  </div>
</div>

Ответ 1

Я думаю, что у меня есть неплохое решение.

Единственным недостатком является то, что мне нужно установить max-width на .title и .info.

Ваша первая проблема заключается в распределении горизонтального пространства. Вы хотите, чтобы второй столбец дал как можно больше места для title. Но не более, чем естественная ширина содержащихся элементов. Итак, нам нужно что-то, что относится к контенту, и к максимальной его ширине, max-content.

Затем нам нужен третий столбец с desc, чтобы взять любую левую ширину, если она есть, а также не более того, что она может заполнить. Это может быть достигнуто с помощью min-max (0, max-content)

И, наконец, мы хотим, чтобы любое левое пространство переходило в 1-й и 4-й столбцы с 1fr.

Эта компоновка работает, потому что свободное пространство распределено в 2 раундах, одно для minmax-функций и второе для элементов fr.

Проблема с этой настройкой заключается в том, что максимальное содержимое title может переполнять контейнер. Мы не можем решить (я думаю) это на самой сетке, и нам нужно установить максимальную ширину на самом элементе.

Сначала вы могли бы подумать, что здесь может помочь функция minmax. Нет, не может. Вы можете увидеть объяснение здесь

Другая проблема заключается в обработке высоты desc. Поскольку он охватывает 2 строки, но оба должны быть разумными для контента, нам здесь не повезло.

К счастью, у вас уже есть вложенная структура. Выполнение переполнения контейнера: скрытие и ограничение высоты внутреннего элемента сделают трюк. Внутренний элемент не имеет достаточной высоты для своего содержимого, но они отображаются из-за переполнения: none. И контейнер подходит по высоте к сетке и скопирует переполненный контент

:root {
  --lorem-ipsum: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
  --lorem-ipsum-short: "Lorem";
  --min-item-size: 100px;
  --max-item-size: 150px;
  --max-item-desc-height: 32px; /* added */
}

.list {
  display: flex;
  flex-wrap: wrap;
  font: 12px/14px Verdana;
}
.item {
  display: grid;
  grid-template-areas:
    "thumb thumb thumb thumb"
    "sl    title desc  sr   "
    "sl    info  desc  sr   ";
  grid-template-columns: 1fr max-content minmax(0px, max-content) 1fr; /* changed */
  grid-template-rows: auto auto 1fr;
  min-width: calc(var(--min-item-size) + 4px);
  max-width: calc(var(--max-item-size) + 4px);
  border: dotted 2px darkblue;
  margin: 4px 2px auto 2px;
}
.item > * {
  min-width: 0;
  min-height: 0;
  border: dotted 1px dodgerblue;
  margin: 1px;
}
.thumb {
  grid-area: thumb;
  margin: auto;
  height: 100px;
  background: linear-gradient(lightskyblue, deepskyblue);
}
.title {
  grid-area: title;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  max-width: var(--max-item-size); /* added */
}
.info {
  grid-area: info;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: var(--max-item-size); /* added */
}
.desc {
  grid-area: desc;
  overflow: hidden;
  max-height: var(--max-item-desc-height); /* added */
}
.desc-text::after {
  content: var(--lorem-ipsum);
}
.desc-text.short::after {
  content: var(--lorem-ipsum-short);
}
<div class="list">
  <div class="item">
    <div class="thumb" style="width: 150px">1</div>
    <div class="title">Short title</div>
    <div class="info">Short info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 150px">2</div>
    <div class="title">Very long and detailed title</div>
    <div class="info">Very long and detailed info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 50px">3</div>
    <div class="title">Short title</div>
    <div class="info">Short info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 50px">4</div>
    <div class="title">Very long and detailed title</div>
    <div class="info">Very long and detailed info</div>
    <div class="desc">
      <div class="desc-text"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 150px">5</div>
    <div class="title">Short title</div>
    <div class="info">Short info</div>
    <div class="desc">
      <div class="desc-text short"></div>
    </div>
  </div>
  <div class="item">
    <div class="thumb" style="width: 150px">6</div>
    <div class="title">Very long and detailed title</div>
    <div class="info">Very long and detailed info</div>
    <div class="desc">
      <div class="desc-text short"></div>
    </div>
  </div>
</div>

Ответ 2

Вопрос довольно трудно понять, и пример, приведенный, свертывает вещи. Поэтому я извиняюсь, если я не отвечу непосредственно на ваш вопрос.

Я думаю, что вы спрашиваете (на основе вашего примера и его требований): "Можете ли вы определить приоритеты, какие элементы растут или сжимаются независимо от их содержимого?"

Ответ на этот вопрос - нет, однако это не означает, что вы не можете достичь того, чего хотите, пока используете только CSS. Пожалуйста, см. Мой нижеприведенный фрагмент о том, как я подошел/решил проблему.

Обратите внимание: я думаю, что вы сильно усложнили себя, пытаясь использовать правила сетки или даже сгибать в этом отношении, поскольку я столкнулся с теми же проблемами, которые вы делали при попытке решить эту проблему с помощью flex.

.list {
  display: flex;
  flex-wrap: wrap;
  font: 12px/14px Verdana;
}

.item {
  min-width: 100px;
  max-width: 150px;
  border: solid 1px black;
  float: left;
  margin: 10px;
}

.thumb {
  margin: auto;
  height: 100px;
  background: linear-gradient(lightskyblue, deepskyblue);
}

.center {
  float: left;
  left: 50%;
  transform: translateX(-50%);
  position: relative;
  max-width: 150px;
}

.meta-wrap {
  float: left;
  max-width: 100%;
}

.desc-wrap {
  overflow: hidden;
  /*
  Make sure this doesn't grow out the rest of the item.
  This can be a static height because if the info is long enough to grow the height
  then the description wouldn't be seen anyway.
  */
  max-height: 27px;
}

.title,
.info,
.text {
  overflow: hidden;
  text-overflow: ellipsis;
}

.title {
  background: orange;
  white-space: nowrap;
}

.info {
  background: tomato;
}

.text {
  background: aqua;
}
<div class="list">

  <div class="item">
    <div class="thumb" style="width: 150px">1</div>
    <div class="center">
      <div class="meta-wrap">
        <div class="title">Short</div>
        <div class="info">Short</div>
      </div>
      <div class="desc-wrap">
        <div class="text">Lorem ipsum text and stuff goes here, cool!</div>
      </div>
    </div>
  </div>

  <div class="item">
    <div class="thumb" style="width: 150px">2</div>
    <div class="center">
      <div class="meta-wrap">
        <div class="title">Long title goes here that should cut off</div>
        <div class="info">long description goes here</div>
      </div>
      <div class="desc-wrap">
        <div class="text">Lorem ipsum text and stuff goes here, cool!</div>
      </div>
    </div>
  </div>

  <div class="item">
    <div class="thumb" style="width: 50px">3</div>
    <div class="center">
      <div class="meta-wrap">
        <div class="title">Short</div>
        <div class="info">Short</div>
      </div>
      <div class="desc-wrap">
        <div class="text">Lorem!</div>
      </div>
    </div>
  </div>

  <div class="item">
    <div class="thumb" style="width: 50px">4</div>
    <div class="center">
      <div class="meta-wrap">
        <div class="title">Long title goes here that should cut off</div>
        <div class="info">long description goes here</div>
      </div>
      <div class="desc-wrap">
        <div class="text">Lorem ipsum text and stuff goes here, cool!</div>
      </div>
    </div>
  </div>

  <div class="item">
    <div class="thumb" style="width: 150px">5</div>
    <div class="center">
      <div class="meta-wrap">
        <div class="title">Short</div>
        <div class="info">Short</div>
      </div>
      <div class="desc-wrap">
        <div class="text">Lorem!</div>
      </div>
    </div>
  </div>

  <div class="item">
    <div class="thumb" style="width: 150px">6</div>
    <div class="center">
      <div class="meta-wrap">
        <div class="title">Long title goes here that should cut off</div>
        <div class="info">long description goes here</div>
      </div>
      <div class="desc-wrap">
        <div class="text"></div>
      </div>
    </div>
  </div>

</div>