【问题标题】:Specifying content of which cells expand cell areas and which do not in CSS Grid在 CSS Grid 中指定哪些单元格扩展单元格区域以及哪些不扩展单元格区域的内容
【发布时间】:2018-06-16 15:05:57
【问题描述】:

我想在网格中有一个包含不重要信息的单元格,它不会使任何其他单元格超出绝对需要的范围。它的高度不应超过其他单元格的高度,其宽度应为空的未占用区域的宽度。

假设对于每个项目,我都有一个缩略图、一个标题(单个可展开的行)、信息(零行或多行)、描述(可能很长,仅在有空白区域时显示)。

我想出了这个:

.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>

我必须将描述放入相对定位单元格内的绝对定位容器中。这使得网格忽略内容并且有点工作,但是有几个问题:

    1234563 0 以外的其他都不起作用(样式属性形式的脏 hack 不算,只是为了显示间距单元格的使用)。
  1. 它看起来不像是纯 CSS 网格解决方案。我想知道是否有更多“原生”方式来指定细胞生长如何受内容影响。


如果您想要一个“干净的开始”,您可以从 CSS 中删除 position: absolute; /*clean hack*/ 行并从 HTML 中删除 style="grid-template-columns: 22px auto 1fr 22px /*dirty hack*/" 属性。一些定位 CSS 属性已过时,但它们不再影响定位。如果你愿意,它们也可以被移除。

干净的开始:

.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;
  overflow: hidden;
}
.desc-text::after {
  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">
    <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>

【问题讨论】:

  • 这个问题在几个方面并不完全清楚。这是一个:网格区域slsr 在哪里?它们在grid-template-areas 中显示为值。但是它们是在哪里定义的呢?
  • @Michael_B 单元格slsr 纯粹用于使缩略图下方的信息块居中。如果您将grid-template-columns 设置为1fr auto auto 1fr,则会居中,但会失去描述单元格宽度的扩展。如果您将其设置为1fr auto 1fr 1fr 之类的东西,您将获得居中,但描述单元格的宽度不会扩展到所有空白区域,即使它可用。基本上,不可能同时拥有both 功能: 1. 如果描述很长,则将描述扩展到空白空间的全宽; 2. 居中信息块为描述,其他单元格较短。
  • @Michael_B 更新了问题。 1. 现在所有项目都按照我想要的方式显示。 2. 样式属性 hack 添加到 HTML 以显示间距单元格的使用。
  • 我想我明白你在追求什么。考虑发布一个简化的、直接的演示,可能只有一张问题卡并删除绝对定位。通过发布一个 hacky 解决方案,您可能会分散对干净有效解决方案的注意力(并冒险接近XY Problem)。
  • @Michael_B (呃,没有保存之前的问题编辑。)我需要所有 6 个案例。单独解决每一个问题是微不足道的。如果我删除绝对定位,它会打破 6 个案例中的 4 个。无论如何,在问题中添加了一个“干净的开始”sn-p。

标签: html css css-grid


【解决方案1】:

我认为我有一个很好的解决方案。

唯一的缺点是我需要在.title.info 上设置max-width

您的第一个问题是分配水平空间。您希望第二列为 title 提供尽可能多的空间。但不超过所包含元素的自然宽度。所以,我们需要一些与内容相关的东西,以及它的最大宽度,max-content

然后我们希望第三列,带有 desc,如果有的话,可以采用任何左边的宽度,并且不能超过它可以填充的宽度。这可以通过 min-max(0, max-content)

来实现

最后,我们希望任何剩余空间进入第一列和第四列,1fr

这种安排是有效的,因为空闲空间分布在 2 轮中,一个用于 minmax 函数,第二个用于 fr 元素。

这个设置的问题是 titlemax-content 会溢出容器。我们无法在网格本身上解决(我认为)这个问题,我们需要在元素本身上设置一个最大宽度。

起初,您可能认为这里的 minmax 函数会有所帮助。不,它不能。可以看解释here

另一个问题是处理desc的高度。由于它跨越 2 行,但都必须对内容敏感,所以我们在这里不走运。

幸运的是,您在这里已经有了一个嵌套结构。让容器 overflow: hidden 并限制内部元素的高度就可以了。内部元素没有足够的高度来容纳其内容,但由于 overflow: 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 的情况下实现您想要的。请参阅我下面的 sn-p,了解我是如何处理/解决问题的。

    请注意:我认为您尝试使用网格规则甚至 flex 让自己变得很困难,因为我在尝试使用 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>

    【讨论】:

    • 我选择 CSS Grid 的原因是它被提议为 布局系统,它可以制作浮动 div 布局、表格布局、包装器元素和所有其他 hacky 和非语义的东西这困扰着过时的 CSS。我正在测试 CSS Grid 的极限,看看它是否像承诺的那样强大和灵活。 / 嗯,在我简化和概括问题时,我没有注意到描述现在具有易于预测的最大高度。不错的收获。
    • 嗯,有趣的定心技术。 float: left; left: 50%; transform: translateX(-50%); 是如何工作的?我在哪里可以读到它?我想我可以用一个包装器让它在 CSS Grid 解决方案中工作......
    • 基本上移动将某物定位在 50% 处会将其置于父级的“中途”点之上,而 translateX(-50%) 将其带回其自身宽度的一半处。有效地将其放置在父对象的中心,而不依赖于静态宽度。我相信你可能会以某种方式抛弃花车,我只是匆忙:)
    猜你喜欢
    • 1970-01-01
    • 2015-12-11
    • 2018-01-11
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2018-11-07
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多