React中的内联CSS样式:如何实现:hover?

时间:2015-02-06 11:54:39

标签: reactjs

我非常喜欢inline CSS pattern in React并决定使用它。

但是,您无法使用:hover和类似的选择器。那么在使用内联CSS样式时实现高亮显示的最佳方法是什么?

#reactjs的一个建议是拥有一个Clickable组件,并按照以下方式使用它:

<Clickable>
    <Link />
</Clickable>

Clickable具有hovered状态,并将其作为道具传递给链接。但是,Clickable(我实现它的方式)将Link包装在div中,以便它可以设置onMouseEnteronMouseLeave。这会使事情变得有点复杂(例如span包裹在div中的行为与span不同。

有更简单的方法吗?

22 个答案:

答案 0 :(得分:86)

我认为onMouseEnter和onMouseLeave是可行的方法,但我认为不需要额外的包装器组件。以下是我实施它的方法:

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={linkStyle} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }

然后,您可以使用悬停状态(true / false)来更改链接的样式。

答案 1 :(得分:32)

我处于同样的境地。真的喜欢在组件中保持样式的模式,但悬停状态似乎是最后的障碍。

我所做的是编写一个mixin,您可以将其添加到需要悬停状态的组件中。 此mixin将为组件的状态添加新的hovered属性。如果用户将鼠标悬停在组件的主DOM节点上,则将其设置为true,并在用户离开元素时将其设置回false

现在,在组件渲染功能中,您可以执行以下操作:

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

现在每次hovered状态改变时,组件都会重新渲染。

我还为此创建了一个沙盒仓库,我用它来测试其中的一些模式。如果您想查看我的实现示例,请查看它。

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

答案 2 :(得分:24)

您可以使用Radium - 它是使用ReactJS的内联样式的开源工具。它完全添加了您需要的选择器。非常受欢迎,请查看 - Radium on npm

答案 3 :(得分:8)

完整的CSS支持正是这个庞大的CSSinJS库的原因,为了有效地执行此操作,您需要生成实际的CSS,而不是内联样式。在更大的系统中,内联样式的响应速度要慢得多。免责声明 - 我保留JSS

答案 4 :(得分:6)

Made Style It - 部分 - 由于这个原因(其他人对其他lib /语法的实现存在分歧,并且内联样式缺乏对属性值前缀的支持)。相信我们应该能够简单地在JavaScript中编写CSS并拥有完全自包含的组件HTML-CSS-JS。使用ES5 / ES6模板字符串,我们现在可以,它也可以! :)

npm install style-it --save

功能语法JSFIDDLE

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return Style.it(`
      .intro:hover {
        color: red;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}

export default Intro;

JSX语法JSFIDDLE

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .intro:hover {
          color: red;
        }
      `}

        <p className="intro">CSS-in-JS made simple -- just Style It.</p>
      </Style>
    );
  }
}

export default Intro;

答案 5 :(得分:5)

关于styled-componentsreact-router v4,您可以这样做:

import {NavLink} from 'react-router-dom'

const Link = styled(NavLink)`     
  background: blue;

  &:hover {
    color: white;
  }
`

...
<Clickable><Link to="/somewhere">somewhere</Link></Clickable>

答案 6 :(得分:4)

如果您使用React with Typescript,则结帐Typestyle

下面是一个示例代码:hover

import {style} from "typestyle";

/** convert a style object to a CSS class name */
const niceColors = style({
  transition: 'color .2s',
  color: 'blue',
  $nest: {
    '&:hover': {
      color: 'red'
    }
  }
});

<h1 className={niceColors}>Hello world</h1>

答案 7 :(得分:4)

添加到Jonathan's answer,以下是覆盖焦点和活动状态的事件,以及使用onMouseOver代替onMouseEnter的事件,因为如果您有任何孩子,后者不会冒泡应用事件的目标内的元素。

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>
    )
  }

答案 8 :(得分:3)

您可以使用css modules作为替代,并使用react-css-modules进行类名映射。

通过这种方式,您可以按如下方式导入样式,并使用本地范围内的普通css作为组件:

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);

这是webpack css modules example

答案 9 :(得分:3)

