Hierarchical selectors do not function properly with styled components

Trying to get the hang of styled components, but struggling with targeting CSS classes in hierarchy. Specifically, I want to apply styles when a user hovers over navigation links. Below is my navbar code:

import React from "react";
import { Nav, Navbar } from "react-bootstrap";
import Flag from "../common/Image";
import styled from "styled-components";
import NavLink from "../common/NavLink";

const imageURL = "/static/img/abc.png";

const Navigation = ({ className }) => {
  return (
    <Navbar className={className} collapseOnSelect expand="lg" variant="light">
      <Navbar.Brand href="#home">
        <Flag imageSource={imageURL} size={[80, 70]} />
      </Navbar.Brand>
      <NavLink linkName="A" URL={"#"} />
      <Navbar.Toggle aria-controls="responsive-navbar-nav" />
      <Navbar.Collapse id="responsive-navbar-nav">
        <Nav className="mr-auto">
          <NavLink linkName="B" URL={"#a"} />
          <NavLink linkName="C" URL={"#b"} />
          <NavLink linkName="D" URL={"#b"} />
        </Nav>
        <Nav>
          <NavLink linkName="Espace de discussion" URL={"#discussions"} />
          <NavLink linkName="Contactez-nous" URL={"#contact"} />
          <Nav.Link>
            <i clasName="fas fa-envelope" />
          </Nav.Link>
          <Nav.Link>
            <i className="fas fa-bell" />
          </Nav.Link>
          <Nav.Link>
            <i className="fas fa-user-circle" />
          </Nav.Link>
        </Nav>
      </Navbar.Collapse>
    </Navbar>
  );
};

export default styled(Navigation)`
  background-color: white;
  border-bottom: 1px solid #e4e8f0;
`;

And here's my NavLink component:

import React from "react";
import styled from "styled-components";
import { Nav } from "react-bootstrap";
import PropTypes from "prop-types";

const NavLink = ({ linkName, URL, className }) => {
  return (
    <Nav.Link className={className} href={URL}>
      {linkName}
    </Nav.Link>
  );
};

NavLink.PropTypes = {
  linkName: PropTypes.string,
  URL: PropTypes.string
};



export default styled(NavLink)`
  cursor: pointer;
  color: green;
  transition: 0.4s linear;
  padding: 10px;
  &:hover {
    color: white;
    font-size: 90;
    background-color: #2e384d;
    border-radius: 10px;
  }

  .navbar-light .navbar-nav .nav-link &:hover {
    color: white;
  }
`;

In the GIF below, you can see that the animation for changing link styles works, but the color only changes to white for the 'A' link. Other style properties like background and border are changing, except for the link color. Here's how it behaves: https://i.sstatic.net/l8J2g.gif When I add this code:

.navbar-light .navbar-nav .nav-link &:hover {
        color: white;
      }
in a regular CSS file without using styled components, it works as expected. I tried using the SASS method within the definition of my styled component like this:

.navbar-light {
    .navbar-nav {
      .nav-link {
        &:hover {
          color: white;
        }
      }
    }
  } 

However, nothing changed. How can I make all link text become white with a styled-component definition?

Answer №1

Alright, the way <Nav> is wrapping your <NavLink> is causing the nav-link className to have higher specificity compared to your styled component className. This means that the NavLink component applies the styled component className before "nav-link", resulting in it not overriding the Bootstrap CSS. For instance, the className might appear as: "sc-lhVmIH gcJAof nav-link", where the styled component className "sc-lhVmIH gcJAof" gets overridden by the last applied className "nav-link". Various solutions are available to address this issue.


Possible Fixes

  1. To resolve this, simply include color: white !important; in the styled NavLink:
export default styled(NavLink)`
  cursor: pointer;
  color: green;
  transition: 0.4s linear;
  padding: 10px;
  border-radius: 10px;

  &:hover {
    color: white !important;
    font-size: 90;
    background-color: #2e384d;
    border-radius: 10px;
  }
`;
  1. In the Navigation section, where
    <NavBar className={className}>...</NavBar>
    accepts a styled component className, add the following css to override the Bootstrap CSS stylesheet:
export default styled(Navigation)`
  background-color: white;
  border-bottom: 1px solid #e4e8f0;

  &.navbar-light {
    & .navbar-nav {
      & .nav-link:hover {
        color: white;
      }
    }
  }
`;
  1. Alternatively, import the Bootstrap less into a .less file and override the nav-link:hover className.

CSS Specificity Details

Here's a breakdown of how CSS specificity is applied within the DOM:

https://i.sstatic.net/3d8iH.png


Demos Available

For a live demonstration, click here.

