Inline CSS styles in React: how to implement a:hover?

前端 未结 18 834
星月不相逢
星月不相逢 2020-11-28 21:51

I quite like the inline CSS pattern in React and decided to use it.

However, you can\'t use the :hover and similar selectors. So what\'s the best way to

相关标签:
18条回答
  • 2020-11-28 22:22

    You can use Radium - it is an open source tool for inline styles with ReactJS. It adds exactly the selectors you need. Very popular, check it out - Radium on npm

    0 讨论(0)
  • 2020-11-28 22:22

    onMouseOver and onMouseLeave with setState at first seemed like a bit of overhead to me - but as this is how react works, it seems the easiest and cleanest solution to me.

    rendering a theming css serverside for example, is also a good solution and keeps the react components more clean.

    if you dont have to append dynamic styles to elements ( for example for a theming ) you should not use inline styles at all but use css classes instead.

    this is a traditional html/css rule to keep html / JSX clean and simple.

    0 讨论(0)
  • 2020-11-28 22:25

    I'm in the same situation. Really like the pattern of keeping the styling in the components but the hover states seems like the last hurdle.

    What I did was writing a mixin that you can add to your component that needs hover states. This mixin will add a new hovered property to the state of your component. It will be set to true if the user hovers over the main DOM node of the component and sets it back to false if the users leaves the element.

    Now in your component render function you can do something like:

    <button style={m(
         this.styles.container,
         this.state.hovered && this.styles.hover,
    )}>{this.props.children}</button>
    

    Now each time the state of the hovered state changes the component will rerender.

    I've also create a sandbox repo for this that I use to test some of these patterns myself. Check it out if you want to see an example of my implementation.

    https://github.com/Sitebase/cssinjs/tree/feature-interaction-mixin

    0 讨论(0)
  • 2020-11-28 22:25

    Adding on to Jonathan's answer, here are the events to cover the focus and active states, and a using onMouseOver instead of onMouseEnter since the latter will not bubble if you have any child elements within the target the event is being applied to.

    var Link = React.createClass({
    
      getInitialState: function(){
        return {hover: false, active: false, focus: false}
      },
    
      toggleHover: function(){
        this.setState({hover: !this.state.hover})
      },
    
      toggleActive: function(){
        this.setState({active: !this.state.active})
      },
    
      toggleFocus: function(){
        this.setState({focus: !this.state.focus})
      },
    
      render: function() {
        var linkStyle;
        if (this.state.hover) {
          linkStyle = {backgroundColor: 'red'}
        } else if (this.state.active) {
          linkStyle = {backgroundColor: 'blue'}
        } else if (this.state.focus) {
          linkStyle = {backgroundColor: 'purple'}
        } 
    
        return(
          <div>
            <a style={linkStyle} 
              onMouseOver={this.toggleHover} 
              onMouseOut={this.toggleHover} 
              onMouseUp={this.toggleActive} 
              onMouseDown={this.toggleActive} 
              onFocus={this.toggleFocus}> 
              Link 
            </a>
          </div>
        )
      }
    
    0 讨论(0)
  • 2020-11-28 22:27

    You can use css modules as an alternative, and additionally react-css-modules for class name mapping.

    That way you can import your styles as follows and use normal css scoped locally to your components:

    import React from 'react';
    import CSSModules from 'react-css-modules';
    import styles from './table.css';
    
    class Table extends React.Component {
        render () {
            return <div styleName='table'>
                <div styleName='row'>
                    <div styleName='cell'>A0</div>
                    <div styleName='cell'>B0</div>
                </div>
            </div>;
        }
    }
    
    export default CSSModules(Table, styles);
    

    Here is a webpack css modules example

    0 讨论(0)
  • 2020-11-28 22:30
    <Hoverable hoverStyle={styles.linkHover}>
      <a href="https://example.com" style={styles.link}>
        Go
      </a>
    </Hoverable>
    

    Where Hoverable is defined as:

    function Hoverable(props) {
      const [hover, setHover] = useState(false);
    
      const child = Children.only(props.children);
    
      const onHoverChange = useCallback(
        e => {
          const name = e.type === "mouseenter" ? "onMouseEnter" : "onMouseLeave";
          setHover(!hover);
          if (child.props[name]) {
            child.props[name](e);
          }
        },
        [setHover, hover, child]
      );
    
      return React.cloneElement(child, {
        onMouseEnter: onHoverChange,
        onMouseLeave: onHoverChange,
        style: Object.assign({}, child.props.style, hover ? props.hoverStyle : {})
      });
    }
    
    0 讨论(0)
提交回复
热议问题