Brandon Durham
Brandon Durham

Reputation: 7727

How can I pass CSS classes to React children and ensure they will override the child’s local class?

I have a <Parent /> component with a single <Child />:

<Parent>
    <Child />
</Parent>

I want to pass a CSS class from the parent into the <Child />, so I do this:

<Parent>
    <Child className={ styles.pill } />
</Parent>

The <Child /> has a className prop and applies the class using the classnames package, like this:

<div className={ classNames(styles.pill, props.className) } />

But you see the <Child /> has a class called styles.pill with these styles:

.pill {
    align-content: stretch;
    align-items: center;
    color: var(--grey__text--dark);
    cursor: pointer;
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
}

The class the parent passed in contains these styles:

.pill {
    align-items: flex-end;
    flex-flow: column wrap;
}

With this setup I can’t guarantee that the styles passed in from the parent will override the styles within the <Child /> component, which is exactly what I want them to do. Currently you never know which will trump the other. It’s seemingly random with every build of the project.

How can I ensure that the CSS properties in class passed in from the parent override any similar properties in the Child component?

Upvotes: 6

Views: 4093

Answers (2)

felixmosh
felixmosh

Reputation: 35533

It is a matter of CSS specificity, there are many ways to insure the override.

  1. Multiple selector trick, in order to enlarge the specificity you can double the selector size by duplicating the class name, in you case, .pill.pill { ...} will be more specific than the original, and therefore will override the style.

  2. Usage of !important, you can specify that in the class of the parent, .pill's declaration will contain !important at the end.

  3. Multiple different selectors, the parent will pass additional different className, that child component will address, .pill.parent-pill {...}, the parent will pass the .parent-pill class to the child.

Those are just 3 easy ways to override the child styles there are more.

Upvotes: 6

shabs
shabs

Reputation: 718

You can use Object.assign to merge one/many objects into a target object, giving precedence to each subsequent object:

const foo = { a: '1', b: '2' }
const bar = { a: '3' }
console.log(Object.assign(foo, bar));

Upvotes: 1

Related Questions