这是我使用React Hooks的解决方案。它结合了扩展运算符和三元运算符。

style.js

export default {
  normal:{
    background: 'purple',
    color: '#ffffff'
  },
  hover: {
    background: 'red'
  }
}

Button.js

import React, {useState} from 'react';
import style from './style.js'

function Button(){

  const [hover, setHover] = useState(false);

  return(
    <button
      onMouseEnter={()=>{
        setHover(true);
      }}
      onMouseLeave={()=>{
        setHover(false);
      }}
      style={{
        ...style.normal,
        ...(hover ? style.hover : null)
      }}>

        MyButtonText

    </button>
  )
}

答案 10 :(得分:2)

首先,使用setState的

onMouseOver和onMouseLeave似乎对我来说有些负担-但这是React的工作方式,对我来说似乎是最简单,最干净的解决方案。

例如,

呈现主题css服务器端也是一种很好的解决方案,并且可以使React组件更干净。

如果您不必在元素上添加动态样式(例如用于主题化),则根本不应该使用内联样式,而应使用css类。

这是一种传统的html / css规则,用于保持html / JSX的简洁明了。

答案 11 :(得分:2)

这可以通过 material-ui makeStyles 调用轻松实现:

import { makeStyles } from '@material-ui/core/styles';

makeStyles({
  root: {
    /* … */
    '&:hover': { /* … */ }
  },
});

答案 12 :(得分:2)

晚聚会但附带解决方案。您可以使用“&”为第n个Child等鼠标悬停定义样式:

 day: {
    display: "flex",
    flex: "1",
    justifyContent: "center",
    alignItems: "center",
    width: "50px",
    height: "50px",
    transition: "all 0.2s",
    borderLeft: "solid 1px #cccccc",

    "&:hover": {
      background: "#efefef"
    },
    "&:last-child": {
      borderRight: "solid 1px #cccccc"
    }
  },

答案 13 :(得分:1)

简单的方法是使用三元运算符

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={this.state.hover ? {"backgroundColor": 'red'}: {"backgroundColor": 'blue'}} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }

答案 14 :(得分:1)

对于在react组件中使用内联样式(以及使用:hover CSS函数),这可能是一个很好的黑客攻击:

... <style> {`.galleryThumbnail.selected:hover{outline:2px solid #00c6af}`} </style> ...

答案 15 :(得分:1)

这是用打字稿编写的用于悬停的通用包装器。该组件将在悬停事件上应用通过 props 'hoverStyle' 传递的样式。

import React, { useState } from 'react';

export const Hover: React.FC<{
  style?: React.CSSProperties;
  hoverStyle: React.CSSProperties;
}> = ({ style = {}, hoverStyle, children }) => {
  const [isHovered, setHovered] = useState(false);
  const calculatedStyle = { ...style, ...(isHovered ? hoverStyle : {}) };
  return (
    <div
      style={calculatedStyle}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    >
      {children}
    </div>
  );
};    

答案 16 :(得分:0)

使用挂钩:

const useFade = () => {
  const [ fade, setFade ] = useState(false);

  const onMouseEnter = () => {
    setFade(true);
  };

  const onMouseLeave = () => {
    setFade(false);
  };

  const fadeStyle = !fade ? {
    opacity: 1, transition: 'all .2s ease-in-out',
  } : {
    opacity: .5, transition: 'all .2s ease-in-out',
  };

  return { fadeStyle, onMouseEnter, onMouseLeave };
};

const ListItem = ({ style }) => {
  const { fadeStyle, ...fadeProps } = useFade();

  return (
    <Paper
      style={{...fadeStyle, ...style}}
      {...fadeProps}
    >
      {...}
    </Paper>
  );
};

答案 17 :(得分:0)

我不确定100%是否是答案,但这是我用来模拟CSS的技巧:使用颜色和图像直接内嵌鼠标悬停效果。

`This works best with an image`

