DEV Community

loading...

Performant JSS

cvr profile image Cristian Velasquez Ramos Originally published at cvr.im ・2 min read

At work, I mainly use Material-UI. It's a really useful library that offers great defaults, great theming, and a decent, though rather complicated, styling system.

I've come to see that the most performant way to style with JSS is to do it less. Huh?

Selectors are your friend

I've realized I started to think in "components" whenever I use JSS. It's probably because it's really a react-only thing.

However, when I start to think in CSS, it suddenly makes JSS much simpler.

Intuitively we use JSS in a manner similar to this:

const styles = createStyles({
  table: {
    padding: "1rem",
  },
  tableHead: {
    fontWeight: "bold",
  },
  tableHeadCell: {
    fontSize: "0.75rem",
  },
  tableRow: {
    padding: "0.5rem",
  },
  tableRowCell: {
    fontSize: "0.5rem",
  },
});

let useStyles = makeStyles(styles);

function TableComponent(props) {
  let { items, columns } = props;
  let classes = useStyles();
  return (
    <table className={classes.table}>
      <thead className={classes.tableHead}>
        {columns.map((column) => (
          <th className={classes.tableHeadCell}>{column}</th>
        ))}
      </thead>
      <tbody>
        {items.map((row) => (
          <tr className={classes.tableRow}>
            {row.map((cell) => (
              <td className={classes.tableRowCell}>{cell}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}
Enter fullscreen mode Exit fullscreen mode

I'm using good ol' fashion JSS here, but you can imagine the same principle with styled-components/emotion

Seems familiar right? Each style is it's own "component".

However, you can make this more performant by applying the styling once rather than to every item within the table by using one simple trick - selectors:

const styles = createStyles({
  table: {
    padding: "1rem",
    "& thead": {
      fontWeight: "bold",
      "& th": {
        fontSize: "0.75rem",
      },
    },
    "& tbody": {
      "& tr": {
        padding: "0.5rem",
        "& td": {
          fontSize: "0.5rem",
        },
      },
    },
  },
});

let useStyles = makeStyles(styles);

function TableComponent(props) {
  let { items, columns } = props;
  let classes = useStyles();
  return (
    <table className={classes.table}>
      <thead>
        {columns.map((column) => (
          <th>{column}</th>
        ))}
      </thead>
      <tbody>
        {items.map((row) => (
          <tr>
            {row.map((cell) => (
              <td>{cell}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}
Enter fullscreen mode Exit fullscreen mode

Selectors are your friend.

Discussion

pic
Editor guide