Styling makes NavLink 'unclickable' in react

2.5k Views Asked by At

I'm trying to style a react-router-dom NavLink navbar. I've gone about it a few different ways, but in every instance whatever way I will choose will make the NavLink 'unclickable' - it will be a nicely styled box that will not navigate on a click. Here are a couple ways I've gone about it:

One way I've tried is making glamorous css boxes with clicked tests. This is the preferred method that I want to work, because it will allow me to style hover and other pseudo-elements. I tried the following with no success. These two glam elements are just styled divs. I was worried that because the navlink was burried in a div it was 'underneath' the element, so I tried both setting the zIndex=999 for the Navlink and zIndex=1 for the glam elements (as well as setting relative and absolute positioning), and I also tried setting pointerEvents='none' for the glam elements so you could 'click through' to the navigation link.

styling:

const NavGlam = glamorous.div(
  {
    display: 'flex',
    flexDirection: 'row',
    position: 'relative',
    width:'100%',
    pointerEvents: 'none',
    listStyle: 'none',
    zIndex: '1',
    fontWeight: 'bolder',
    backgroundColor: 'purple',
  }
);

const NavGlamLi = glamorous.div(
  {
    display: 'flex',
    flex:'1',
    position:'relative',
    fontWeight: 'bolder',
    zIndex: '1',
    alignItems: 'center',
    verticalAlign: 'center',
    pointerEvents: 'none',
    textAlign: 'center',
    padding: '10px',
    margin: '10px'
  },
  ({clicked})=>({
    backgroundColor:clicked==='true'?`tomato`:`black`,
    color:clicked==='true'?`white`:`orange`
  })
);

Link in render:

<NavGlam>
  <NavGlamLi clicked={this.props.clicked==='home'?`true`:`false`}>
     <NavLink to="/home" exact activeClassName="active">Home</NavLink>
  </NavGlam>
</NavGlam>

Another way that I tried to do it (as a bit of a hack), was to create a function in the class and send through the click events in that way. Here the styling would only be on navlink, so there should not have been any click through problems, but again, clicking doesn't work!

function:

  navfunk(clicked){
    if (clicked==='true'){
      return(
        {
          display: 'flex',
          flex:'1',
          fontWeight: 'bolder',
          alignItems: 'center',
          verticalAlign: 'center',
          pointerEvents: 'none',
          textAlign: 'center',
          padding: '10px',
          margin: '10px',
          backgroundColor: 'tomato',
          color: 'white',
          textDecoration: 'none'
        }
      )
    }else{
      return(
        {
          display: 'flex',
          flex:'1',
          fontWeight: 'bolder',
          alignItems: 'center',
          verticalAlign: 'center',
          pointerEvents: 'none',
          textAlign: 'center',
          padding: '10px',
          margin: '10px',
          backgroundColor: 'black',
          color: 'orange',
          textDecoration: 'none'
        }
      )
    }
  }

And the link:

</NavGlam>
  <NavLink style={this.navfunk(this.props.clicked==='about'?`true`:`false`)}   to="/about" activeClassName="active">About</NavLink>
</NavGlam>

What DOES work is when I just put the NavLinks inside a styled-component like this:

import styled from 'styled-components'

const Nav = styled.nav`
  display: flex;
  list-style: none;
  > :not(:first-child) {
    margin-left: 1rem;
  }
  a {
    font-weight: 300;
    color: ${palette('grayscale', 5)};
    font-size: 1.25rem;
    &.active {
      color: ${palette('grayscale', 5)};
    }
  }
`

  <Nav>
    <NavLink  to="/home" exact activeClassName="active">Home</NavLink>
  <Nav>

But, styled-components do not have good support for pseudo-elements (CLARIFICATION: the &.active method doesn't work in the above), so I don't want to use this. Is there anyone who can tell me why my glamorous css examples do not work?

2

There are 2 best solutions below

0
On

You are apply pointer-events: none to your <NavGlamLi /> element. Your <NavLink /> is a child of your <NavGlamLi />. Anything that is a child of an element with 'pointer-events: none` will also not receive pointer events.

You also do not need to include the activeClassName="active" because that is the default setting of a <NavLink />

Check this out to read about pointer-event values.

1
On

I had the exact problem with standard Link

Your problem is this line

const NavGlam = glamorous.div(

You don't want to create DIV. Glamorous has several methods, some of them are specific for exact elements e.g.

glamorous.h1 , glamorous.p , glamorous.input, glamorous.select ....

What you want to do is this:

Glamorous style file

import g from 'glamorous';
import { Link } from 'react-router-dom'; // or NavLink

export const StyledLink = g(Link)({
  textDecoration: 'none',
  .... other styles .....
});

And then import in your Component

import { StyledLink } from './style'; // your Glamorous style file

And use as a regular Link, Glamorous with it's import takes care about transforming it to regular Link, giving it style and doing its magic

<StyledLink to="/contact">Contact page</StyledLink> // standard usage

Hope this helps. Good luck :)