Advanced Usage of Styled Components for your React App - Part 2

Olena Drugalya - Feb 22 '21 - - Dev Community

This post continues the topic about Advanced Usage of Styled Components and covers more cool styling which you can do with styled components. So, let's start!

In this post Im going to use the same hamburger menu component which I was creating in the previous post. So let's refresh the code:
// Menu.js

import {MenuButton, Line, MenuNavigation, NavList, NavItem, NavLink} from "./Menu.styles";
import { useState } from "react";

export const Menu = () => {
  const [display, setDisplay] = useState(false);

  const handleClick = () => {
    setDisplay(!display);
  };
  return (
    <>
      <MenuButton onClick={handleClick}>
        <Line></Line>
        <Line></Line>
        <Line></Line>
      </MenuButton>
      <MenuNavigation displayIt={display}>
        <NavList>
          <NavItem>
            <NavLink href="/">About</NavLink>
          </NavItem>
          <NavItem>
            <NavLink primary href="/">
              Home
            </NavLink>
          </NavItem>
        </NavList>
      </MenuNavigation>
    </>
  );
};

Enter fullscreen mode Exit fullscreen mode

//Menu.styles.js

import styled from "styled-components";

export const MenuButton = styled.div`
  cursor: pointer;
  width: 3rem;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
`;

export const Line = styled.div`
  width: 80%;
  height: 3px;
  background-color: black;
  margin: 0.2rem;
`;

export const MenuNavigation = styled.div`
  position: fixed;
  width: 200px;
  max-width: 70%;
  height: 100%;
  left: 0;
  margin-top: 1.4rem;
  z-index: 200;
  background-color: white;
  padding: 1rem 2rem;
  transition: all 0.7s ease;
  box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
  display: ${(props) => (props.displayIt ? "block" : "none")};
`;

export const NavList = styled.ul`
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  align-items: center;
`;

export const NavItem = styled.li`
  margin: 5px 0;
  box-sizing: border-box;
  width: 100%;
  display: block;
`;

export const NavLink = styled.a`
  color: #8f5c2c;
  text-decoration: none;
  width: 100%;
  box-sizing: border-box;
  display: block;
  padding: 0.5rem;
  ${(props) =>
    props.primary &&
    `
    background: green;
    color: white;
  `}
`;

Enter fullscreen mode Exit fullscreen mode

And this is the output - a nice-looking hamburger menu and when we toggle it, we can see the expanded menu sliding out from left side of the page like this:
hamburger_menu

Hover Effect

Lets add a hover effect to our menu links, so when we hover over them, the background colour will be different. As you know, we add hover effect by using :hover pseudo-class in CSS. You can use pseudo-classes in styled components right the same way:

:hover {
    background-color: #f0e5d8;
  }
Enter fullscreen mode Exit fullscreen mode

Now our style for links look like this:

export const NavLink = styled.a`
  color: #8f5c2c;
  text-decoration: none;
  width: 100%;
  box-sizing: border-box;
  display: block;
  padding: 0.5rem;
  ${(props) =>
    props.primary &&
    `
    background: green;
    color: white;
  `};
  :hover {
    background-color: #f0e5d8;
  }
`;
Enter fullscreen mode Exit fullscreen mode

And this is the result:
hover

You can use any pseudo-classes like :active, :focus or :visited and many others with styled components (list of the most used pseudo-classes you can find here)

Media Queries

We probably want our Hamburger menu to be visible only on mobile devices. So we can add a media query to the MenuButton styles like this:

@media screen and (min-width: 500px) {
    display: none;
  }
Enter fullscreen mode Exit fullscreen mode

So, as you can see, media queries are working as well in a usual way with styled components.

Using Classes

What if we want to style a particular element by using className attribute? We can do that! But here comes a tricky part :)

Let's consider we want to style our menu links using className attribute. We have added blu and red classes to them:

 <NavList>
   <NavItem>
     <NavLink className="blue" href="/"> About </NavLink>
   </NavItem>
   <NavItem>
     <NavLink primary href="/"> Home </NavLink>
   </NavItem>
   <NavItem>
     <NavLink className="red" href="/"> Contact </NavLink>
   </NavItem>
 </NavList>
Enter fullscreen mode Exit fullscreen mode

We can access those classes from styled components in 2 ways:

  1. Using . selector with a class name This approach can be used only on the parent element to target its child element. It refers to the child element of the component. So, to target one of our links - NavLink - we need to use class selector in its parent - NavItem:
export const NavItem = styled.li`
  margin: 5px 0;
  box-sizing: border-box;
  width: 100%;
  display: block;

 .blue {color: blue;} <- this is our NavLink with class Blue
`;
Enter fullscreen mode Exit fullscreen mode

Now one of our links has blue colour:
classes_red

2.Using & selector together with . and class name
This approach lets us target the className of the main component itself, so we can target Red class from NavLink:

export const NavLink = styled.a`
  color: #8f5c2c;
  text-decoration: none;
  width: 100%;
  box-sizing: border-box;
  display: block;
  padding: 0.5rem;
  ${(props) =>
    props.primary &&
    `
    background: green;
    color: white;
  `};
  :hover {
    background-color: #f0e5d8;
  }
  &.red { <- this is out NavLink with class Red
    background: red; 
  }
`;
Enter fullscreen mode Exit fullscreen mode

And now our link has red background color:
classes_red

Ampersand & is pretty important selector in styled components. It can be used to increase the specificity of rules on the component; this can be useful if you are dealing with a mixed styled-components and vanilla CSS environment where there might be conflicting styles.

If you look now at hover effect of NavLink with class red, you can see that it's gone. That is because & has higher specificity over tags styles. To get the effect back, we need to add it inside the & block of code:

&.red {
    background: red;
    :hover {
      background-color: #f0e5d8;
    }
  }
Enter fullscreen mode Exit fullscreen mode

Now we have hover effect back:
red_hover

Phew that was a lot we have explored today! I hope you learned something new together with me :) But its not all what we can do with styled-components.
To be continued...

P.S. You can find the link to the project HERE if you need it.

Thank you for reading my blog. Feel free to connect on LinkedIn or Twitter :)

Buy Me a Coffee at ko-fi.com

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .