如果第一列不存在,则其余列应占据空间

时间:2019-08-06 16:02:42

标签: html css css-grid

我正在尝试用CSS制作卡片组件,我认为这很简单,但是我在CSS网格属性方面苦苦挣扎。另外,在这种情况下,我不能使用flexbox ,原因不值得解释:)

布局非常简单:左侧是图片,右侧是一些文本。

<div class="card">
  <figure card="card__img">
    <img src="https://via.placeholder.com/600" width="600" height="600">
  </figure>
  <p class="card__txt">Lorem ipsum tempus fugit.</p>
</div>

这是棘手的部分:图像是可选,并且在显示时,宽度不得超过50%。

当我为图片添加最大宽度时,如果图片不存在,文本将不会展开。

这是我目前的状态:

.card {
  display: grid;
  column-gap: 1em;
  grid-template-columns: minmax(0, 50%) 1fr;
}

我试图弄乱grid-template-columns的宽度,但是我对此还不熟悉。


您可以在此Codepen上看到它的运行情况:https://codepen.io/tcharlss/pen/gVvOjY

这是代码段:

/* Layout stuff I'm strugling width*/

.card {
  display: grid;
  column-gap: 1em;
  grid-template-columns: minmax(0, 50%) 1fr;
}

/* Decoration & miscellaneous */

body { font-family: sans; }
.container {
  display: grid;
  column-gap: 1em;
  grid-template-columns: repeat(auto-fill, 35em);
}
.container + .container {
  margin-top: 2em;
}
.explication {
  color: hsl(230, 100%, 45%);
  font-family: monospace;
  font-style: italic;
}
.card {
  border: 1px solid hsl(230, 100%, 45%);
  min-height: 18em;
}
.card__txt {
  background-color: hsl(0, 0%, 90%);
  margin: 0;
}
figure {
  margin: 0;
}
img {
  max-width: 100%;
  height: auto;
}
<div class="container">

  <div class="col">
    <p class="explication">If an image is present, it can't be wider then 50%</p>
    <div class="card">
      <figure card="card__img">
        <img src="https://via.placeholder.com/600" width="600" height="600">
      </figure>
      <p class="card__txt">Lorem ipsum tempus fugit. Aut rerum nostrum qui adipisci est aut. Est error omnis sit velit.</p>
    </div>
  </div>
  
  <div class="col">
    <p class="explication">Without image, the text should expand to fill all the available space</p>
    <div class="card">
      <p class="card__txt">Lorem ipsum tempus fugit. Aut rerum nostrum qui adipisci est aut. Est error omnis sit velit.</p>
    </div>
  </div>
  
</div>

3 个答案:

答案 0 :(得分:2)

最容易想到的一种方法是,以一种方式设置通用.card__text元素的样式,然后使用+组合器设置.card__img元素之后的元素的样式与此不同:

/* here we use Grid layout, setting two columns
   each of 1fr (using the repeat() function): */
.card {
  display: grid;
  grid-gap: 1em;
  grid-template-columns: repeat(2, 1fr);
}

/* setting the default presentation of the
   .card__txt elements; positioning them
   in the first column, spanning two
   columns: */
.card__txt {
  grid-column: 1 / span 2;
}

/* separately styling the .card__txt elements
   that follow a .card__img element; here we
   place them in the second column: */
.card__img + .card__txt {
  grid-column: 2;
}

/* Decoration & miscellaneous */

body {
  font-family: sans;
}

.container {
  display: grid;
  column-gap: 1em;
  grid-template-columns: repeat(auto-fill, 35em);
}

.container+.container {
  margin-top: 2em;
}

.explication {
  color: hsl(230, 100%, 45%);
  font-family: monospace;
  font-style: italic;
}

.card {
  border: 1px solid hsl(230, 100%, 45%);
  min-height: 18em;
}

.card__txt {
  background-color: hsl(0, 0%, 90%);
  margin: 0;
}

figure {
  margin: 0;
}

img {
  max-width: 100%;
  height: auto;
}


/* changes */

.card {
  display: grid;
  grid-gap: 1em;
  grid-template-columns: repeat(2, 1fr);
}

.card__txt {
  grid-column: 1 / span 2;
}

.card__img+.card__txt {
  grid-column: 2;
}
<div class="container">

  <div class="col">
    <p class="explication">If an image is present, it can't be wider then 50%</p>
    <div class="card">

      <!-- Note the correction, in your posted code the following
           was written:
      <figure card="card__img">
      I corrected 'card' to 'class' -->
      <figure class="card__img">
        <img src="https://via.placeholder.com/600" width="600" height="600">
      </figure>
      <p class="card__txt">Lorem ipsum tempus fugit. Aut rerum nostrum qui adipisci est aut. Est error omnis sit velit.</p>
    </div>
  </div>

  <div class="col">
    <p class="explication">Without image, the text should expand to fill all the available space</p>
    <div class="card">
      <p class="card__txt">Lorem ipsum tempus fugit. Aut rerum nostrum qui adipisci est aut. Est error omnis sit velit.</p>
    </div>
  </div>

</div>

JS Fiddle demo

答案 1 :(得分:1)

我认为the answer by @DavidThomas和在这种特定情况下一样好。

在当前的Grid(Level 1)迭代中似乎没有什么更好的。

为清楚起见,以下是对该问题的描述:

您已经定义了一个两列网格:

.card {
  display: grid;
  column-gap: 1em;
  grid-template-columns: minmax(0, 50%) 1fr;
}

使用grid-template-columns创建了 explicit 列。这样的列从一开始就内置在网格中,无法删除。这些列已被占用或未被占用。

这就是示例中没有图像的文本不会展开的原因:第一列保留其空间,该空间定义为minmax(0, 50%)

人们可能会认为该列在未占用时将默认为 min 值(0),从而使第二列(1fr)在容器中扩展。

但事实并非如此。 The minmax() function defaults to the max value.这就是为什么您在示例中看到50%的空白区域而没有图像的原因。


除了@DavidThomas提出的选择器向导之外,我能想到的解决方案的最佳方法包括从grid-template-columns切换到grid-auto-columns

这会将您从显式网格(始终存在列)带到隐式网格(必要时存在列)。此方法还可以消除列间隙。

但是这种方法有许多障碍要克服,包括:

  • 您必须更改元素的顺序(图像必须在文本之后,因为否则minmax(0, 50%)将始终是第一列; order属性将无济于事,因为它适用到项目,而不是列);
  • 将列设置为min-content并将项目设置为max-width: 50%都不起作用,因为在这种情况下,您使用的是图像,浏览器根据图像的宽度计算列宽指定的值,而不是使用的值(demo)。

但是,如果您想采用这种方法,请按以下步骤进行操作:

答案 2 :(得分:0)

结合了repeat()auto-fitminmax()的解决方案:

.card {
  display: grid;
  column-gap: 1em;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); }

每个项目最多可以占可用空间的一小部分,因此,如果有2个,则为50%,如果有一个,则为100%。

  • 通用机制

    例如,如果容器为500px(无间隙)且minmax的最小值为100px,则auto-fit将创建5个100px的显式列,将您的项目放置在这些列中(如果有5个以上的项目,则创建新行),如果某些列为空,则将其折叠(如果有的话,将其间隙),最后将最多包含项的列拉伸到最大值(从minmax开始)。
  • 在您的示例中

    容器为560px,间距为16px,因此自动调整会创建4列100px的列(加上16 * 3 = 48px的间距-不能设为5列,因为它将是564像素),并根据是否有图片而折叠2或3,然后将项目的列拉伸到可用空间的一小部分。

我叉了你的笔here

我使用了CSS-Tricks article来介绍自动调整/自动填充和Firefox检查器网格工具。