Overlaying a gradient on cells within a grid

My Pen

Hello, I’m working on a JavaScript project that visualizes the amount of time a user has lived in weeks. I have a grid of cells representing each week, where the cells that the user has already lived are filled with black. I would like to overlay a gradient on top of the filled cells for design purposes.

I’m wondering if anyone has any suggestions on how I could achieve this effect? Any help or guidance would be greatly appreciated!

Well for starters, what sort of gradient are you trying to apply?

This looks to be a CSS-based presentation issue, so am moving it over to that forum for expert input.

https://imgur.com/i85mFi9

A linear gradient like the one in the image linked above.

you could try replacing

cells[weeksFilled].style.backgroundColor = BLACK;

with

cells[weeksFilled].style.border="1px solid #000"; cells[weeksFilled].style.borderRadius="50%"; cells[weeksFilled].style.backgroundImage="radial-gradient(#fff,#000)";

Thanks for your reply. What I’m looking to do is not to have each ‘owl’ class cell filled in with a gradient, but instead have the entire body of ‘owl’ cells make up a dynamic gradient.

Here is a visual https://imgur.com/i85mFi9

it’s… going to get messy, because you’re flexing the container…

I got close but no cigar as there are problems in rubbing out some odd bits and pieces.

I thought it might be possible using a css mask to reveal the background but there is the same issue as my method above of just revealing the bits you want to see.

I’ll have to have a re-think tomorrow.

Could you fake the gradient effect by giving each square a solid fill which alters gradually from one to the next?
Though that would probably revert to using JS to add the style attributes.

1 Like

Pretty much, that’s what I would have to do, but would need some extra code to handle the flexing (when a box jumps from one row to the next, etc)

2 Likes

play with these changes
1.

      // Create the grid
      for (let i = 0; i < GRID_SIZE; i++) {
        const cell = document.createElement("div");
        cell.className = "cell";
        cell.style.width = CELL_SIZE + "px";
        cell.style.height = CELL_SIZE + "px";
        cell.style.margin = CELL_MARGIN + "px";
        /* added*/
        cell.style.backgroundImage="linear-gradient(to right, #fb02a8, #9e4ece)";
        cell.style.backgroundSize="780px 15px";
        cell.style.backgroundPositionX=-15*i + "px"; 
        /* end added */
        gridContainer.appendChild(cell);
      }
      // Animate filling the grid
      function animateFillGrid() {
        const birthday = new Date(dateInput.value);
        const birthdayTimestamp = birthday.getTime();
        const now = Date.now();
        const millisecondsSinceBirth = now - birthdayTimestamp;
        const weeksSinceBirth = Math.floor(millisecondsSinceBirth / (1000 * 60 * 60 * 24 * 7));

        let weeksFilled = 0;

        const interval = setInterval(() => {
          if (weeksFilled >= weeksSinceBirth) {
            clearInterval(interval);
            return;
          }

          /*cells[weeksFilled].style.backgroundColor = BLACK;*/
          /*added*/
            cells[weeksFilled].style.border="1px solid #000"; 
            cells[weeksFilled].style.borderRadius="50%"; 
            cells[weeksFilled].style.backgroundImage="none";
            cells[weeksFilled].style.backgroundPositionX=0;
            cells[weeksFilled].style.backgroundImage="radial-gradient( #fff, #000 )"; 
            cells[weeksFilled].style.backgroundSize="13px 13px";
          /* end added */
          cells[weeksFilled].classList.add("owl"); // One Week Lived
          weeksFilled++;
          weeksLivedHeading.innerText = `${weeksFilled} weeks`;
        }, 5);
      }

If you don’t mind a little compromise then you can do it with one line of css.

e.g.

.owl{
   background: linear-gradient(45deg, red, blue) fixed !important;
  background-size:cover!important;
}

@snadyleiby thank you, this helps immensely.

@PaulOB is the compromise that it’s achieved with CSS? I love the simplicity of this solution. Thank you!

1 Like

The compromise is that it uses a fixed background to achieve the effect so effectively the gradients length is the viewport height and width.

It’s probably not noticeable but if you scroll the page then a slightly different part of the gradient is seen in the squares. (It’s often used like this for parallax effects)

One thing I should have mentioned is that mobile devices don’t like background attachment fixed combined with cover and will result in a gradient that is the length of the document not the viewport. It just means that the gradient will be less noticeable on mobile but will still work.

A couple of other notes:
The animation doesnt restart from blank if you change the date.
Consequently of above: if you put an old date in, and then a newer one, the wrong number of boxes are lit up.
Consider making the style (borrder, borderRadius) changes in your javascript part of the “owl” class, rather than the javascript. Much cleaner to just add/remove a class…

1 Like

@m_hutley Thank you for the notes.

And actually to everyone, I’m gladly taking feedback and suggestions. I will be looking for a more in depth critique when it is more polished.

Cheers!

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.