class TestHover extends React.PureComponent {
render() {
const landingImage = {     
"backgroundImage": "url(https://i.dailymail.co.uk/i/pix/2015/09/01/18/2BE1E88B00000578-3218613-image-m-5_1441127035222.jpg)",
"BackgroundColor": "Red", `this can be any color`
"minHeight": "100%",
"backgroundAttachment": "fixed",
"backgroundPosition": "center",
"backgroundRepeat": "no-repeat",
"backgroundSize": "cover", 
"opacity": "0.8", `the hove trick is here in the opcaity slightly see through gives the effect when the background color changes`
    }

  return (
    <aside className="menu">
        <div className="menu-item">
          <div style={landingImage}>SOME TEXT</div>
        </div>
    </aside>
      ); 
  }
}
ReactDOM.render(
    <TestHover />,
  document.getElementById("root")
);

CSS:

.menu {
top: 2.70em;
bottom: 0px;
width: 100%;
position: absolute;
}

.menu-item {
cursor: pointer;
height: 100%;
font-size: 2em;
line-height: 1.3em;
color: #000;
font-family: "Poppins";
font-style: italic;
font-weight: 800;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
  

悬停之前

.menu-item:nth-child(1) {
color: white;
background-color: #001b37;
} 
  

悬停时

.menu-item:nth-child(1):hover {
color: green;
background-color: white;
}

示例:https://codepen.io/roryfn/pen/dxyYqj?editors=0011

答案 18 :(得分:0)

<Hoverable hoverStyle={styles.linkHover}>
  <a href="https://example.com" style={styles.link}>
    Go
  </a>
</Hoverable>

“悬停”定义为:

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 : {})
  });
}

答案 19 :(得分:0)

我在我最近的一个应用程序中使用了一个很好的hack-ish解决方案,这个解决方案适用于我的目的,我发现它比在vanilla js中编写自定义悬停设置功能更快(尽管我认识到,这可能不是最佳实践在大多数环境中..)所以,如果你仍然感兴趣,这里就是。

我创建一个父元素只是为了保持内联的javascript样式,然后是一个具有className或id的子节点,我的css样式表将锁定并在我的专用css文件中写入悬停样式。这是因为更细粒度的子元素通过继承接收内联js样式,但其cover文件覆盖了其悬停样式。

所以基本上,我的实际css文件的存在仅仅是为了保持悬停效果,没有别的。这使得它非常简洁和易于管理,并允许我在我的内联React组件样式中进行繁重的工作。

以下是一个例子:

const styles = {
  container: {
    height: '3em',
    backgroundColor: 'white',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    borderBottom: '1px solid gainsboro',
  },
  parent: {
    display: 'flex',
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    color: 'darkgrey',
  },
  child: {
    width: '6em',
    textAlign: 'center',
    verticalAlign: 'middle',
    lineHeight: '3em',
  },
};

var NavBar = (props) => {
  const menuOptions = ['home', 'blog', 'projects', 'about'];

  return (
    <div style={styles.container}>
      <div style={styles.parent}>
        {menuOptions.map((page) => <div className={'navBarOption'} style={styles.child} key={page}>{page}</div> )}
      </div>
    </div>
  );
};


ReactDOM.render(
  <NavBar/>,
  document.getElementById('app')
);
.navBarOption:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

请注意,“child”内联样式没有设置“color”属性。如果确实如此,这将无效,因为内联样式优先于我的样式表。

答案 20 :(得分:0)

我使用这个技巧,内联样式和 css 的混合:

//inline-style:
const button = {
  fontSize: "2em",
};
return (
  <div style={button} data-hover="button">
    <style>{`[data-hover="button"]:hover {
        font-size: 2.1em !important;
    }`}</style>
    {this.props.text}
  </div>
);

答案 21 :(得分:0)

我做了一些类似于 this 的事情,但我没有使用 material-ui 或 makeStyles。我在样式对象中的 css 中添加了悬停作为条件:

const styles = {
  hoverStyle: {
    color: 'grey',
    '&:hover': { color: 'blue !important' },
  }
};

var NavBar = (props) => {
  const menuOptions = ['home', 'blog', 'projects', 'about'];

  return (
    <div>
      <div>
        {menuOptions.map((page) => <div style={styles.hoverStyle} key={page}>{page}</div> )}
      </div>
    </div>
  );
};

这对我有用。