Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwriting nested styles in React Bootstrap using Styled-Components

I'm using styled-components with React Bootstrap. We want a tab (Tab 3 in this example) to be colored based on a status. It works well when the tab is not active, but when it's active, the Bootstrap style overwrites the style.

I've identified the style that's overwriting my color in the console. When I use console to turn off the style, I see my intended tab color.

I'm just not sure how to target this style using style-components. I've tried experimenting with different ideas from the official doc but haven't been able to get it working.

My styled component:

 export const TabNavItem = styled(NavItem)`
      background-color: ${props => (props.colorize ? 'orange' : 'white')};
      }
    `;

Usage:

  render() {
    const { children, active, colorize } = this.props;
    return (
      <TabNavItem onClick={this.handleChangeLocation} active={active} colorize={colorize}>
        {children}
      </TabNavItem>
    );
  }

Color works fine when tab is not active:

Color works fine when tab is not active

When tab is active, color is covered by Bootstrap styles:

When tab is active, color is covered by Bootstrap styles

This is the style I need to overwrite (background-color):

This is the style I need to overwrite (background-color)

like image 753
sutee Avatar asked Nov 15 '17 22:11

sutee


People also ask

How do you overwrite styled-components?

You can override an existing styled-components component by passing it to the styled() constructor/wrapper. For example, suppose you have the following styled button element: const Button = styled.

How do you override a style in React?

To override a style, you have two options. Either you can pass a style object, or you can pass a function that will obtain props regarding the current internal state of the component, thus enabling you to modify styles dynamically depending on the component state, such as isError or isSelected .

Does styled-components work with React bootstrap?

Bootstrap Styled is a front-end ecosystem for React made with Bootstrap 4 philosophy, using the power of css-in-js thanks to styled-components. It offer a community an ecosystem of tools, components and variables to create standardized, sharable and highly customizable front-end modules.

How can you apply dynamic styles to styled-components?

One way to dynamically change css properties with styled components is to insert a custom prop into your React component and access said property using the dollar sign and curly braces commonly used for template literals. Our current example is testing to see if our use pointer prop is true.


2 Answers

I typically wouldn't apply styled-components directly to each react-bootstrap components, but instead create a single one to wrap the entire component scope and rely more on CSS classes to get things done.

For example in your case, I would do something like:

const StyledWrap = styled.div`
  & .nav-tabs > .active > li {
    background: white;
  }

  & .nav-tabs > .active.colorize > li {
    background: orange;
  }
`
const MyCustomNavbar = (props) => {
  return (
    <StyledWrap>
      /* ... */
        <NavItem active={true} />
        <NavItem className="colorize"/>
        <NavItem active={true} className="colorize" />
      /* ... */
    </StyledWrap>
  )
}

In my opinion, its a cleaner pattern that keeps your component specific CSS properly scoped, concentrated and comprehensive.

Generally, I find that applying styled-components only once per component scope keeps things simple and manageable. When you apply it in multiple places you end up doing a lot of prefixing and end up with code that looks like this:

<StyledNavbar>
  <StyledNav>
    <StyledNavItem active={true} />
    <StyledNavDropdown>
      <StyledMenuItem eventKey={1.1}>Action 1</StyledMenuItem>
      <StyledMenuItem eventKey={1.2}>Action 2</StyledMenuItem>
    </StyledNavDropdown>
  </StyledNav>
</StyledNavbar>

This is an extreme example, but you get the idea.

like image 143
strider Avatar answered Sep 18 '22 12:09

strider


I have a couple of suggestions for how you might be able to fix this particular issue. You might not like either of them, as they aren't very elegant, but here goes.

Approach 1

Override the style using a more specific selector. You know how styled components can leverage Sass to their advantage? Well, you can use that to create a selector for your tabs that will be at least as specific as the one in Bootstrap. Assuming the component you are styling is the li in this equation, you could do something like this (hacky, I know).

body .nav-tabs > & {
    &.active > a {
        background-color: blue; // whatever
    }
}    

The initial & refers of course to the li in question, so would give you a selector like body .nav-tabs > li.active > a

Approach 2

A little bit simpler would be the idea of using the !important flag at the end of the CSS rule, like so:

export const TabNavItem = styled(NavItem)`
  background-color: ${props => (props.colorize ? 'orange' : 'white')} !important;
`;
like image 36
Michael Evans Avatar answered Sep 20 '22 12:09

Michael Evans