Azhorabai
Azhorabai

Reputation: 111

Using the CSS Grid repeat() declaration in JavaScript

I need to understand how I can utilize the repeat() from CSS Grid in JavaScript to do the following:

let variable = prompt("number");

el.style.setProperty('grid-template-columns: repeat(variable, 1fr)')

Doing the following does not work either:

el.style.setProperty('grid-template-columns: repeat(' + variable + ', 1fr)')

I've tried concatenating the variable in the repeat() but it does not go through.

Upvotes: 1

Views: 4194

Answers (1)

David Thomas
David Thomas

Reputation: 253456

First – as an edit, unfortunately – your original code didn't work because with:

el.style.setProperty('grid-template-columns: repeat(' + variable + ', 1fr)')

You tried to set the property incorrectly; CSSStyleDeclaration.setProperty() requires two – or three – comma-separated arguments; to update the property you need to change your approach to use:

el.style.setProperty('grid-template-columns', 'repeat(' + variable + ', 1fr)');

The third argument is, as the documentation (linked below) shows, the priority (which should be either "!important", undefined or ""; if no value is supplied the argument is treated as an empty string).

Your approach seems reminiscent of an attempt to update the style attribute of the HTMLElement; which can be modified with a string but using the available methods (such as the one you were attempting to use) is almost certainly far more reliable for those browsers in which they're available.

However, to use the style attribute string-modification approach:

document.querySelector('#setRepeats').addEventListener('click', function() {
  let grid = document.getElementById('box'),
    repeatNumber = document.getElementById('repeatNumber').value;
  // using HTMLElement.setAttribute() to update the style attribute of the
  // 'grid' node:
  grid.setAttribute('style',
    // updating the attribute with the following concatenated string:
    'grid-template-columns: repeat(' + repeatNumber + ', 1fr)');
});
#box {
  display: grid;
  grid-template-columns: repeat( var(--repeatNumber, 2), 1fr);
  grid-gap: 5px;
}

.elements:nth-child(odd) {
  background-color: #ccc;
}

.elements:nth-child(even) {
  background-color: #fff;
}
<label for=""><input type="number" id="repeatNumber"></label>
<button id="setRepeats" type="button">Update repeats</button>
<div id="box">
  <div class="elements">1</div>
  <div class="elements">2</div>
  <div class="elements">3</div>
  <div class="elements">4</div>
  <div class="elements">5</div>
  <div class="elements">6</div>
  <div class="elements">7</div>
  <div class="elements">8</div>
  <div class="elements">9</div>
  <div class="elements">10</div>
  <div class="elements">11</div>
  <div class="elements">12</div>
  <div class="elements">13</div>
  <div class="elements">14</div>
  <div class="elements">15</div>
</div>

JS Fiddle demo.

However, one further approach, using CSSStyleDeclaration.setProperty() correctly:

// here we bind an event-listener, the anonymous function, to the 'click'
// events received on the <button> element (with the id of 'setRepeats'):
document.querySelector('#setRepeats').addEventListener('click', function() {

  // retrieving the element whose property we wish to update:
  let grid = document.getElementById('box'),

    // retrieving the element from which the number is received:
    repeatNumber = document.getElementById('repeatNumber').value;

  // accessing the CSSStyleDeclaration Object of the 'grid'
  // node:
  grid.style

    // updating/setting the 'grid-template-columns'
    // property of the 'grid' node, first identifying
    // the property and then assigning the value
    // (here we use a template literal to concatenate
    // the retrieved variable into the string):
    .setProperty('grid-template-columns', `repeat(${repeatNumber}, 1fr)`);
});
#box {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 5px;
}

.elements:nth-child(odd) {
  background-color: #ccc;
}

.elements:nth-child(even) {
  background-color: #fff;
}
<label for=""><input type="number" id="repeatNumber"></label>
<button id="setRepeats" type="button">Update repeats</button>
<div id="box">
  <div class="elements">1</div>
  <div class="elements">2</div>
  <div class="elements">3</div>
  <div class="elements">4</div>
  <div class="elements">5</div>
  <div class="elements">6</div>
  <div class="elements">7</div>
  <div class="elements">8</div>
  <div class="elements">9</div>
  <div class="elements">10</div>
  <div class="elements">11</div>
  <div class="elements">12</div>
  <div class="elements">13</div>
  <div class="elements">14</div>
  <div class="elements">15</div>
</div>

JS Fiddle demo.

document.querySelector('#setRepeats').addEventListener('click', function() {
  let grid = document.getElementById('box'),
    repeatNumber = document.getElementById('repeatNumber').value;
    
  // here we update the CSS Custom Property identified by its name
  // of '--repeatNumber' (the double-hyphen prefix identifies the
  // property as a custom property), updating its value to that
  // held within the 'repeatNumber' variable:
  grid.style
    .setProperty('--repeatNumber', repeatNumber);
});
#box {
  display: grid;
  /* taking advantage of the CSS var() function's ability to use a
     default value should the supplied variable not resolve (or
     resolve to an invalid value); here 2 is the default to be used
     in the event that the CSS custom property '--repeatNumber'
     is unavilable or invalid. As the property isn't defined on
     page-load the page first loads with the default value of 2: */
  grid-template-columns: repeat( var(--repeatNumber, 2), 1fr);
  grid-gap: 5px;
}

.elements:nth-child(odd) {
  background-color: #ccc;
}

.elements:nth-child(even) {
  background-color: #fff;
}
<label for=""><input type="number" id="repeatNumber"></label>
<button id="setRepeats" type="button">Update repeats</button>
<div id="box">
  <div class="elements">1</div>
  <div class="elements">2</div>
  <div class="elements">3</div>
  <div class="elements">4</div>
  <div class="elements">5</div>
  <div class="elements">6</div>
  <div class="elements">7</div>
  <div class="elements">8</div>
  <div class="elements">9</div>
  <div class="elements">10</div>
  <div class="elements">11</div>
  <div class="elements">12</div>
  <div class="elements">13</div>
  <div class="elements">14</div>
  <div class="elements">15</div>
</div>

JS Fiddle demo.

References:

Upvotes: 8

Related Questions