没有媒体查询的CSS网格最大列

时间:2019-03-21 13:31:57

标签: html css css3 flexbox css-grid

是否可以定义一个具有最大列数的网格,但是当屏幕宽度改变时允许元素包装到新行上?

我有一些隐含的类,它们允许行包装到新行上,但是没有最大列数。

这是使用flex boxes

的一种方法的代码笔

CSS:

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

另一种方法是使用grid

.grid {
  display: grid;
  counter-reset: grid-items;
  position: relative;
}


.grid--auto-fit {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

我想要一个相当通用的解决方案,我想在没有Java脚本或媒体查询的情况下实现什么?

3 个答案:

答案 0 :(得分:3)

对于 flexbox CSS网格,您不能明确地做到这一点-但您可以使用 hack 使用CSS Variables(通常这就是您所需要的)。


CSS网格布局

例如,您可以在:root中设置全局列号,而在网格包装器上设置特定列号-请参见下面的 CSS网格全局设置了4列:

:root {
  --columns: 3;
}

.grid {
  display: grid;
  grid-gap: 10px;
  /* adjusting for the 10px grid-gap as well */
  grid-template-columns: repeat(auto-fit, minmax(calc(100% / var(--columns) - 20px), 1fr)); 
}

.grid > * {
  background-color: green;
  height: 200px;
}
<div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>

现在,您可以通过重新声明 --columns来为网格容器上的列数设置规则(也可以让JS添加一个包含class声明的--columns)-请参见下面的演示

:root {
  --columns: 3;
}

.grid {
  display: grid;
  grid-gap: 10px;
  --columns: 4; /* re-define the number of columns */
  grid-template-columns: repeat(auto-fit, minmax(calc(100% / var(--columns) - 20px), 1fr));
}

.grid > * {
  background-color: green;
  height: 200px;
}
<div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>


Flexbox

类似的参数对 flexboxes 有效-请参见下面的简化演示

:root {
  --columns: 3;
}

.flexbox {
  display: flex;
  flex-wrap: wrap;
  --columns: 4; /* re-define the number of columns */
}

.flexbox > * {
  background-color: green;
  height: 200px;
  margin: 10px;
  flex-basis: calc(100% / var(--columns) - 20px);
}
<div class="flexbox">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>

答案 1 :(得分:3)

使用flexbox,您可以简单地为容器设置max-width,因为您的元素具有固定的宽度:

.flex-container {
  display: flex;
  flex-wrap: wrap;
  max-width:calc(5*(200px + 20px)); 
}

.flex-item {
  background: tomato;
  padding: 5px;
  width: 200px;
  height: 100px;
  margin: 10px;
  
  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing:border-box;
}
<div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
</div>

唯一的缺点是您需要知道元素的宽度及其边距,才能正确设置max-width

如果您希望元素扩展并覆盖所有宽度,可以对min-width使用以下技巧:

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

.flex-item {
  background: tomato;
  padding: 5px;
  min-width: 200px;
  width:calc(100%/5 - 20px); /*5 columns*/
  height: 100px;
  margin: 10px;
  
  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing:border-box;
}
<div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
</div>

这里您还需要考虑边距,您可以使用CSS变量轻松地使它更加灵活:

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

.flex-item {
  --m:10px;
  background: tomato;
  padding: 5px;
  min-width: 200px;
  width:calc(100%/5 - 2*var(--m)); /*5 columns*/
  height: 100px;
  margin: var(--m);
  
  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing:border-box;
}
<div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
</div>

如果您希望元素始终扩展(即使有换行),也可以考虑使用flex-grow,但是您可能会遇到需要修复一些问题的最后一行的问题:

.flex-container {
  display: flex;
  flex-wrap: wrap;
  --m:10px;
}

.flex-item {
  background: tomato;
  padding: 5px;
  min-width: 200px;
  flex-grow:1;
  width:calc(100%/5 - 2*var(--m)); /*5 columns*/
  height: 100px;
  margin: var(--m);
  
  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing:border-box;
}

.flex-container span {
  min-width: 200px;
  flex-grow:1;
  width:calc(100%/5 - 2*var(--m)); /*5 columns*/
  margin:0 var(--m);
}
<div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
  
  <!-- 4 empty elements to fix the issue (we can also use pseudo element) -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

在下面的示例中,我们将列数设为5,因此,如果在最后一行中有1-4个元素,则至少需要4个空元素才能解决此问题。当然,这是一个缺点,但是由于您知道列数,因此可以轻松设置这些空元素,并且不需要任何JS。

为了使其更加灵活,以下是有关CSS变量的想法:

.flex-container {
  display: flex;
  flex-wrap: wrap;
  border:1px solid;
  --m:10px;
  --n:5;
  --width:150px;
}

.flex-item {
  background: tomato;
  min-width: var(--width);
  flex-grow:1;
  width:calc(100%/var(--n) - 2*var(--m));
  height: 50px;
  margin: var(--m);
  
  box-sizing:border-box;
}

.flex-container span {
  display:contents; /* each span will give us 2 elements*/
}
.flex-container span:before,
.flex-container span:after,
.flex-container:before,
.flex-container:after{
  content:"";
  min-width: var(--width);
  flex-grow:1;
  width:calc(100%/var(--n) - 2*var(--m));
  margin:0 var(--m);
  order:1; /*we make sure they are at the end*/
}
<div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
  
  <!-- a lot of elements !! -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="flex-container wrap" style="--n:10">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
  
  <!-- a lot of elements !! -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="flex-container wrap" style="--n:3">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
  
  <!-- a lot of elements !! -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

我使用display:contents可以设置N个空元素,以后将其视为2 * N,这可以减少代码。

如果您将有7列,我们将仅需要6个额外的元素。我们可以使用两个伪元素,然后仅使用2个空元素来覆盖其余4个。

答案 2 :(得分:-1)

通过一些数学运算,您可以在 minmax 内的 max 函数中添加一个百分比。这样它会在 200 像素处中断,但会扩展以填充页面的 1/3(在这种情况下,因为我使用了 33%,不过只需添加您想要的任何百分比)

grid-template-columns: repeat(auto-fit, minmax(max(200px, 33%), 1fr));