Robo Robok
Robo Robok

Reputation: 22663

How to style child elements in React's SCSS module?

Let's say I'm having the following component in React:

import classNames from 'classnames';
import style from './Cat.module.scss';

export default function Cat({ src, alt, bio, disclaimer, className }) {
    return (
        <div className={classNames(
            style.container,
            className,
        )}>
            <img
                src={src}
                alt={alt}
            />
            <p className={style.bio}>
                {bio}
            </p>
            <p className={style.disclaimer}>
                {disclaimer}
            </p>
        </div>
    );
};

Now, let's use this Cat component on a page component:

import style from './GarfieldPage.module.scss';

export default function GarfieldPage() {
    return (
        <>
            <h1>This is my cat!</h1>
            <Cat
                src="garfield.png"
                alt="Garfield"
                bio="The best cat ever!"
                disclaimer="Loves lasagna"
                className={style.garfield}
            />
        </>
    );
};

I'd like to apply some custom styling to, let's say, bio. There are several ways to do it, in order I personally find them friendly:

  1. Using data- attributes to mark elements for easier access, so in my Cat component it would become:
<p className={style.bio} data-bio>

Then in my page component's styles:

.garfield [data-bio] {
    color: purple;
}
  1. Importing class names from other SCSS module. This could be the most "correct" way to do it, but sounds like a lot of imports.

  2. Allowing class names as props for each element:

export default function Cat({
    src,
    alt,
    bio,
    disclaimer,
    className,
    bioClassName,
    disclaimerClassName,
}) {
    return (
        <div className={classNames(
            style.container,
            className,
        )}>
            <img
                src={src}
                alt={alt}
            />
            <p className={classNames(
                style.bio,
                bioClassName,
            )}>
                {bio}
            </p>
            <p className={classNames(
                style.disclaimer,
                disclaimerClassName,
            )}>
                {disclaimer}
            </p>
        </div>
    );
};

Sounds like a prop hell, especially when component is large.

  1. Using CSS match operator:
.garfield [class~=bio] {
    color: purple;
}

I don't like that one, because there could be a name clash.

  1. Assuming component tree in my SCSS:
.garfield p:last-child {
    color: purple;
}

Assuming that component wouldn't change their tree sounds like a bad idea.

Is there any recognized pattern to style children elements in a module? Did I miss a better way to do it?

Upvotes: 2

Views: 3338

Answers (1)

whygee
whygee

Reputation: 1984

You can also use :global.

You would do something like this:

.garfield :global(.bio) {
    color: purple;
}

A working demo.

I can't say it's better than the approaches you mentioned, it depends on the situation really. :global is especially useful when you want to override a component style that comes from a package when it doesn't let you to do so via props.

Upvotes: 6

Related Questions