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

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

为了简单起见,下面是 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.

166627 次浏览

像这样吗?

$(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>

好的,在阅读了 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. 或者你可以在我的例子中使用 grid-auto-rows

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

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

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

对于那些在这里寻找一种动态表格的方法,包装项目到新的行,并且仍然在行之间对齐的人来说,一个相当好的解决方案是对所有元素使用 flexflex-wrapflex: 1:

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


.container .item {
flex: 1;
}

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

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

这里是网格中动态列的一个非常简单的示例

.container {
display: grid;
grid-template-columns: repeat(auto-fit, 250px);
grid-row-gap: 5px;
grid-column-gap: 5px;
justify-content: center;
width: 90%;
margin: 0 auto;
list-style: none;
}


.container>.item {
padding: 5px;
background-color: gray;
}
<div class="container">
<div class="item">item1</div>
<div class="item">item2</div>
<div class="item">item3</div>
<div class="item">item4</div>
</div>

我来寻找的是如何使浏览器计算适当的列数,同时保持行的伸展。我在 mdn docs中找到了答案。

重要的是设置一个列的最小宽度,在我的例子中我使用了200px。

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


/* The following is irrelevant for the grid logic */
.fancy-colors {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
resize: horizontal;
overflow: auto;
}


.fancy-colors > * {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
<div class="wrapper fancy-colors">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
</div>