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

前端 未结 5 2064
猫巷女王i
猫巷女王i 2020-12-13 08:51

What I wanna do is to make a CSS grid with 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

相关标签:
5条回答
  • 2020-12-13 08:59

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

    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.

    0 讨论(0)
  • 2020-12-13 09:01

    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 flex with flex-wrap and flex: 1 for all elements:

    .container {
      width: 100%;
      display: flex;
      flex-wrap: wrap;
      align-items: center;
    }
    
    .container .item {
      flex: 1;
    }
    
    0 讨论(0)
  • 2020-12-13 09:09

    Simply use below code to generate grid columns automatically

    .container {
      display: grid;
      grid-auto-flow: column;
    }
    
    0 讨论(0)
  • 2020-12-13 09:18

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

    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-rows in my particular example.

    0 讨论(0)
  • 2020-12-13 09:20

    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>

    0 讨论(0)
提交回复
热议问题