使用CSS Grid设置最小和最大列数

Sum*_*gga 14 html css css3 css-grid

我有10个div(64px x 64px),我希望最多显示5列(适用于大视口和超大视口),最少3列(适用于iPhone 7等小视口).

我试图用CSS Grid做到这一点,但不能做最小列部分(即使有空间来容纳3个col,它也会变为2列).

body {
  background-color: wheat;
}

.parent {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(100px, 140px));
  max-width: 800px;
}

.child {
  height: 64px;
  width: 64px;
  background-color: brown;
}
Run Code Online (Sandbox Code Playgroud)
<body>
  <div class="parent">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>
Run Code Online (Sandbox Code Playgroud)

网格容器的最大宽度为800px.

这是Codepen的链接

编辑:如果可能,我想只使用CSS Grid完成此操作,即不使用Media Queries或Flexbox.

Ber*_*nat 80

我一直在寻找相同的答案,由于我找不到这个问题的任何有用的答案,所以我设法自己解决了它。这是我的解决方案,仅使用 CSS 网格即可完美运行。

长话短说

解决方案 A - 推荐(3 - 5 列,每列最小宽度为 64px)

/* Note the difference with solution B on the grid-template-columns value */

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%/3, max(64px, 100%/5)), 1fr));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}
Run Code Online (Sandbox Code Playgroud)

/* Note the difference with solution B on the grid-template-columns value */

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%/3, max(64px, 100%/5)), 1fr));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}
Run Code Online (Sandbox Code Playgroud)
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%/3, max(64px, 100%/5)), 1fr));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}


/* Styles not related to the goal */
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin-top: 0;
  text-align: center;
}

.parent {
  justify-content: space-evenly;
  margin: 0 auto;
  padding: 5px;
  border: 5px solid dodgerblue;
  background: wheat;
  overflow: hidden;
  resize: both;
}

.child {
  margin: 0 auto;
  border: 2px solid brown;
}
Run Code Online (Sandbox Code Playgroud)

解决方案 B(3 - 5 列,每列宽度恰好为 64px)

/* Note the difference with solution A on the grid-template-columns value */

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, min(100%/3, max(64px, 100%/5))));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}
Run Code Online (Sandbox Code Playgroud)

<p>You can resize the blue container</p>

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>
Run Code Online (Sandbox Code Playgroud)
/* Note the difference with solution A on the grid-template-columns value */

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, min(100%/3, max(64px, 100%/5))));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}
Run Code Online (Sandbox Code Playgroud)

可重用的解决方案(Sass mixin)

如果您想要一个可重用的函数来轻松生成具有不同最大和最小列值的列布局,允许您在列之间添加一些间隙或调整列的最小宽度,您应该利用 Sass mixins 和 CSS 变量,如下所示:

/* For solution A - recommended */
@mixin grid-min-max-cols($min-cols, $max-cols, $cols-min-width, $grid-row-gap: 0px, $grid-column-gap: 0px) {
  --min-cols: #{$min-cols};
  --max-cols: #{$max-cols};
  --cols-min-width: #{$cols-min-width};
  --grid-row-gap: #{$grid-row-gap};
  --grid-column-gap: #{$grid-column-gap};
  
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min((100%/var(--min-cols) - var(--grid-column-gap)*(var(--min-cols) - 1)/var(--min-cols)), max(var(--cols-min-width), (100%/var(--max-cols) - var(--grid-column-gap)*(var(--max-cols) - 1)/var(--max-cols)))), 1fr));
  gap: var(--grid-row-gap) var(--grid-column-gap);
}

/* For solution B */
@mixin grid-min-max-cols($min-cols, $max-cols, $cols-min-width, $grid-row-gap: 0px, $grid-column-gap: 0px) {
  --min-cols: #{$min-cols};
  --max-cols: #{$max-cols};
  --cols-min-width: #{$cols-min-width};
  --grid-row-gap: #{$grid-row-gap};
  --grid-column-gap: #{$grid-column-gap};
  
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, min((100%/var(--min-cols) - var(--grid-column-gap)*(var(--min-cols) - 1)/var(--min-cols)), max(var(--cols-min-width), (100%/var(--max-cols) - var(--grid-column-gap)*(var(--max-cols) - 1)/var(--max-cols))))));
  gap: $grid-row-gap $grid-column-gap;
}

.parent {
  @include grid-min-max-cols(3, 5, 64px, 5px, 5px);
}
Run Code Online (Sandbox Code Playgroud)

检查我的 CodePen 以查看两个可重用解决方案(A 和 B)的完整功能示例:

https://codepen.io/btous/pen/QWvGNGm

与 Flexbox 类似的方法

检查我的 CodePen 以查看使用 Flexbox 的类似方法的完整功能示例:

