Search code examples
reactjssasscss-grid

Looking for a better way to write this css grid (scss)


I have the following grid: https://codesandbox.io/s/react-and-scss-forked-bwy6v?file=/src/index.js and Im looking for a better/shorter way to write this grid. My first time using a grid.
This is actually a small part of a responsive website that i'm building.
enter image description here

.addTransaction {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 50px;

  & div {
    border: solid 1px red;
  }

  & .buySell {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 2;

    display: grid;
    grid-template-columns: 0.5fr 0.5fr;
    column-gap: 5px;

    & .sell {
      width: 100%;
    }

    & .buy {
      width: 100%;
    }

  }

  & .token {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 2;
    grid-row-end: 3;
  }


  & .quantity {
    grid-column-start: 1;
    grid-column-end: 1;
    grid-row-start: 3;
    grid-row-end: 4;
  }

  & .price {
    grid-column-start: 2;
    grid-column-end: 2;
    grid-row-start: 3;
    grid-row-end: 4;
  }

  & .date {
    grid-column-start: 1;
    grid-column-end: 1;
    grid-row-start: 4;
    grid-row-end: 5;
  }

  & .exchange {
    grid-column-start: 2;
    grid-column-end: 2;
    grid-row-start: 4;
    grid-row-end: 5;
  }

  & .totalSpent {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 5;
    grid-row-end: 6;
  }

  & .addToCalc {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 6;
    grid-row-end: 7;
  }

  & .submit {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 7;
    grid-row-end: 8;
  }
}

import styles from "./styles.module.scss";

const App = () => (
  <div className={styles.addTransaction}>
    <div className={styles.buySell}>
      <div>
        <button className={styles.buy}>BUY</button>
      </div>
      <div>
        <button className={styles.sell}>SELL</button>
      </div>
    </div>
    <div className={styles.token}>token</div>
    <div className={styles.quantity}>quantity</div>
    <div className={styles.price}>price</div>
    <div className={styles.date}>date</div>
    <div className={styles.exchange}>exchange</div>
    <div className={styles.totalSpent}>totalSpent</div>
    <div className={styles.addToCalc}>addToCalc</div>
    <div className={styles.submit}>submit</div>
  </div>
);

Please suggest a better way
Thanks


Solution

  • Some ways to make it shorter:

    • CSS grids auto-flow, so you don't need to specify every row and column unless you're reordering cells
    • For the cells that span two columns, you can use the shorthand syntax:
      grid-column: auto / span 2;
      
    • If you have a lot of cells with the same property (e.g. spanning two columns), you can add a common class name for them. If that isn't an option, you can also chain multiple selectors with a comma to add common properties:
      .firstClass, .secondClass { example-property: 4px; }
      

    The result is a lot shorter

    .addTransaction {
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-auto-rows: 50px;
    
      & div {
        border: solid 1px red;
      }
    
      & .buySell {
        display: grid;
        grid-template-columns: 0.5fr 0.5fr;
        column-gap: 5px;
    
        & .buy,
        & .sell {
          width: 100%;
        }
      }
    
      & .buySell,
      & .token,
      & .totalSpent,
      & .addToCalc,
      & .submit {
        grid-column: auto / span 2;
      }
    }
    

    https://codesandbox.io/s/react-and-scss-forked-t8hcw?file=/src/styles.module.scss

    Some other options:

    • consider .grid-template-areas for really complex layouts. It can be a readability lifesaver over manually specifying grid-column or grid-row multiple times.
    • Should only the first row have a gap? You can add that gap everywhere and then you wouldn't need the nested grid. If your content is nested, you can use display: contents to flatten the hierarchy in CSS
      & .addTransaction {
        /* ... */
        column-gap: 5px;
      
        /* ... */
        & .buySell { 
          display: contents;
      
          & button {
            width: 100%;
          }
        }
      }