November 02, 2020 | 2 minutes read

Performant JSS

#jss#css#frontend#react

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:

1const styles = createStyles({
2 table: {
3 padding: "1rem",
4 },
5 tableHead: {
6 fontWeight: "bold",
7 },
8 tableHeadCell: {
9 fontSize: "0.75rem",
10 },
11 tableRow: {
12 padding: "0.5rem",
13 },
14 tableRowCell: {
15 fontSize: "0.5rem",
16 },
17});
18
19let useStyles = makeStyles(styles);
20
21function TableComponent(props) {
22 let { items, columns } = props;
23 let classes = useStyles();
24 return (
25 <table className={classes.table}>
26 <thead className={classes.tableHead}>
27 {columns.map((column) => (
28 <th className={classes.tableHeadCell}>{column}</th>
29 ))}
30 </thead>
31 <tbody>
32 {items.map((row) => (
33 <tr className={classes.tableRow}>
34 {row.map((cell) => (
35 <td className={classes.tableRowCell}>{cell}</td>
36 ))}
37 </tr>
38 ))}
39 </tbody>
40 </table>
41 );
42}

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:

1const styles = createStyles({
2 table: {
3 padding: "1rem",
4 "& thead": {
5 fontWeight: "bold",
6 "& th": {
7 fontSize: "0.75rem",
8 },
9 },
10 "& tbody": {
11 "& tr": {
12 padding: "0.5rem",
13 "& td": {
14 fontSize: "0.5rem",
15 },
16 },
17 },
18 },
19});
20
21let useStyles = makeStyles(styles);
22
23function TableComponent(props) {
24 let { items, columns } = props;
25 let classes = useStyles();
26 return (
27 <table className={classes.table}>
28 <thead>
29 {columns.map((column) => (
30 <th>{column}</th>
31 ))}
32 </thead>
33 <tbody>
34 {items.map((row) => (
35 <tr>
36 {row.map((cell) => (
37 <td>{cell}</td>
38 ))}
39 </tr>
40 ))}
41 </tbody>
42 </table>
43 );
44}

Selectors are your friend.