我可以使用动态行数或列数制作 CSS 网格吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43115822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 12:30:09  来源:igfitidea点击:

Can I make a CSS grid with dynamic number of rows or columns?

csscss-grid

提问by art-solopov

What I wanna do is to make a CSS gridwith a dynamic number of cells. For the sake of simplicity, let's assume there will always be four cells per row. Can I specify a grid with such a dynamic number of rows?

我想做的是用动态数量的单元制作一个CSS 网格。为简单起见,我们假设每行总是有四个单元格。我可以指定一个具有如此动态行数的网格吗?

To make it easier, here's the Flexbox implementation:

为方便起见,这里是 Flexbox 实现:

const COLORS = [
  '#FE9',
  '#9AF',
  '#F9A',
  "#AFA",
  "#FA7"
];

function addItem(container, template) {
  let color = COLORS[_.random(COLORS.length - 1)];
  let num = _.random(10000);
  
  container.append(Mustache.render(template, { color, num }));
}

$(() => {
  const tmpl = $('#item_template').html()
  const container = $('#app');
  
  for(let i=0; i<5; i++) { addItem(container, tmpl); }
  
  $('#add_el').click(() => {
    addItem(container, tmpl);
  })
  
  container.on('click', '.del_el', (e) => {
    $(e.target).closest('.item').remove();
  });
});
.container {
  width: 100%;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
}
.container .item {
  flex: 0 0 calc(25% - 1em);
  min-height: 120px;
  margin: 0.25em 0.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app" class="container">
</div>

<button id="add_el">Add element</button>

<template id="item_template">
  <div class="item" style="background: {{color}}">
    <p>{{ num }}</p>
    <p>
      <button class="del_el">Delete</button>
    </p>
  </div>
</template>

P.S.Apparently, I wasn't clear enough the first time... I want to recreate this effect using the latest CSS Grid Layout.

PS显然,我第一次不够清楚......我想使用最新的CSS Grid Layout重新创建这种效果

采纳答案by art-solopov

Okay, after reading the MDN reference,I found the answer! The key to dynamic rows (or columns) is the repeatproperty.

好的,在阅读了MDN 参考之后,我找到了答案!动态行(或列)的关键是repeat属性。

const COLORS = [
  '#FE9',
  '#9AF',
  '#F9A',
  "#AFA",
  "#FA7"
];

function addItem(container, template) {
  let color = COLORS[_.random(COLORS.length - 1)];
  let num = _.random(10000);
  
  container.append(Mustache.render(template, { color, num }));
}

$(() => {
  const tmpl = $('#item_template').html()
  const container = $('#app');
  
  for(let i=0; i<5; i++) { addItem(container, tmpl); }
  
  $('#add_el').click(() => {
    addItem(container, tmpl);
  })
  
  container.on('click', '.del_el', (e) => {
    $(e.target).closest('.item').remove();
  });
});
.container {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(auto-fill, 120px);
  grid-row-gap: .5em;
  grid-column-gap: 1em;
}

.container .item {
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app" class="container">
</div>

<button id="add_el">Add element</button>

<template id="item_template">
  <div class="item" style="background: {{color}}">
    <p>{{ num }}</p>
    <p>
      <button class="del_el">Delete</button>
    </p>
  </div>
</template>

P.S.Or you can use grid-auto-rowsin my particular example.

PS或者您可以grid-auto-rows在我的特定示例中使用。

回答by Adam K.

Something like this?

像这样的东西?

$(document).ready(function() {
 //Prepare Element selectors
  var cssElem = $("#Dynam"), rowElem = $("#rows"), columnElem = $("#columns"), appElem = $("#app");
  var noItems = $(".item").length,defaultColumns = 4;
    
  //Init default state
  cssElem.html(".container .item {flex: 0 0 calc(" + (100 / defaultColumns) + "% - 1em);}");
  columnElem.val(defaultColumns);
  rowElem.val(Math.ceil(noItems / columnElem.val()));

  //Add listeners to change
  appElem.on("DOMSubtreeModified", function() {
    noItems = $(".item").length;
    rowElem.val(Math.ceil(noItems / columnElem.val()));
  });
  columnElem.on("change", function() {
    rowElem.val(Math.ceil(noItems / columnElem.val()));
    cssElem.html(".container .item {flex: 0 0 calc(" + (100 / columnElem.val()) + "% - 1em);}");
  });
  rowElem.on("change", function() {
    columnElem.val(Math.ceil(noItems / rowElem.val()));
    cssElem.html(".container .item {flex: 0 0 calc(" + (100 / columnElem.val()) + "% - 1em);}");
  });
});

const COLORS = ['#FE9', '#9AF', '#F9A', "#AFA", "#FA7"];

function addItem(container, template) {
  let color = COLORS[_.random(COLORS.length - 1)];
  let num = _.random(10000);

  container.append(Mustache.render(template, {
    color,
    num
  }));
}

$(() => {
  const tmpl = $('#item_template').html()
  const container = $('#app');

  for (let i = 0; i < 5; i++) {
    addItem(container, tmpl);
  }

  $('#add_el').click(() => {
    addItem(container, tmpl);
  })

  container.on('click', '.del_el', (e) => {
    $(e.target).closest('.item').remove();
  });
});
.container {
  width: 100%;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
}

.container .item {
  min-height: 120px;
  margin: 0.25em 0.5em;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style id="Dynam"></style>
<button id="add_el">Add element</button> rows:
<input id="rows" /> columns:<input id="columns" />

<div id="app" class="container">
</div>

<template id="item_template">
  <div class="item" style="background: {{color}}">
    <p>{{ num }}</p>
    <p>
      <button class="del_el">Delete</button>
    </p>
  </div>
</template>

回答by user2705463

You don't need to use repeat. Instead you can just use set a variable --grid-template-columns from your javascript code.

您不需要使用重复。相反,您可以使用 javascript 代码中的设置变量 --grid-template-columns 。

rootEl.style.setProperty('--grid-template-columns' theGridTemplateColumnsValue)

rootEl.style.setProperty('--grid-template-columns' theGridTemplateColumnsValue)

theGridTemplateColumnsValue is a string that can also contains other css variables. This way you can have a dynamic number of columns per row.

theGridTemplateColumnsValue 是一个字符串,它也可以包含其他 css 变量。通过这种方式,您可以拥有每行动态的列数。

回答by Vic Seedoubleyew

For those landing here looking for a way to have a sort of dynamic table, with items wrapping to new rows, and still being aligned across rows, a pretty good solution is to use flexwith flex-wrapand flex: 1for all elements:

对于那些在这里登陆寻找一种方式,有一种动态表的,与项目包装到新行,同时在整个行对齐,一个不错的解决方案是使用flexflex-wrapflex: 1所有元素:

.container {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.container .item {
  flex: 1;
}

回答by Alex Varghese

Simply use below code to generate grid columns automatically

只需使用下面的代码自动生成网格列

.container {
  display: grid;
  grid-auto-flow: column;
}

回答by Evyatar Saias

Another option is to use JavaScript to set the gridTemplateRows and the gridTemplateColumns attributes dynamically. This can be done as follows:

另一种选择是使用 JavaScript 动态设置 gridTemplateRows 和 gridTemplateColumns 属性。这可以按如下方式完成:

function initDynamicGrid(numRows, numColumns){
      const totalSqaures = numRows * numColumns;
      let rowsString = "";
      let columnsString = "";
      for(let i = 0; i < numRows;i++){
        if(i === numRows -1){
          rowsString +="1fr";
        }else{
          rowsString +="1fr ";
        }
      }
      for(let i = 0; i < numColumns;i++){
        if(i === numColumns -1){
          columnsString +="1fr";
        }else{
          columnsString +="1fr ";
        }
      }
      let gridContainer = document.createElement('div');
      gridContainer.style.display ="grid";
      gridContainer.style.gridTemplateRows = rowsString;
      gridContainer.style.gridTemplateColumns = columnsString;

      for(let i = 0; i < totalSqaures; i++){
        let squareInGrid = document.createElement('div');
         // Here you can put stuff into the squareInGrid or append css to it.
        gridContainer.appendChild(squareInGrid );
      }
}

It might not be too fancy but its a nice and simple way to get the job done. I hope this helped somebody.

它可能不太花哨,但它是完成工作的一种很好且简单的方法。我希望这对某人有所帮助。