skip to Main Content

I have been looking for a satisfactory answer to this for a while using both Google/Stackoverflow and ChatGPT, but I really can’t figure it out.

I am trying to create a box (main-container) containing 3 x 3 smaller boxes (square). The idea is for main-container to have a higher z-index than square and for square to be transparent, so that when I animate something going through, the animated element (at, say, z-index 1) would be hidden when going through the space between the squares (i.e. the visible portion of main-container), but visible when going through a square.

The code below works, but only using black as background-color for main-container. I would like to be able to obtain the same result with any color.

// Create a colored square element
var square = document.createElement('div');
square.style.width = '2vw';
square.style.height = '2vw';
square.style.backgroundColor = 'red';
square.style.position = 'absolute';

// Set the initial position of the square to center left
square.style.left = '0';
square.style.top = 'calc(50vh - 1vw)';

// Add the square element to the page
document.body.appendChild(square);

// Animate the square
function animateSquare() {
  var currentPosX = parseFloat(square.style.left);
  
  // Update the square's position
  var newPosX = currentPosX + 5; // Move the square to the right by 5 pixels
  
  square.style.left = newPosX + 'px';

  // Check if the square has reached the center right
  if (newPosX + square.offsetWidth >= window.innerWidth / 2) {
    // If the square has reached the center right, stop animating
    return;
  }
  
  // Continue animating
  requestAnimationFrame(animateSquare);
}

// Start the animation
animateSquare();
.main-container {
  position: relative;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  width: 30vw;
  height: 30vw;
  align-items: center;
  justify-content: space-evenly;
  padding: 1%;
  border: solid 1px gray;
  border-radius: 10%;
  background-color: black;
  mix-blend-mode: hard-light;
  z-index: 3;
}

.square {
  width: 24%;
  height: 24%;
  margin: 1%;
  border-radius: 20%;
  background-color: rgb(204, 118, 118);
  z-index: -1;
}
<div class="main-container">
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
  <div class="square"></div>
</div>

3

Answers


  1. Maybe grid?

    More information – GRID

    Example

     
    /* style of container */
    .grid {
      width: 94px;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      grid-column-gap: 2px;
      grid-row-gap: 2px;
      background-color: #000;
      border-radius: 10px;
    }
    
    /* style of elements */
    .grid div {
      width: 30px;
      height: 30px;
      background-color: #000;
      color: #000;
      border-radius: 10px;
    
      cursor: pointer;
    
      /* for text center position */
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    /* highlighted sub element by backround */
    .grid div:hover {
      background-color: #999;
    }
    <div class="grid">
      <!-- 1. row -->
      <div>1.1</div>
      <div>1.2</div>
      <div>1.3</div>
      <!-- 2. row -->
      <div>2.1</div>
      <div>2.2</div>
      <div>2.3</div>
      <!-- 3. row -->
      <div>3.1</div>
      <div>3.2</div>
      <div>3.3</div>
    </div>

    I have created a grid. Its background color matches the background and text color of its elements. When I hover over one of the elements, instead of changing the z-index, I change the background color, making the text on it visible along with the element.

    You didn’t quite convey the objective and desired outcome you want to achieve… If I misunderstood something, please let me know!

    Login or Signup to reply.
  2. I think you need a mask for elements. See this Clipping and Masking in CSS article but you’ll have to create the vector yourself.

    Create a vector that’s exactly the same with the picture you’ve provided but only the places you want the animation to be visible should be filled. Then simply mask the element that’s being animated to the vector.

    Login or Signup to reply.
  3. Create an SVG image (easier to use an SVG editor) with <clipPath id="clip" clipPathUnits="objectBoundingBox"> and use it as your element’s CSS clip-path

    Here’s an example with 9 squares (you can create squares with rounded borders as in your example. This one is a proof of concept)

    body {
      background-color: #4a9;
    }
    
    .grid {
      position: relative;
      background: url(https://placekitten.com/408/287) 50% / cover;
      width: 300px;
      height: 300px;
      clip-path: url(#clip);
    }
    
    .ball {
      display: flex;
      justify-content: center;
      align-items: center;
      background: gold;
      border-radius: 50%;
      width: 50%;
      height: 50%;
      animation: moveBall 2s ease-in-out alternate infinite;
    }
    
    @keyframes moveBall {
      0%   { translate: -20% -20%; }
      100% { translate: 120% 120%; }
    }
    <div class="grid">
      <div class="ball">HI!</div>
    </div>
    
    <svg id="clipSvg" x="0px" y="0px" viewBox="0 0 1 1" style="width: 100%; height: 100%;">
      <defs>
        <clipPath id="clip" clipPathUnits="objectBoundingBox">
          <rect x="0" y="0" width="0.32" height="0.32" fill="black"/>
          <rect x="0.34" y="0" width="0.32" height="0.32" fill="black"/>
          <rect x="0.68" y="0" width="0.32" height="0.32" fill="black"/>
          <rect x="0" y="0.34" width="0.32" height="0.32" fill="black"/>
          <rect x="0.34" y="0.34" width="0.32" height="0.32" fill="black"/>
          <rect x="0.68" y="0.34" width="0.32" height="0.32" fill="black"/>
          <rect x="0" y="0.68" width="0.32" height="0.32" fill="black"/>
          <rect x="0.34" y="0.68" width="0.32" height="0.32" fill="black"/>
          <rect x="0.68" y="0.68" width="0.32" height="0.32" fill="black"/>
        </clipPath>
      </defs>
    </svg>

    If you want your ball to be visible even on the outside, than the task is even simpler. Create a black SVG shape with the desired perforations (rounded squares), play with the z-indexes of that shape inside its container, make sure the ball has a lower z-index than the perforated shape.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search