React 中的内联 CSS 样式:如何实现 a:hover?
Posted
技术标签:
【中文标题】React 中的内联 CSS 样式:如何实现 a:hover?【英文标题】:Inline CSS styles in React: how to implement a:hover? 【发布时间】:2015-04-06 13:31:36 【问题描述】:我非常喜欢inline CSS pattern in React 并决定使用它。
但是,您不能使用:hover
和类似的选择器。那么在使用内联 CSS 样式时实现高亮显示的最佳方法是什么?
#reactjs 的一个建议是拥有一个 Clickable
组件并像这样使用它:
<Clickable>
<Link />
</Clickable>
Clickable
有一个hovered
状态并将其作为道具传递给链接。但是,Clickable
(我实现它的方式)将Link
包装在div
中,以便它可以设置onMouseEnter
和onMouseLeave
。这让事情变得有点复杂(例如,span
包裹在 div
中的行为与 span
不同)。
有没有更简单的方法?
【问题讨论】:
你是绝对正确的 - 使用内联样式模拟 :hover 等选择器的唯一方法是使用onMouseEnter
和 onMouseLeave
。关于它的确切实施 - 这完全取决于你。查看您的具体示例,为什么不将 <Clickable/>
包装器设为 span
?
我建议使用外部样式表和 ExtractText Webpack 插件,如果您希望使用 ServerRender,这将帮助您更长时间地运行,否则您可以尝试 Radium github.com/FormidableLabs/radium
目前 Styled Component 是在 react 中模拟 css/scss 的所有可能性的最佳解决方案。
【参考方案1】:
我认为 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>
)
然后您可以使用悬停状态(真/假)来更改链接的样式。
【讨论】:
这似乎涵盖了:hover
,但不包括:focus
@AdamTuttle react 有一个 onFocus
事件;所以你可以为:focus
和:hover
做同样的事情,除了需要onMouseEnter
和onMouseLeave
你只需要onFocus
请注意,此方法强制在主线程上执行,而典型的 CSS 事件处理效率更高。【参考方案2】:
聚会迟到了,但有解决办法。您可以使用“&”来定义悬停第 n 个子等的样式:
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"
,
【讨论】:
这不是一个解决方案,问题是如何使用 INLINE css,而不是使用单独的样式表。 老兄,仔细看看。这是内联样式。 这不适用于 React。你需要一个额外的库,比如 styled-components。 它不适用于内联样式,这个例子会带来混乱。如果它确实有效,请提供一个完整组件的更好示例。 这不仅仅在 React 上工作,在 codesandbox.io/s/zealous-roentgen-yo57x 上测试【参考方案3】:我也有同样的情况。非常喜欢在组件中保留样式的模式,但悬停状态似乎是最后一个障碍。
我所做的是编写一个 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
【讨论】:
不是长期运行的好解决方案,Radium 将是更好的选择或使用外部样式表 @abhirathore2006 Radium 的工作方式相同,问题是如何在不使用外部样式表的情况下做到这一点 使用普通扩展运算符不是更有意义吗? 上述m
是什么?【参考方案4】:
您可以使用 Radium - 它是一个用于 ReactJS 内联样式的开源工具。它准确地添加了您需要的选择器。很受欢迎,看看-Radium on npm
【讨论】:
我刚看到这篇文章,您将如何在以下情况下实现 Radium?module.exports = React.createClass( displayName: 'App',)
@Rkayat 您可以将其包装为module.exports = Radium(React.createClass( displayName: 'App',))
或将类分配给一个值并在其上方添加@Radium
装饰器,因为文档提到github.com/FormidableLabs/radium#usage
还有一个很棒的东西叫做 CSS ;)【参考方案5】:
这是我使用 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>
)
【讨论】:
我喜欢有创造力的人如何使用这些类型的东西,你可能可以使用像const onMouseEnter, onMouseLeave, styles = useHoverStyle(style.hover)
这样的自定义钩子让这个更干净、更可重用由于缺乏对悬停状态的内联样式支持,因此依赖于如此复杂的 JS ?【参考方案6】:
完整的 CSS 支持正是如此庞大的 CSSinJS 库的原因,为了有效地做到这一点,您需要生成实际的 CSS,而不是内联样式。此外,内联样式在更大的系统中的反应要慢得多。免责声明 - 我维护JSS。
【讨论】:
是什么让它变慢了? @ICW 因为涉及到JS。【参考方案7】:制作Style It——部分原因——因为这个原因(其他人不同意其他库/语法的实现以及内联样式缺乏对属性值前缀的支持)。相信我们应该能够简单地用 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;
【讨论】:
我在 JSX 语法示例中注意到,JSFiddle 链接具有正确的代码,但此处显示的示例在样式结束标记后缺少右括号,并且缩进可能是由于缺少括号而关闭.【参考方案8】:添加到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>
)
【讨论】:
关于可访问性的选项卡交互怎么样?我认为这只是一种解决方法。【参考方案9】:如果你使用带有 Typescript 的 React,请查看 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>
【讨论】:
【参考方案10】:关于styled-components 和react-router v4,您可以这样做:
import NavLink from 'react-router-dom'
const Link = styled(NavLink)`
background: blue;
&:hover
color: white;
`
...
<Clickable><Link to="/somewhere">somewhere</Link></Clickable>
【讨论】:
【参考方案11】:简单的方法是使用三元运算符
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>
)
【讨论】:
【参考方案12】:这对于在 React 组件中具有内联样式(并且还使用 :hover CSS 函数)来说是一个不错的 hack:
...
<style>
`.galleryThumbnail.selected:hoveroutline:2px solid #00c6af`
</style>
...
【讨论】:
【参考方案13】:您可以使用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
【讨论】:
仅供参考:如果您使用 Meteor,请查看此软件包:github.com/nathantreid/meteor-css-modules。到目前为止,我自己使用它取得了巨大的成功。 这是设置 react 组件样式的好方法,但不能完全控制内联样式。例如,您不能像使用 Radium 或其他基于onMouseOver
的解决方案那样在运行时更改 :hover
样式【参考方案14】:
onMouseOver 和 onMouseLeave 与 setState 起初对我来说似乎有点开销 - 但由于这就是 react 的工作原理,对我来说它似乎是最简单和最干净的解决方案。
例如,渲染一个主题 css 服务器端也是一个很好的解决方案,并且可以保持反应组件更干净。
如果您不必将动态样式附加到元素(例如用于主题化),则根本不应该使用内联样式,而应使用 css 类。
这是一个传统的 html/css 规则,用于保持 html/JSX 简洁明了。
【讨论】:
【参考方案15】:这是使用 CSS 变量的另一个选项。这需要提前定义 css 悬停,所以我猜它不是纯内联的,而是非常少的代码和灵活的。
css(设置悬停状态):
.p:hover:
color:var(--hover-color) !important,
opacity:var(--hover-opacity)
反应:
<p style='color':'red','--hover-color':'blue','--hover-opacity':0.5>
【讨论】:
这是最好的答案!干净,没有依赖,可以理解,最重要的是,工作!谢谢@yeahdixon【参考方案16】:这是一个用打字稿编写的通用悬停包装器。该组件将在悬停事件上应用通过 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>
);
;
【讨论】:
【参考方案17】:这可以通过material-ui makeStyles
调用轻松实现:
import makeStyles from '@material-ui/core/styles';
makeStyles(
root:
/* … */
'&:hover': /* … */
,
);
【讨论】:
【参考方案18】:我做了类似于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>
);
;
这对我有用。
【讨论】:
它输出:&: hover: [object Object];
只有在项目中集成了 sass 时才可能有效,否则无效(我刚刚测试过,悬停声明被简单地丢弃了)【参考方案19】:
使用钩子:
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>
);
;
【讨论】:
【参考方案20】:<Hoverable hoverStyle=styles.linkHover>
<a href="https://example.com" style=styles.link>
Go
</a>
</Hoverable>
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 : )
);
【讨论】:
【参考方案21】:我使用这个技巧,内联样式和 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>
);
【讨论】:
【参考方案22】:我找到了一种简洁的方法,用 useState
周围的包装器,我称之为 useHover
。
不需要额外的库/框架。
const App = () =>
const hover = useHover(backgroundColor: "LightBlue")
return <p ...hover>Hover me!</p>
包装代码:
function useHover(styleOnHover: CSSProperties, styleOnNotHover: CSSProperties = )
const [style, setStyle] = React.useState(styleOnNotHover);
const onMouseEnter = () => setStyle(styleOnHover)
const onMouseLeave = () => setStyle(styleOnNotHover)
return style, onMouseEnter, onMouseLeave
请注意,useHover
有一个可选的第二个参数,用于当组件未悬停时的样式。
试试看here
【讨论】:
【参考方案23】:我在我最近的一个应用程序中使用了一个非常 hack-ish 的解决方案,它适用于我的目的,我发现它比在 vanilla js 中编写自定义悬停设置函数更快(虽然,我承认,也许不是最佳实践在大多数环境中..) 所以,如果你仍然感兴趣,那就去吧。
我创建一个父元素只是为了保存内联 javascript 样式,然后创建一个具有 className 或 id 的子元素,我的 css 样式表将锁定并在我的专用 css 文件中写入悬停样式。这是因为更细粒度的子元素通过继承接收内联 js 样式,但其悬停样式被 css 文件覆盖。
所以基本上,我的实际 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”属性。如果是这样,这将不起作用,因为内联样式将优先于我的样式表。
【讨论】:
【参考方案24】:我不能 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
【讨论】:
【参考方案25】:您可以创建一个 abstract
悬停类,例如颜色。
.hoverClassColor:hover
color:var(--hover-color) !important;
然后对于所有想要在悬停时将颜色更改为red
的元素:
render()
return <a className='hoverClassColor' style='--hover-color':'red'>Test</a>
对我来说,它就像内联,因为这些类是抽象的,可以重复用于您想要实现颜色悬停的所有元素。
【讨论】:
以上是关于React 中的内联 CSS 样式:如何实现 a:hover?的主要内容,如果未能解决你的问题,请参考以下文章