https://codepen.io/btous/pen/OJzwdJw

让我们更深入吧!

了解CSS 属性minmax()中的功能grid-template-columns

CSS语句告诉浏览器根据元素容器自身的宽度以及函数的和值grid-template-columns: repeat(auto-fit, minmax(min, max))来计算元素容器的列数。所以解决这个问题的关键是要了解函数内部是如何工作的,关于minmaxminmax()minmax(min, max)repeat()grid-template-columns CSS属性上是如何工作的。

  1. 如果我们有一个具有以下 CSS 属性和值 的网格容器,它会获取该容器并将其划分为与参数grid-template-columns: repeat(auto-fit, minmax(min, max)宽度相符的尽可能多的列。因此,如果我们在 500px 容器上设置该属性,它会将其分为 5 列,每列 100px,因为这是maxminmax()grid-template-columnsrepeat(auto-fit, minmax(50px, 100px)maxminmax()
  2. 如果容器将其宽度增加到 550 像素,它仍然可以容纳最多 5 列(因为要容纳另一个 100 像素列,它的宽度应该至少为 600 像素),但它将有 50 像素的剩余空间留空。
  3. 如果函数的第二个值minmax()小于第一个值,则将第一个值作为最终值,因此minmax(100px, 50px)结果为 100px。
  4. 如果该max值设置为 1fr(1 个分数),浏览器的行为将如第一点和第二点中所述,但使用该min值来计算划分容器的列数,如果有任何剩余空间,它将在所有列之间均匀分配。因此,如果我们将该grid-template-columns属性设置为repeat(auto-fit, minmax(100px, 1fr)与第二个点上定义的容器宽度相同 (550px) 的容器,它仍然最多可容纳 5 列,并且将有 50px 的剩余空间,但不会保留此剩余空间空,相反,它将与所有 5 列(每列 20 像素)均匀分布,从而形成每列 120 像素的 5 列布局。

有关更多详细信息,请参阅此 CSS-TRICKS 帖子:

https://css-tricks.com/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit

现在我们知道了它是如何工作的,我们可以面对问题并逐步解决它,为函数设置minmax参数minmax()

我们有两种不同的方法让grid-template-columns属性计算列数:

  • 第一个,如第四点所解释的,是将值设置min为我们想要的每列宽度,并将max值设置为 1fr

    minmax(?px, 1fr)
    
    Run Code Online (Sandbox Code Playgroud)
  • 第二个,正如前两点所解释的,是将值设置max为我们想要的每列宽度,并将min值设置为 0px,因为我们要确保参数min永远不会高于参数max以避免它被采用作为第三点解释的最终值

    minmax(0px, ?px)
    
    Run Code Online (Sandbox Code Playgroud)

这里的要点是,如果为?设置的值 符号是静态的,当容器可以容纳超过所需的最大列数时,它将继续将它们添加到布局中,当容器中没有可用空间来容纳所需的最小列数时,它将继续删除它们从布局来看。

好吧,现在我们知道我们需要让浏览器动态计算这个值,以确保它永远不会破坏我们定义的最大和最小列布局,所以让我们开始吧!

minmax()动态计算函数的列宽

这是最棘手的部分。首先,我们需要列数永远不会超过我们想要的最大列数(在您的情况下为 5,但可以是任何值)。

为了实现这一点,我们必须确保列宽永远不会超过容器宽度除以最大列数(5 为您),即 100%/5,所以现在我们有以下内容:

/* For solution A - recommended (note the difference with solution B on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(calc(100%/5), 1fr));
}

/* For solution B (note the difference with solution A on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, calc(100%/5)));
}
Run Code Online (Sandbox Code Playgroud)

很酷,现在布局不超过 5 列的最大值,但它始终返回 5 列布局,因为容器始终可以容纳 5 列相同宽度除以 5 的内容。请参阅下面的代码片段:

方案一:

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, min(100%/3, max(64px, 100%/5))));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}


/* Styles not related to the goal */
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin-top: 0;
  text-align: center;
}

.parent {
  justify-content: space-evenly;
  margin: 0 auto;
  padding: 5px;
  border: 5px solid dodgerblue;
  background: wheat;
  overflow: hidden;
  resize: both;
}

.child {
  margin: 0 auto;
  border: 2px solid brown;
}
Run Code Online (Sandbox Code Playgroud)
<p>You can resize the blue container</p>

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

方案B:

/* For solution A - recommended */
@mixin grid-min-max-cols($min-cols, $max-cols, $cols-min-width, $grid-row-gap: 0px, $grid-column-gap: 0px) {
  --min-cols: #{$min-cols};
  --max-cols: #{$max-cols};
  --cols-min-width: #{$cols-min-width};
  --grid-row-gap: #{$grid-row-gap};
  --grid-column-gap: #{$grid-column-gap};
  
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min((100%/var(--min-cols) - var(--grid-column-gap)*(var(--min-cols) - 1)/var(--min-cols)), max(var(--cols-min-width), (100%/var(--max-cols) - var(--grid-column-gap)*(var(--max-cols) - 1)/var(--max-cols)))), 1fr));
  gap: var(--grid-row-gap) var(--grid-column-gap);
}

