Search code examples
cssgrid

Display grid: 7 items, 3 columns, last centered


I have 7 items (possible there will be 8 or 9 or more in the future) lined up in 3 vertical columns.

I would like that when there are 7, the last one is aligned in the center. Warning: I would like there to be a lag, like in my example.

If there are 8, let it fill one of the last two columns. And 9, that all the columns are filled. How to do that?

HTML :

<article class="wCard" v-for="card in workshops" :key="card._id">
        <div class="wCard__content">
          <img class="wCard__icon" :src="$urlFor(card.icon.asset.url)" />
           ………
        </div>
          
</article>

enter image description here


Solution

  • I used css grid to create a grid with 30px and 100px row heights to create top gap on right and left columns. In order to place the place boxes to the right grids i created an algorithm. First 7 elements are placed left or right columns while first and last(7th box) boxes are placed according to their index so that the last box can be at the middle. After 7th element it just keeps filling the elements with the same priority ( midle > left > right ).

    I didn't understand what you meant with lag but i assummed that you want them to be showed up after being renderer with some delay. Created a keyframe to make this happen. Hope this helps.

    Live preview: codesandbox.io

    App.js

    import "./styles.css";
    import GridBox from "./GridBox";
    import React, { useState } from "react";
    export default function App() {
      const boxCount = 11;
    
      const boxItems = [...Array(boxCount).keys()].map((key, index) => {
        let rowLocation;
        let colLocation;
        if (index < 7) {
          const rowIndex = Math.floor(index / 2) * 2;
          if (index === 0) {
            rowLocation = "1/3";
            colLocation = "2/3";
          } else if (index === 5) {
            rowLocation = `5/7`;
            colLocation = "2/3";
          } else if (index === 6) {
            rowLocation = `3/5`;
            colLocation = "2/3";
          } else if (index % 2 === 1) {
            rowLocation = `${rowIndex + 2}/${rowIndex + 4}`;
            colLocation = "1/2";
          } else if (index % 2 === 0) {
            rowLocation = `${rowIndex}/${rowIndex + 2}`;
            colLocation = "3/4";
          }
        } else {
          const rowIndex = Math.floor(index / 3) * 2 + 2;
          if (index % 3 === 0) {
            rowLocation = `${rowIndex - 1}/${rowIndex + 1}`;
            colLocation = "2/3";
          } else if (index % 3 === 1) {
            rowLocation = `${rowIndex + 0}/${rowIndex + 2}`;
            colLocation = "1/2";
          } else if (index % 3 === 2) {
            rowLocation = `${rowIndex + 0}/${rowIndex + 2}`;
            colLocation = "3/4";
          }
        }
    
        return (
          <GridBox
            key={key}
            gridColProp={colLocation}
            gridRowProp={rowLocation}
            animationDelayProp={index * 0.3}
          ></GridBox>
        );
      });
    
      return (
        <div
          className="grid"
          style={{
            gridTemplateRows: `repeat(${Math.ceil(boxCount / 3) + 1}, 30px 100px)`
          }}
        >
          {boxItems}
        </div>
      );
    }
    

    GridBox.js

    export default function GridBox({
      gridColProp,
      gridRowProp,
      animationDelayProp
    }) {
      return (
        <div
          className="gridBox"
          style={{
            gridColumn: gridColProp,
            gridRow: gridRowProp,
            animationDelay: `${animationDelayProp}s`
          }}
        >
          <div></div>
        </div>
      );
    }
    

    styles.css

    .grid {
      display: grid;
      grid-template-columns: repeat(3, 130px);
      grid-template-rows: repeat(3, 30px 100px);
      grid-column-gap: 0px;
      grid-row-gap: 0px;
    }
    .gridBox {
      border: 1px solid black;
      box-shadow: 3px 3px gray;
      margin: 10px;
      animation: animateGrid 0.3s linear forwards;
      transform: translateY(10px);
      opacity: 0;
    }
    @keyframes animateGrid {
      from {
        opacity: 0;
        transform: translateY(10px);
      }
      to {
        opacity: 1;
        transform: translateY(0px);
      }
    }