Target React Child Components Within CSS Modules

Target React Child Components Within CSS Modules

CSS Modules are great for scoping styles within React components. Scoping here means each class name is randomly generated at build time. Hence, even classes with the same name during development will be differently named in the built bundles.

This random generation prevents the use of parent-child component styling. An example is the code block below. The styles.table classes from the stylesheet will only be applied to the <Table> component. So if we want to style <td> child elements, we have to attach classes to each of them.

<Table className={styles.table} borderless>
  <tbody>
    <tr>
      <td className={styles.td}>Application Date</td>
      <td className={styles.td}>11/2/2021</td>
    </tr>
    <tr>
      <td className={styles.td}>Loan Type</td>
      <td className={styles.td}>Microcredit</td>
    </tr>
    <tr>
      <td className={styles.td}>Loan Amount</td>
      <td className={styles.td}>$ 100,000</td>
    </tr>
    <tr>
      <td className={styles.td}>Loan Duration</td>
      <td className={styles.td}>4 months</td>
    </tr>
  </tbody>
</Table>

You can solve the duplication issue by

  1. Using styled-components
  2. Creating a custom tableData component. Below is an implementation of option 2.
const TableData = ({children}) => (<td className={styles.td}>{children}</td>)

<Table className={styles.table} borderless>
  <tbody>
    <tr>
      <TableData>Application Date</TableData>
      <TableData>16/2/2021</TableData>
    </tr>
    <tr>
      <TableData>Loan Type</TableData>
      <TableData>Microcredit</TableData>
    </tr>
    <tr>
      <TableData>Loan Amount</TableData>
      <TableData>N 300,000</TableData>
    </tr>
    <tr>
      <TableData>Loan Duration</TableData>
      <TableData>4 months</TableData>
    </tr>
  </tbody>
</Table>

A better way to solve the problem is to specify the child selector with the :global keyword

/* table.module.css */
.table :global(td) {
  padding: 0.5rem 0.75rem 0.5rem 0.75rem !important;
}

The parent selector (styles.table) is added to the parent element, in this case: <Table>.

      <Table className={styles.table} borderless>
        <tbody>
        ...
      </Table>

All td elements within the <Table> component will have modified padding. It won't affect td elements that are not children of <Table>.

Credits

Some ideas and concepts for this article were obtained from:

  1. dev.to/li/selecting-elements-in-children-co..
  2. engineering.liefery.com/2018/06/27/overridi..
  3. Cover photo by Juliane Liebermann on Unsplash.

Thank you for stopping by. Adios ✌🏾🧑.

Β