/* For solution B */
@mixin grid-min-max-cols($min-cols, $max-cols, $cols-min-width, $grid-row-gap: 0px, $grid-column-gap: 0px) {
  --min-cols: #{$min-cols};
  --max-cols: #{$max-cols};
  --cols-min-width: #{$cols-min-width};
  --grid-row-gap: #{$grid-row-gap};
  --grid-column-gap: #{$grid-column-gap};
  
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, min((100%/var(--min-cols) - var(--grid-column-gap)*(var(--min-cols) - 1)/var(--min-cols)), max(var(--cols-min-width), (100%/var(--max-cols) - var(--grid-column-gap)*(var(--max-cols) - 1)/var(--max-cols))))));
  gap: $grid-row-gap $grid-column-gap;
}

.parent {
  @include grid-min-max-cols(3, 5, 64px, 5px, 5px);
}
Run Code Online (Sandbox Code Playgroud)
minmax(?px, 1fr)
Run Code Online (Sandbox Code Playgroud)

为了让布局在减少宽度时减少列,我们必须告诉他你想要的最小列宽,即 64px,这样只要列不适合容器宽度,它就可以开始删除列。

我们将通过将函数的参数包装minmax()在一个max()函数中来实现这一点,该函数将取两个参数之间的最大值(所需的最小列宽,即 64px,以及我们已有的,即 calc(100%/5)) ),给我们以下内容:

/* For solution A - recommended (note the difference with solution B on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(max(64px, 100%/5), 1fr));
}

/* For solution B (note the difference with solution A on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, max(64px, 100%/5)));
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们不需要该calc()函数在max().

使用上面的代码,只要 100%/5 的结果小于 64px,它就会将max()函数值设置为 64px,并且该minmax()函数将转换为minmax(64px, 1fr)(对于解决方案 A)或minmax(0, 64px)(对于解决方案 B),并将容器宽度除以64px 来计算可以容纳多少列。请参阅下面的片段:

方案一:

minmax(0px, ?px)
Run Code Online (Sandbox Code Playgroud)
/* For solution A - recommended (note the difference with solution B on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(calc(100%/5), 1fr));
}

/* For solution B (note the difference with solution A on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, calc(100%/5)));
}
Run Code Online (Sandbox Code Playgroud)

方案B:

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(calc(100%/5), 1fr));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}


/* Styles not related to the goal */
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin-top: 0;
  text-align: center;
}

.parent {
  justify-content: space-evenly;
  margin: 0 auto;
  padding: 5px;
  border: 5px solid dodgerblue;
  background: wheat;
  overflow: hidden;
  resize: both;
}

.child {
  margin: 0 auto;
  border: 2px solid brown;
}
Run Code Online (Sandbox Code Playgroud)
<p>You can resize the blue container</p>

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

现在我们已经正确设置了最大列数,但仍需要设置最小值(在您的情况下为 3)。为此,我们需要确保 for 的参数minmax()永远不会高于容器的三分之一,即 100%/3。

我们将通过再次包装函数的参数来实现这一点minmax(),但在本例中,在min()函数内部,除了我们已有的值(ie)之外max(64px, 100%/5),我们还将添加在上一段中找到的值,结果如下:

/* For solution A - recommended (note the difference with solution B on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%/3, max(64px, 100%/5)), 1fr));
}

/* For solution B (note the difference with solution A on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, min(100%/3, max(64px, 100%/5))));
}
Run Code Online (Sandbox Code Playgroud)

您可以在下面的片段中看到他们的行为:

方案一:

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, calc(100%/5)));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}


/* Styles not related to the goal */
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin-top: 0;
  text-align: center;
}

.parent {
  justify-content: space-evenly;
  margin: 0 auto;
  padding: 5px;
  border: 5px solid dodgerblue;
  background: wheat;
  overflow: hidden;
  resize: both;
}

.child {
  margin: 0 auto;
  border: 2px solid brown;
}
Run Code Online (Sandbox Code Playgroud)
<p>You can resize the blue container</p>

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

方案B:

/* For solution A - recommended (note the difference with solution B on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(max(64px, 100%/5), 1fr));
}

/* For solution B (note the difference with solution A on the grid-template-columns value) */
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, max(64px, 100%/5)));
}
Run Code Online (Sandbox Code Playgroud)
.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(max(64px, 100%/5), 1fr));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}


/* Styles not related to the goal */
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin-top: 0;
  text-align: center;
}

.parent {
  justify-content: space-evenly;
  margin: 0 auto;
  padding: 5px;
  border: 5px solid dodgerblue;
  background: wheat;
  overflow: hidden;
  resize: both;
}

.child {
  margin: 0 auto;
  border: 2px solid brown;
}
Run Code Online (Sandbox Code Playgroud)

允许 CSS 列间隙

至此,我们已经设置了您的布局,但最好在不破坏网格的情况下设置间隙,所以让我们开始吧!

如果我们想将一个column-gap属性(因为行间距不会影响我们的布局)设置为,比方说,5px,当我们计算列宽来设置布局时,我们必须考虑到这个属性。如果没有,它就会破裂。

为此,我们必须从运算中减去每列的间隙​​来计算max函数的参数minmax()

我们可以通过将该值乘以列数减一来获得每列的比例列间隙column-gap,因为间隙总是比列少一个。这将导致:

/* For solution A - recommended (note the difference with solution B on the grid-template-columns value) */
.parent {
  display: grid;
  row-gap: 5px;
  column-gap: 5px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%/3 - 5px*(3-1)/3, max(64px, 100%/5 - 5px*(5-1)/5)), 1fr));
}

/* For solution B (note the difference with solution A on the grid-template-columns value) */
.parent {
  display: grid;
  row-gap: 5px;
  column-gap: 5px;
  grid-template-columns: repeat(auto-fit, minmax(0, min(100%/3 - 5px*(3-1)/3, max(64px, 100%/5 - 5px*(5-1)/5))));
}
Run Code Online (Sandbox Code Playgroud)

在下面的片段中查看他们的行为:

方案一:

.parent {
  display: grid;
  row-gap: 5px;
  column-gap: 5px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%/3 - 5px*(3-1)/3, max(64px, 100%/5 - 5px*(5-1)/5)), 1fr));
}

.child {
  width: 64px;
  height: 64px;
  max-width: 100%;
}


/* Styles not related to the goal */
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin-top: 0;
  text-


San*_*shK 5

您可以通过使用@media用于grid-template-columns: repeat(5, 1fr);大型设备的查询来获取所需的输出grid-template-columns: repeat(3, 1fr);用于小型设备

body {
  background-color: wheat;
}

.parent {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(5, 1fr);  
}

.child {
  height: 64px;
  width: 64px;
  background-color: brown;
}

@media(max-width:540px){
  .parent {
     grid-template-columns: repeat(3, 1fr);
  }
}
Run Code Online (Sandbox Code Playgroud)
<body>
  <div class="parent">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答,但是否可以在不使用媒体查询或 flexbox 的情况下做到这一点?抱歉,我在发布问题后添加了此条件。我在问题的最后提到了它。 (2认同)
  • 这可能是可能的,并且浏览器支持将受到限制。媒体查询将提供您可以根据规则进行任何布局的自由..所以需要接近更好的选择 (2认同)

weB*_*Ber 5

我想这就是你要找的。

body {
  background-color: wheat;
}

.parent {
  display: grid;
  grid-gap: 2vw;
  grid-template-columns: repeat(auto-fill, minmax(100px, 120px));
  max-width: 800px;
}

.child {
  height: 64px;
  width: 64px;
  background-color: brown;
}
Run Code Online (Sandbox Code Playgroud)
<body>
  <div class="parent">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>
Run Code Online (Sandbox Code Playgroud)

我已经改变 -grid-template-columns: repeat(auto-fill, minmax(100px, 140px));grid-template-columns: repeat(auto-fill, minmax(100px, 120px));

因为在小屏幕尺寸中,孩子将占用140px保留的区域,导致它在小屏幕中分解为 2 列,现在我已将其更改为120pxgrid-gap: 2vw;解决此问题。

我希望这对你有帮助。


Pan*_*ool 3

我希望这有帮助

https://codepen.io/pandiyancool/pen/oPmgeP

CSS

body {
  background-color: wheat;
}

.parent {
  display: flex;
  flex-wrap: wrap;
}

.child {
  height: 80px;
  padding: 25px;
  background-color: brown;
  border: 1px solid #ccc;
  flex: 1 1 160px;
  flex-basis: 20%;
}
Run Code Online (Sandbox Code Playgroud)


Copyright Info

© Copyright 2013-2021 admin@qa.1r1g.com

如未特别说明,本网站的内容使用如下协议:
Creative Commons Atution-NonCommercial-ShareAlike 4.0 International license
.

用以下方式浏览
回到顶部