简体   繁体   中英

:focus is not working with :hover with styled-component for React.js

I want to create a blueprint component (Input) and I wanted it to be easily customized, so I decided to use styled-component package. The problem here is that the :focus attribute is not working when :hover attribute. I tried many solutions to similar questions but with no result. Maybe I am missing something?

By the way, I am still a newbie with react.js.

UPDATE: It seems like the hover effect is taking place after the focus effect, I added width (expansion) onfocus: the box expanded without any animation ( I guess due to the fact that hover animation interrupted it ) and border color switched to hover color...

UPDATE 2: I switched the order in which:focus and:hover are written in the component, :hover first and then:focus second: and now focus works and hover don't: and so ORDER IS IMPORTANT .

The Specific Component (Created with styled-component)

  const Comp = styled.input.attrs((props) => ({
    type: "text",
    size: props.small ? 5 : undefined,
  }))`
    border-radius: ${borderRadius};
    border: ${borderWidth} ${borderStyle} ${borderColor};
    padding: ${padding};
    margin: ${margin};
    width: ${width}
    color: ${color};
    outline: none;
    font-size: ${fontSize};
    font-style: ${fontStyle};
    font-weight: ${fontWeight};
    background-color: ${bgColor};
    :placeholder {
      color: ${placeholderColor};
    }
    &:focus {
      border-color: ${focusColor};
      color: ${focusColor};
      width : ${focusExpansion};
      animation: onFocus 0.7s;
    }
    &:not(:focus) {
      border-color: ${borderColor};
      color: ${color};
      width: ${width};
      animation: offFocus 0.7s;
    }
    @keyframes onFocus {
      from {
        border-color: ${borderColor};
        color: ${color};
        width: ${width};
      }
      to {
        border-color: ${focusColor};
        color: ${focusColor};
        width: ${focusExpansion};
      }
    }
    @keyframes offFocus {
      from {
        border-color: ${focusColor};
        color: ${focusColor};
        width: ${focusExpansion};
      }
      to {
        border-color: ${borderColor};
        color: ${color};
        width: ${width};
      }
    }
    &:hover {
      border-color: ${hoverColor};
      color: ${hoverColor};
      animation: onHover 0.7s;
    }
    &:not(:hover) {
      border-color: ${borderColor};
      color: ${color};
      animation: offHover 0.7s;
    }

    @keyframes onHover {
      from {
        border-color: ${borderColor};
        color: ${color};
      }
      to {
        border-color: ${hoverColor};
        color: ${hoverColor};
      }
    }

    @keyframes offHover {
      from {
        border-color: ${hoverColor};
        color: ${hoverColor};
      }
      to {
        border-color: ${borderColor};
        color: ${color};
      }
    }
  `;
 

The Complete File

import styled from "styled-components";

const InputBox = (props) => {
  const defaultFontSize = "15px";

  const padding = props.padding != null ? props.padding : "3px 10px 3px 10px";
  const margin = props.margin != null ? props.margin : "0px";
  const width = props.width != null ? props.width : "100px";
  const color = props.color != null ? props.color : "black";
  const borderStyle = props.borderStyle != null ? props.borderStyle : "solid";
  const borderWidth = props.borderWidth != null ? props.borderWidth : "3px";
  const borderColor = props.borderColor != null ? props.borderColor : color;
  const borderRadius = props.borderRadius != null ? props.borderRadius : "0px";
  const fontSize = props.fontSize != null ? props.fontSize : defaultFontSize;
  const fontStyle = props.fontStyle != null ? props.fontStyle : "normal";
  const fontWeight = props.fontWeight != null ? props.fontWeight : "normal";
  const placeholder =
    props.placeholder != null ? props.placeholder : "placeholder";
  const placeholderColor =
    props.placeholder != null ? props.placeholder : "grey";
  const bgColor = props.bgColor != null ? props.bgColor : "none";
  const hoverColor = props.hoverColor != null ? props.hoverColor : color;
  const focusColor = props.focusColor != null ? props.focusColor : color;
  const focusExpansion =
    props.focusExpansion != null ? props.focusExpansion : width;

  const Comp = styled.input.attrs((props) => ({
    type: "text",
    size: props.small ? 5 : undefined,
  }))`
    border-radius: ${borderRadius};
    border: ${borderWidth} ${borderStyle} ${borderColor};
    padding: ${padding};
    margin: ${margin};
    width: ${width}
    color: ${color};
    outline: none;
    font-size: ${fontSize};
    font-style: ${fontStyle};
    font-weight: ${fontWeight};
    background-color: ${bgColor};
    :placeholder {
      color: ${placeholderColor};
    }
    &:focus {
      border-color: ${focusColor};
      color: ${focusColor};
      width : ${focusExpansion};
      animation: onFocus 0.7s;
    }
    &:not(:focus) {
      border-color: ${borderColor};
      color: ${color};
      width: ${width};
      animation: offFocus 0.7s;
    }
    @keyframes onFocus {
      from {
        border-color: ${borderColor};
        color: ${color};
        width: ${width};
      }
      to {
        border-color: ${focusColor};
        color: ${focusColor};
        width: ${focusExpansion};
      }
    }
    @keyframes offFocus {
      from {
        border-color: ${focusColor};
        color: ${focusColor};
        width: ${focusExpansion};
      }
      to {
        border-color: ${borderColor};
        color: ${color};
        width: ${width};
      }
    }
    &:hover {
      border-color: ${hoverColor};
      color: ${hoverColor};
      animation: onHover 0.7s;
    }
    &:not(:hover) {
      border-color: ${borderColor};
      color: ${color};
      animation: offHover 0.7s;
    }

    @keyframes onHover {
      from {
        border-color: ${borderColor};
        color: ${color};
      }
      to {
        border-color: ${hoverColor};
        color: ${hoverColor};
      }
    }

    @keyframes offHover {
      from {
        border-color: ${hoverColor};
        color: ${hoverColor};
      }
      to {
        border-color: ${borderColor};
        color: ${color};
      }
    }
  `;

  return <Comp placeholder={placeholder} />;
};

export default InputBox;


Usage in App

import React from "react";
import EditText from "./components/EditText";
import InputBox from "./components/InputBox";
import Colors from "./Colors";

const App = () => {
  return (
    <div>
      <InputBox
        padding={"10px"}
        margin={"20px"}
        color={Colors.BLUE}
        hoverColor={Colors.GREEN_MEADOW}
        focusColor={Colors.ORANGE}
        borderRadius={"50px"}
        borderWidth={"4px"}
        fontStyle={"italic"}
        fontWeight={"bold"}
      />
    </div>
  );
};

export default App;

Answering my own question, After hours of experimentation with styled-component: It turned out that the order of (hover) and (focus) is important with the last one overriding the effects made by the first, and that's why changing the same property, with an animation, in both selectors (hover and focus) won't produce a good result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM