React.js内联样式最佳做法


511

我知道您可以在React类中指定样式,如下所示:

var MyDiv = React.createClass({
  render: function() {
    var style = {
      color: 'white',
      fontSize: 200
    };

    return <div style={style}> Have a good and productive day! </div>;
  }
});

我是否应该以这种方式进行所有样式设置,并且在CSS文件中完全没有指定样式?

还是应该完全避免使用内联样式?

两者兼而有之,似乎很奇怪而且很乱-在调整样式时需要检查两个位置。


您可以使用react-theme来组织内联样式,并使它们在构建可重用组件时易于自定义。它的工作原理与material-ui中的ThemeManager相似。
mantramantramantra

6
考虑使用github.com/css-modules/css-modulesgithub.com/gajus/react-css-modules是一个React实现(我是作者)。CSS模块和React CSS模块自动将您的组件类名称映射到在文档范围内分配了唯一名称的CSS模块。
加茹斯2015年

1
我必须写媒体查询时使用CSS。我还使用基本CSS库(如bootstrap)中的类。
vijayst,2016年

通常不建议将style属性用作样式元素的主要方法。(reactjs.org/docs/dom-elements.html#style
米德·埃卜拉欣

从今天开始,我建议使用css-in-js解决方案。它具有样式属性的所有优点,而没有缺点。我写了一个答案stackoverflow.com/questions/26882177/...
奔鲤鱼

Answers:


462

目前还没有很多“最佳实践”。我们中那些使用内联样式作为React组件的人仍在进行大量试验。

有许多方法千差万别: React内联样式库比较表

全部还是全部?

我们所称的“样式”实际上包括许多概念:

  • 布局- 元素/组件与其他对象的关系外观
  • 外观— 元素/组件的特征
  • 行为和状态- 元素/组件在给定状态下的外观

从状态样式开始

React已经在管理组件的状态,这使得状态和行为样式自然适合与组件逻辑并置。

与其构建要使用条件状态类进行渲染的组件,不如考虑直接添加状态样式:

// Typical component with state-classes
<li 
 className={classnames({ 'todo-list__item': true, 'is-complete': item.complete })} />


// Using inline-styles for state
<li className='todo-list__item'
 style={(item.complete) ? styles.complete : {}} />

请注意,我们使用的是外观样式的类,但不再使用任何带.is-前缀的类来表示状态和行为

我们可以使用Object.assign(ES6)或_.extend(下划线/破折号)添加对多个状态的支持:

// Supporting multiple-states with inline-styles
<li 'todo-list__item'
 style={Object.assign({}, item.complete && styles.complete, item.due && styles.due )}>

定制和可重用性

现在,我们正在使用Object.assign它变得非常简单,以使我们的组件可以以不同的样式重用。如果我们想覆盖默认样式,则可以在调用现场使用props进行覆盖,例如:<TodoItem dueStyle={ fontWeight: "bold" } />。像这样实现:

<li 'todo-list__item'
 style={Object.assign({},
         item.due && styles.due,
         item.due && this.props.dueStyles)}>

布局

就个人而言,我认为没有必要的理由来使用内联布局样式。有很多很棒的CSS布局系统。我只用一个。

就是说,不要将布局样式直接添加到您的组件中。用布局组件包装组件。这是一个例子。

// This couples your component to the layout system
// It reduces the reusability of your component
<UserBadge
 className="col-xs-12 col-sm-6 col-md-8"
 firstName="Michael"
 lastName="Chan" />

// This is much easier to maintain and change
<div class="col-xs-12 col-sm-6 col-md-8">
  <UserBadge
   firstName="Michael"
   lastName="Chan" />
</div>

为了获得布局支持,我经常尝试将组件设计为100% widthand height

出现

这是“内联式”辩论中最具争议的领域。最终,这取决于您设计的组件以及JavaScript团队的舒适度。

可以肯定的是,您需要图书馆的协助。浏览器状态(:hover:focus)和媒体查询在原始React中很痛苦。

我喜欢Radium,因为这些硬部件的语法旨在模拟SASS。

代码组织

通常,您会在模块外部看到样式对象。对于待办事项列表组件,它可能看起来像这样:

var styles = {
  root: {
    display: "block"
  },
  item: {
    color: "black"

    complete: {
      textDecoration: "line-through"
    },

    due: {
      color: "red"
    }
  },
}

吸气功能

在模板中添加一堆样式逻辑可能会有点混乱(如上所示)。我喜欢创建getter函数来计算样式:

React.createClass({
  getStyles: function () {
    return Object.assign(
      {},
      item.props.complete && styles.complete,
      item.props.due && styles.due,
      item.props.due && this.props.dueStyles
    );
  },

  render: function () {
    return <li style={this.getStyles()}>{this.props.item}</li>
  }
});

进一步观察

我在今年早些时候的React Europe上更详细地讨论了所有这些内容:内联样式以及何时最好使用“ CSS”

在您发现新发现的过程中,我很乐意提供帮助:)打我-> @chantastic


10
伟大的阅读。也非常感谢您@chantastic的相关演讲。#accepted
eye_mew 2015年

5
“用布局组件包装您的组件”:很明显,但是正是我所需要的。
tandrewnichols

2
@chantastic好答案。一年过去了,这一切仍然正确吗?只是真的只是进入React和内联样式的想法,并想知道自发布此答案以来是否发生了任何变化。
alexrussell

4
@alexrussell谢谢!我认为这里的答案仍然很好。发生了变化的一个方面是,阿芙罗狄蒂似乎是社区首选的内联阶梯库(在Radium之上),尽管这实际上是个人喜好问题。
不可思议的

2
@alexrussell糟糕。不小心提早提交。我现在使用这种组件技术来设置组件样式。这个想法很简单。您创建一个只关心的风格和撰写应用程序与那些,而不是部件divspana,等这将有助于孤立保持的风格,无论你使用的库。reactpatterns.com/#Style组件
不可思议的

134

React中的style属性期望该值是一个对象,即键值对。

style = {}里面将有另一个对象{float:'right'}以使其工作。

<span style={{float:'right'}}>{'Download Audit'}</span>

希望这能解决问题


3
因此,如果我想在JS文件中使用css类,则如何使用相同的媒体查询
Pardeep Jain

@PardeepJain一种方法是使用Emotion,如果您对met.js峰会2018
Bruno Finger

这种方法的一个缺点是,内联定义样式每次都会创建一个新对象。这会style导致道具差异,从而导致性能问题。至少要在之外定义一个不变的样式render。希望这可以帮助!
Dawson B,

49

我在React组件中广泛使用内联样式。我发现将样式并置在组件中非常清晰,因为它总是很清楚组件有什么样式以及没有什么样式。加上手头的Java脚本的全部功能确实简化了更复杂的样式需求。

一开始我并没有说服,但是经过数月的摸索之后,我已经完全转换,并且正在将所有CSS转换为内联或其他JS驱动的CSS方法。

Facebook员工和React贡献者“ vjeux”的演示也非常有帮助— https://speakerdeck.com/vjeux/react-css-in-js


5
如何使用内联样式制作响应式布局?您无法在此处进行媒体查询。
宙斯

您获得了js的强大功能,js可以检测浏览器大小以动态构建样式。
JordyvD

3
@ g3mini仍然不是推荐的方法,因为对于样式化组件(如和其他组件)CSS Modules,存在很多更强大的解决方案styled-components
Denialos

js中也有css =)虽然我现在更喜欢使用CSS模块。
JordyvD

这里没有考虑的一件事是,很容易在同一个SASS文件中查看父样式和子样式,而如果您需要查看不同组件中的规则,则可能必须打开和关闭许多文件。
林戈

23

样式属性的主要目的是用于基于状态的动态样式。例如,您可以在进度条上基于某些状态,或者在位置或可见性基于其他状态下具有宽度样式。

JS中的样式强加了限制,即应用程序无法为可重用组件提供自定义样式。在上述情况下,这是完全可以接受的,但当您更改可见特性(尤其是颜色)时,这是完全可以接受的。


我们有一段时间的一个相关想法是能够使用gulp和LESS隔离React组件的特定CSS规则。有点像为每个组件设置一个特定的className,然后在组件文件中为该类添加特定的CSS。这很有道理。
David Hellsing 2014年

我经常使用“ component- {app}-{componentName}”格式的类名。“ {app}”可以是应用程序的名称,也可以是与应用程序无关的组件的“公用”名称。例如,TodoList的“ component-foo-todo-list”和“ component-common-light-switch-toggle”。对于打包的组件,{app}将是npm名称。这就是您所指的吗?
Brigand 2014年

是的,命名约定是一回事,但主要的事情是将隔离的CSS规则添加到同一组件js文件中。
David Hellsing 2014年

2
这不是真的。您可以明确地应用自定义样式来响应组件。该组件只需要将自己的样式对象与从上方移交的对象合并即可,该对象可以来自应用程序数据。见的最后一张幻灯片speakerdeck.com/vjeux/react-css-in-js像下面提到
Flion

当然,如果您的组件是单个元素,但是考虑到<div><a>foo <b>bar</b></a><table>...</table></div>如何从道具中设置样式呢?请记住,html结构应保留实现细节,否则您将失去很多组件提供的好处。
布莱根,2015年


10

JSX中的样式与HTML中的样式非常相似。

HTML案例:

div style =“ background-color:red; color:white”

JSX案例:

div style = {{backgroundColor:'red',color:'white'}}


8

我要做的是为我的每个可重用组件提供一个唯一的自定义元素名称,然后为该组件创建一个css文件,特别是为该组件(以及仅针对该组件)提供所有样式选项。

var MyDiv = React.createClass({
  render: function() {
    return <custom-component style={style}> Have a good and productive day! </custom-component>;
  }
});

在文件“ custom-component.css”中,每个条目都将以custom-component标签开头:

custom-component { 
   display: block; /* have it work as a div */
   color: 'white'; 
   fontSize: 200; 
} 
custom-component h1 { 
  font-size: 1.4em; 
}

这意味着您不会松开关注点分离的关键概念。视图与风格。如果共享您的组件,则其他人可以更轻松地为其设置主题以使其与其余网页匹配。


这就是我的方法。唯一的缺点是它是两个文件而不是一个。我可以忍受这一点。
调味

5

这真的取决于如何你的应用程序是,如果你想用捆扎机喜欢的WebPack在构建和捆绑CSS和JS在一起,你想如何管理您的应用程序流!最后,根据您的情况,您可以做出决定!

我在大型项目中组织文件的偏好是将CSS和JS文件分开,这样可以更轻松地共享文件,让UI用户更轻松地浏览CSS文件,还可以为整个应用程序组织更加整齐的文件!

始终以这种方式思考,确保在开发阶段一切都应该放置在适当的位置,并正确命名,并易于其他开发人员查找...

我个人根据需要混合使用它们,例如...尝试使用外部CSS,但是如果需要,React也将接受样式,则需要将其作为具有键值的对象传递,如下所示:

import React from 'react';

const App = props => {
  return (
    <div className="app" style={{background: 'red', color: 'white'}}>  /*<<<<look at style here*/
      Hello World...
    </div>
  )
}

export default App;


3

我通常有与每个React组件相关联的scss文件。但是,我不明白为什么您不使用逻辑封装组件并进行查看。我的意思是,Web组件也有类似的问题。


3

根据您的配置,内联样式可以为您提供热重装。每次样式更改时,都会立即重新渲染该网页。这有助于我更快地开发组件。话虽如此,我相信您可以为CSS + SCSS设置热重载环境。


3

您可以使用内联样式,但是如果在所有样式中都使用它们,则会受到一些限制,一些已知的限制是您不能在其中使用CSS伪选择器媒体查询

您可以使用Radium 来解决此问题,但我仍然觉得项目发展会变得麻烦。

我建议使用CSS模块

使用CSS模块,您将可以自由地在CSS文件中编写CSS,而不必担心命名冲突,CSS模块会注意这一点。

此方法的优点是,它为您提供了特定组件的样式功能。这将为下一开发人员创建更多可维护的代码和可读的项目体系结构。


3

对于某些组件,更容易使用内联样式。另外,我发现对组件样式进行动画处理更容易,更简洁(因为我使用的是Javascript,而不是CSS)。

对于独立组件,我使用“扩展运算符”或“ ...”。对我来说,它清晰,美丽并且可以在狭窄的空间中工作。这是我制作的一些加载动画,以显示它的好处:

<div style={{...this.styles.container, ...this.state.opacity}}>
    <div style={{...this.state.colors[0], ...this.styles.block}}/>
    <div style={{...this.state.colors[1], ...this.styles.block}}/>
    <div style={{...this.state.colors[2], ...this.styles.block}}/>
    <div style={{...this.state.colors[7], ...this.styles.block}}/>
    <div style={{...this.styles.block}}/>
    <div style={{...this.state.colors[3], ...this.styles.block}}/>
    <div style={{...this.state.colors[6], ...this.styles.block}}/>
    <div style={{...this.state.colors[5], ...this.styles.block}}/>
    <div style={{...this.state.colors[4], ...this.styles.block}}/>
  </div>

    this.styles = {
  container: {
    'display': 'flex',
    'flexDirection': 'row',
    'justifyContent': 'center',
    'alignItems': 'center',
    'flexWrap': 'wrap',
    'width': 21,
    'height': 21,
    'borderRadius': '50%'
  },
  block: {
    'width': 7,
    'height': 7,
    'borderRadius': '50%',
  }
}
this.state = {
  colors: [
    { backgroundColor: 'red'},
    { backgroundColor: 'blue'},
    { backgroundColor: 'yellow'},
    { backgroundColor: 'green'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
  ],
  opacity: {
    'opacity': 0
  }
}

编辑2019年11月

在行业(一家财富500强公司)工作,我不允许进行任何内联样式。在我们的团队中,我们已确定嵌入式样式不可读且不可维护。而且,在亲眼目睹了内联样式使支持应用程序变得完全无法忍受之后,我不得不同意。我完全不鼓励内联样式。


2

内联样式的问题是内容安全策略(CSP)变得越来越普遍,不允许这样做。因此,我建议完全避免使用内联样式。

更新: 为了进一步说明,CSP是服务器发送的HTTP标头,它们限制了可以在页面上显示的内容。如果开发人员对站点的编码不正确,则可以将其简单地应用到服务器上,以阻止攻击者做任何顽皮的事情。

这些限制的大多数目的是阻止XSS(跨站点脚本)攻击。XSS是攻击者找出在页面上包含他自己的javascript的方法(例如,如果我输入用户名bob<SCRIPT>alert("hello")</SCRIPT>然后发表评论,而您访问该页面,则该页面不应显示警报)。开发人员应拒绝让用户向网站中添加此类内容的功能,但是如果万一他们犯了错误,则CSP会在发现任何script>标签时阻止该页面加载。

CSP只是对开发人员的一种额外保护,可确保开发人员犯了一个错误,即攻击者不会对该站点的访问者造成问题。

因此,所有这些都是XSS,但是如果攻击者不能包含<script>标签,但可以包含<style>标签或style=在标签上包含参数,该怎么办?然后,他也许可以以某种方式来更改网站的外观,从而使您被诱骗单击错误的按钮或其他问题。这不是什么要担心的问题,但是仍然需要避免,CSP会为您做到这一点。

https://securityheaders.io/是测试CSP网站的一个很好的资源。

您可以在以下位置阅读有关CSP的更多信息:http : //www.html5rocks.com/zh-cn/tutorials/security/content-security-policy/


您能再说明一点吗?
德米特里·马南尼科夫2015年

8
您是专门指该unsafe-inline政策。通过此策略,可以限制样式元素,使其不限于<style>应用于元素的style属性的内联样式<div style="">。由于上面的问题是关于style属性的,因此似乎完全不建议使用内联样式的建议。另外,react建议将所有CSS移入JS:github.com/reactjs/react-future/blob/master/04%20-%20Layout/…–
potench

1
@potench该链接确实很棒,可能值得其回答
eye_mew 2015年

6
不幸的是,@eye_mew和@ Sam-Rad-@potench的答案不正确。CSP unsafe-inline禁用所有形式的内联样式,包括style属性。您可以通过JS(例如elem.style.color = 'blue';)以编程方式在元素上使用样式API ,但不能在元素上设置样式属性(就像'unsafe-inline'在script-src指令中禁止内联脚本标签一样,但不允许onclick属性和朋友。)
Alex Sexton 2015年

2
Facebook团队提供了更多有关React v15 github.com/facebook/react/issues/5878中如何将样式应用于CSP的信息。值得一读
Mark Lundin

2

与在CSS文件中编写样式相比,React的style属性具有以下优点

  1. 使用工具javascript作为编程语言的能力可以控制元素的样式。这包括嵌入变量,使用条件以及将样式传递给子组件。
  2. 一种“组件”方法。为组件编写的HTML,JS和CSS代码不再分开。组件的代码被合并,并写在一个地方。

但是,React的style属性有一些缺点 -您不能

  1. 无法使用媒体查询
  2. 不能使用伪选择器,
  3. 与CSS类相比效率较低。

在JS中使用CSS,您可以获得样式标签的所有优点,而没有这些缺点。到今天为止,js库中有一些受欢迎且受良好支持的CSS,包括:Emotion,Styled-Components和Radium。这些库对CSS来说就像React对HTML一样。它们允许您编写CSS并在JS代码中控制CSS。

让我们比较一下我们的代码在样式简单元素时的外观。我们将设置“ hello world” div的样式,使其在桌面上显示较大,而在移动设备上显示较小。

使用样式属性

return (
   <div style={{fontSize:24}} className="hello-world">
      Hello world
   </div>
)

由于无法在样式标签中进行媒体查询,因此我们必须在元素中添加className并添加CSS规则。

@media screen and (max-width: 700px){
   .hello-world {
      font-size: 16px; 
   }
}

使用Emotion的10 CSS标签

return (
   <div
      css={{
         fontSize: 24, 
         [CSS_CONSTS.MOBILE_MAX_MEDIA_QUERY]:{
            fontSize: 16 
         }
      }
   >
      Hello world
   </div>
)

Emotion还支持模板字符串以及样式化的组件。因此,如果您愿意,可以写:

return (
   <Box>
      Hello world
   </Box>
)

const Box = styled.div`
   font-size: 24px; 
   ${CSS_CONSTS.MOBILE_MAX_MEDIA_QUERY}{
      font-size: 16px; 
   }
`

引擎盖后面的“ JS中的Css”使用css类。情感是专门考虑性能而构建的,并使用缓存。与React样式属性相比,JS中的Css将提供更好的性能。

最佳实践

以下是我推荐的一些最佳做法:

  1. 如果要内联或在JS中设置元素的样式,请使用css-in-js库,请勿使用style属性。

我是否应该以这种方式进行所有样式设置,并且在CSS文件中完全没有指定样式?

  1. 如果使用css-in-js解决方案,则无需在Css文件中编写样式。用JS编写CSS更为出色,因为您可以使用JS提供的所有编程语言工具。

我应该完全避免使用内联样式吗?

  1. 一般而言,在JS中构建样式代码与构建代码非常相似。例如:
    • 识别重复的样式,并将它们写在一个地方。在Emotion中,有两种方法可以做到这一点:
// option 1 - Write common styles in CONSTANT variables
// styles.js
export const COMMON_STYLES = {
   BUTTON: css`
      background-color: blue; 
      color: white; 
      :hover {
         background-color: dark-blue; 
      }
   `
}

// SomeButton.js
const SomeButton = (props) => {
   ...
   return (
      <button
         css={COMMON_STYLES.BUTTON}
         ...
      >
         Click Me
      </button>
   )
}

// Option 2 - Write your common styles in a dedicated component 

const Button = styled.button`
   background-color: blue; 
   color: white; 
   :hover {
      background-color: dark-blue; 
   }   
`

const SomeButton = (props) => {
   ...
   return (
      <Button ...> 
         Click me
      </Button>
   )
}
  • React编码模式由封装的组件组成-将控制组件的HTML和JS写在一个文件中。那就是您要设置该组件样式的CSS /样式代码所在的位置。

  • 必要时,在组件中添加样式道具。这样,您可以重用子组件中编写的代码和样式,并由父组件根据您的特定需求对其进行自定义。

const Button = styled.button([COMMON_STYLES.BUTTON, props=>props.stl])

const SmallButton = (props)=>(
   <Button 
      ...
      stl={css`font-size: 12px`}
   >
      Click me if you can see me
   </Button>
)

const BigButton = (props) => (
   <Button
      ...
      stl={css`font-size: 30px;`}
   >
      Click me
   </Button>
)

2

您也可以使用StrCSS,它创建隔离的类名等等!示例代码如下所示。您可以(可选)从Visual Studio Marketplace安装VSCode扩展,以支持语法突出显示!

资料来源:strcss

import { Sheet } from "strcss";
import React, { Component } from "react";

const sheet = new Sheet(`
  map button
    color green
    color red !ios
    fontSize 16
  on hover
    opacity .5
  at mobile
    fontSize 10
`);

export class User extends Component {
  render() {
    return <div className={sheet.map.button}>
      {"Look mom, I'm green!
      Unless you're on iOS..."}
    </div>;
  }
}

1

有时候,我们需要为组件中的某些元素设置样式,但是如果我们必须仅显示该组件中的某个元素,或者样式是如此之少,则可以使用React js中的内联样式,而不是使用CSS类。reactjs内联样式与HTML内联样式相同,只是属性名称略有不同

使用style = {{prop:“ value”}}在任何标签中编写样式

import React, { Component } from "react";
    import { Redirect } from "react-router";

    class InlineStyle extends Component {
      constructor(props) {
        super(props);
        this.state = {};
      }

      render() {
        return (
          <div>
            <div>
              <div
                style={{
                  color: "red",
                  fontSize: 40,
                  background: "green"
                }}// this is inline style in reactjs
              >

              </div>
            </div>
          </div>
        );
      }
    }
    export default InlineStyle;

您能否添加一些有关此代码如何以及为何为OP问题提供答案的更多信息?谢谢!
deHaar

1

2020更新:最佳实践是使用一个库,该库已经为您完成了艰苦的工作,并且在您按照视频最初接受的答案所指出的那样进行切换时不会杀死您的团队(仍然有用)。只是为了了解趋势,这是一个非常有用的图表。在对此进行自己的研究之后,我选择将Emotion用于我的新项目,事实证明它非常灵活且可扩展。

鉴于2015年最受好评的答案建议 Radium,现在将Radium降级为维护模式。因此,添加替代列表似乎是合理的。终止Radium 的帖子建议了一些库。链接的每个站点都有易于使用的示例,因此我将避免在此处复制和粘贴代码。

  • Emotion受其他样式元素的 “启发” ,在js中使用样式,可以与框架无关,但肯定会促进其React库。截至本文发布时,情绪一直保持最新。
  • 样式化组件具有可比性,并且提供了许多与Emotion相同的功能。也积极地得到维护。Emotion和样式组件均具有相似的语法。它是专门为与React组件一起使用而构建的。
  • JSS js中样式的另一种选择是框架无关的,尽管它确实有许多框架程序包,其中包括React-JSS。

0

无论如何,绝对不建议使用内联CSS。我们在基于JSS的项目中使用了样式化组件。它通过在组件上添加动态类名称来保护CSS覆盖。您还可以根据传递的道具添加css值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.