If you prefer to view working examples on codesandbox (including solution #1 and #2 - choose one):

https://codesandbox.io/s/styled-svg-component-bxk11?fontsize=14

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: No matching callable signature found within the statics of React$Component during function call

I encountered an unfamiliar error while working with flow: Flow: function call. Callable signature not found in statics of React$Component This error occurred when using the following code: export default connect( null, { showModal }, )(withRouter(F ...

Is there a different method similar to Textfield onChange that works like the HTML onChange attribute?

In my current setup, I have a Textfield component nested within other components where I pass a function pointer down to it as a prop. The challenge I'm facing is that the function responsible for passing the contents of the Textfield back up to the r ...

Can I align HTML elements to the left side within a Material UI grid?

Utilizing material UI for the styling. Can an HTML element or Typography element be positioned to the left side of a Grid and still remain on the same line? Below is a brief code snippet: return ( <Wrapper> <form> <Gri ...

Developing a Bootstrap layout that expands on larger screens but maintains a set height can pose challenges when

I am experiencing an issue with a bootstrap 4 navbar that is supposed to expand on large screens and collapse on small devices. The problem arises when I try to set the navbar height to be smaller than the default height, causing the expand feature to not ...

When you click on the button, the section will not be displayed

I'm facing an issue with my code. I have a set of five buttons and corresponding sections. When a button is clicked, the active and active-btn classes are supposed to be added to that button as well as the corresponding section element with the same i ...

Problems encountered when applying box-shadow for text background across multiple lines

Lately, I've become accustomed to using box-shadow to add backgrounds to text headings. I've been employing a little trick of applying a box-shadow to a span element within h1 tags in order to create a unique "background with padding" highlight e ...

Can PHP be used to dynamically load a different stylesheet on a webpage?

Currently in the process of developing a mobile version of my website, I have determined that implementing an alternate stylesheet would be the most effective method to ensure compatibility with mobile devices. I am considering using a PHP script for use ...

The mandatory field in the TextField component of Material UI fails to work upon submission

I have integrated the textfield component from the Material UI library into my React application for user input. However, I am facing an issue with the 'required' attribute not working as expected when submitting the form. The input data is being ...

ReactJS issue: Unexpected warning about having a unique "key" prop for each child in a list

What a glorious day! Unfortunately, my view is obstructed by this pesky obstacle: https://i.sstatic.net/ODemS.png I've exhausted all my options (except asking for help ._.) and scoured every corner. Alas, the desired outcome remains elusive :'( ...

Adjust the appearance of a glyphicon by modifying its color according to various criteria

Using angularjs, I implemented ng-repeat to display details in a table. In the final column, I aim to display the glyphicon 'glyphicon glyphicon-stop' in a specific color. <tr ng-repeat="ps in $ctrl.personLst"> <td>{{ ps.id}}</td& ...

The hyperlink cannot be activated

I am encountering an issue with a web page that has a simple layout. The footer of the page contains a link, but it is unclickable. I attempted to set z-index: 1000000 for the footer element, however, this did not resolve the problem. I am unsure of what m ...

Creating tabbed interfaces with JQuery

How do I build tabs using jQuery without displaying the content of all tabs until clicked? I have tried using this code, and it works well once a tab is clicked. However, when the page is refreshed, the content of both tabs is visible. jQuery (funct ...

The issue I am facing in ReactJS is that the Child Component does not update when I update the

I am looking to update my child component with a new promo when a button is clicked. Below is the code snippet for updating the child component: const callCoupon = async (promo) => { /// result = some api call; setpro(result); } const discou ...

Pass on styling properties to children components in React and implement them within a CSS stylesheet

Currently, I am utilizing the Dropdown component to mimic an HTML dropdown functionality. However, this component is actually comprised of divs, ordered lists, and unordered lists. My challenge lies in applying styles to specific elements with className at ...

The Next JS Zego cloud does not recognize the term "document" as defined

While integrating Zego Cloud into my Next.js application, I encountered an error indicating that the document is not defined. In order to access React hooks and the DOM of the browser in my Next.js application, I am utilizing the "use client" method. Howe ...

The scroll() function in jQuery does not bubble up

Recently, I encountered an issue with a Wordpress plugin that displays popups on scroll. The code I currently have is as follows: jQuery(window).scroll(function(){ //display popup }); The problem arises with a particular website that has specific CSS ...

Unable to change background-image as intended

Here is an example of my HTML code with an initial background image: <div id="ffff" style="width: 200px; height: 200px; background-image: url('/uploads/backroundDefault.jpg')">sddsadsdsa<br>dffdsdfs</div> Everything seems to b ...

Populating a data grid with several objects within a JSON object

I am currently developing a project utilizing React with typescript and materialUi. My task is to retrieve data from a JSON fetch request and display it in a DataGrid. The structure of the JSON data is as follows: { id: "1234567890", number: ...

The Bootstrap 4 navbar appears slim on medium and smaller sized screens

Currently, I am using Bootstrap 4 in combination with Rails 5 to create a collapsing navbar. The functionality of the collapse is working properly, but the size of the collapsed navbar seems to be unusually small. You can see the issue in this screenshot: ...

What could be causing my HTML form elements to shift position when I click on them in Internet Explorer 8?

I'm facing an issue with my HTML form that has multiple input fields (text and select types) arranged in pairs on each row. Surprisingly, everything works fine in all browsers, including IE7. However, when it comes to IE8, I encounter a peculiar probl ...