330

In React you can clearly create an object and assign it as an inline style. i.e.. mentioned below.

var divStyle = {
  color: 'white',
  backgroundImage: 'url(' + imgUrl + ')',
  WebkitTransition: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};

var divStyle2 = {fontSize: '18px'};

React.render(<div style={divStyle}>Hello World!</div>, mountNode);

How can I combine multiple objects and assign them together?

Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
PythonIsGreat
  • 7,529
  • 7
  • 21
  • 26

20 Answers20

590

If you're using React Native, you can use the array notation:

<View style={[styles.base, styles.background]} />

Check out my detailed blog post about this.

Nick
  • 11,483
  • 8
  • 41
  • 44
  • 70
    Sadly you can't do this in regular React. – YoTengoUnLCD May 06 '17 at 05:25
  • 17
    This should be the accepted answer if you're using React-Native – calcazar Aug 15 '17 at 20:04
  • 3
    You can slightly modify existing inline style by adding the style names/values. For example, `` – Gürol Canbek Sep 01 '18 at 19:48
  • For two static styles, doing [`StyleSheet.compose()`](https://facebook.github.io/react-native/docs/stylesheet#compose) outside the render function might be more efficient. It will produce a new static stylesheet that will only be sent over the bridge once. (This advice does not apply to styles which change at runtime, or which are inline instead of in a StyleSheet.) – joeytwiddle Nov 13 '19 at 08:36
355

You can use the spread operator:

 <button style={{...styles.panel.button,...styles.panel.backButton}}>Back</button
Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
Nath
  • 6,774
  • 2
  • 28
  • 22
72

You can do this with Object.assign().

In your example, you would do:

ReactDOM.render(
    <div style={Object.assign(divStyle, divStyle2)}>
        Hello World!
    </div>,
    mountNode
);

That will merge the two styles. The second style will replace the first if there are matching properties.

As Brandon noted, you should use Object.assign({}, divStyle, divStyle2) if you want to reuse divStyle without the fontSize applied to it.

I like to use this to make components with default properties. For example, here's a little stateless component with a default margin-right:

const DivWithDefaults = ({ style, children, ...otherProps }) =>
    <div style={Object.assign({ marginRight: "1.5em" }, style)} {...otherProps}>
        {children}
    </div>;

So we can render something like this:

<DivWithDefaults>
    Some text.
</DivWithDefaults>
<DivWithDefaults className="someClass" style={{ width: "50%" }}>
    Some more text.
</DivWithDefaults>
<DivWithDefaults id="someID" style={{ marginRight: "10px", height: "20px" }}>
    Even more text.
</DivWithDefaults>

Which will give us the result:

<div style="margin-right:1.5em;">Some text.</div>
<div style="margin-right:1.5em;width50%;" class="someClass">Some more text.</div>
<div style="margin-right:10px;height:20px;" id="someID">Even more text.</div>
Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
qel
  • 944
  • 7
  • 7
  • 6
    this solution is potentially misusing `Object.assign()` in a way that would lead to some undesirable consequences. See [the answer here](http://stackoverflow.com/a/37686582/5456001) a more reliable solution. – Brandon Jun 07 '16 at 18:23
  • 2
    Your answer demonstrates a way to misuse Object.assign(). That might be useful information for some people, but it doesn't apply to my example. This example is not storing the default in an object, mutating it, then reusing the mutated object somewhere else. – qel Jun 08 '16 at 19:00
  • disagree. you address two separate ways of using `Object.assign()` in your answer. the first, in the first few sentences, is an example of the misuse I identified (ie, if OP did what you advise in your first `code` block, he/she'd mutate `{divStyle}`). the second way--ie, wrapping it in a function as you have, will work, but the answer doesn't make it clear that you're _working around_ `Object.assign()`'s common 'gotcha' wrt immutability (though personally I think it's a little cumbersome to write a custom stateless function for every default component). – Brandon Jun 08 '16 at 23:11
  • Oh, OK. That's true. If he wanted to reuse divStyle without applying the fontSize it'd need the empty object first. I'll update the answer. – qel Jun 10 '16 at 20:47
  • Object.assign() is by far the most convenient way to achieve a concatenation :) – aldobsom Jul 22 '19 at 16:51
53

Unlike React Native, we cannot pass array of styles in React, like

<View style={[style1, style2]} />

In React, we need to create the single object of styles before passing it to style property. Like:

const Header = (props) => {
  let baseStyle = {
    color: 'red',
  }

  let enhancedStyle = {
    fontSize: '38px'
  }

  return(
    <h1 style={{...baseStyle, ...enhancedStyle}}>{props.title}</h1>
  );
}

We have used ES6 Spread operator to combine two styles. You can also use Object.assign() as well for the same purpose.

This also works if you don't need to store your style in a var

<Segment style={{...segmentStyle, ...{height:'100%'}}}>
    Your content
</Segment>
Andy
  • 2,124
  • 1
  • 26
  • 29
achyut pokhrel
  • 694
  • 5
  • 5
33

Object.assign() is an easy solution, but the (currently) top answer's usage of it — while just fine for making stateless components, will cause problems for the OP's desired objective of merging two state objects.

With two arguments, Object.assign() will actually mutate the first object in-place, affecting future instantiations.

Ex:

Consider two possible style configs for a box:

var styles =  {
  box: {backgroundColor: 'yellow', height: '100px', width: '200px'},
  boxA: {backgroundColor: 'blue'},
};

So we want all our boxes to have default 'box' styles, but want to overwrite some with a different color:

// this will be yellow
<div style={styles.box}></div>

// this will be blue
<div style={Object.assign(styles.box, styles.boxA)}></div>

// this SHOULD be yellow, but it's blue.
<div style={styles.box}></div>

Once Object.assign() executes, the 'styles.box' object is changed for good.

The solution is to pass an empty object to Object.assign(). In so doing, you're telling the method to produce a NEW object with the objects you pass it. Like so:

// this will be yellow
<div style={styles.box}></div>

// this will be blue
<div style={Object.assign({}, styles.box, styles.boxA)}></div>

// a beautiful yellow
<div style={styles.box}></div>

This notion of objects mutating in-place is critical for React, and proper use of Object.assign() is really helpful for using libraries like Redux.

Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
Brandon
  • 7,736
  • 9
  • 47
  • 72
  • 2
    Your example of how to misuse Object.assign is not a valid representation of how Object.assign is being used in the (currently) top answer. – qel Jun 08 '16 at 18:56
  • thanks, made edits to reflect which aspect is (currently) a misuse – Brandon Jun 08 '16 at 23:13
  • 1
    nice piece of code right there. Object.assign({}, this.state.showStartOverBtn ? {} : this.hidden ,this.btnStyle)} conditionals also work like a charm – steveinatorx Nov 04 '16 at 01:11
27

Array notaion is the best way of combining styles in react native.

This shows how to combine 2 Style objects,

<Text style={[styles.base, styles.background]} >Test </Text>

this shows how to combine Style object and property,

<Text style={[styles.base, {color: 'red'}]} >Test </Text>

This will work on any react native application.

26
    const style1 = {
        backgroundColor: "#2196F3", 
    }
    
    const style2 = {
        color: "white", 
    }

    const someComponent = () => {
        return <div style={{ ...style1, ...style2 }}>This has 2 separate styles</div> 
    }
    

Note the double curly brackets. The spread operator is your friend.

jasonleonhard
  • 12,047
  • 89
  • 66
  • 6
    Should absolutely be accepted as the correct answer. Life saver! – Rob Hern Oct 23 '20 at 15:03
  • 1
    I agree with @RobHern. This should be the accepted answer, which also allows adding other inline styles, like: style={{...styles.title, color: backgroundDark ? "#fff" : "#000"}} – Serdar Feb 24 '21 at 14:48
22

Actually, there is a formal way to combine and it is like below:

<View style={[style01, style02]} />

But, there is a small issue, if one of them is passed by the parent component and it was created by a combined formal way we have a big problem:

// The passing style02 from props: [parentStyle01, parentStyle02]

// Now:
<View style={[style01, [parentStyle01, parentStyle02]]} />

And this last line causes to have UI bug, surly, React Native cannot deal with a deep array inside an array. So I create my helper function:

import { StyleSheet } from 'react-native';

const styleJoiner = (...arg) => StyleSheet.flatten(arg);

By using my styleJoiner anywhere you can combine any type of style and combine styles. even undefined or other useless types don't cause to break the styling.

AmerllicA
  • 29,059
  • 15
  • 130
  • 154
13

You can also combine classes with inline styling like this:

<View style={[className, {paddingTop: 25}]}>
  <Text>Some Text</Text>
</View>
Gil Perez
  • 853
  • 10
  • 13
  • No, you cant do that. What is say here is Reactjs (note react native), not understand why have it such upvote – Mahefa Mar 19 '21 at 11:39
8

Need to merge the properties in object. For Example,

const boxStyle = {
  width : "50px",
  height : "50px"
};
const redBackground = {
  ...boxStyle,
  background: "red",
};
const blueBackground = {
  ...boxStyle,
  background: "blue",
}




 <div style={redBackground}></div>
 <div style={blueBackground}></div>
Narayanan
  • 197
  • 1
  • 2
  • 10
7

I've found that this works best for me. It overrides as expected.

return <View style={{...styles.local, ...styles.fromProps}} />
Adrian Bartholomew
  • 2,506
  • 6
  • 29
  • 37
5

You can use compose

 const styles = StyleSheet.create({
        divStyle :{
          color: 'white',
          backgroundImage: 'url(' + imgUrl + ')',
          WebkitTransition: 'all', // note the capital 'W' here
          msTransition: 'all' // 'ms' is the only lowercase vendor prefix
        },
        divStyle2 :{fontSize: '18px'}
    })
        
        React.render(<div style={StyleSheet.compose(styles.divStyle, styles.divStyle2)}>Hello World!</div>, mountNode);

OR

 React.render(<div style={[styles.divStyle, styles.divStyle2]}>Hello World!</div>, mountNode);
Avinash
  • 879
  • 2
  • 14
  • 26
  • 1
    This was the solution that worked for me. The accepted solution did not work. On Expo 44 + ReactNative 0.64.3. – Justin Schier Jan 19 '22 at 22:03
  • Stylesheet compose didn't work for me on react native. Passing styles as array worked brilliantly. – Reez0 Feb 22 '22 at 13:33
2

For ones that looking this solution in React, If you want to use the spread operator inside style, you should use: babel-plugin-transform-object-rest-spread.

Install it by npm module and configure your .babelrc as such:

{
  "presets": ["env", "react"],
  "plugins": ["transform-object-rest-spread"]
}

Then you can use like...

const sizing = { width: 200, height: 200 }
 <div
   className="dragon-avatar-image-background"
   style={{ backgroundColor: blue, ...sizing }}
  />

More info: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/

Phoenix
  • 437
  • 3
  • 6
  • 15
2

To add multiple styles inline in react js, you can do like this

<div style={{...styles.cardBody,...{flex:2}}}>
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • using spread is operator is right approach , if you are in ES6. This is the right Answer. Also a good example for combining styles classes and in-line style method – niran Dec 08 '22 at 14:13
1

So basically I'm looking at this in the wrong way. From what I see, this is not a React specific question, more of a JavaScript question in how do I combine two JavaScript objects together (without clobbering similarly named properties).

In this StackOverflow answer it explains it. How can I merge properties of two JavaScript objects dynamically?

In jQuery I can use the extend method.

Community
  • 1
  • 1
PythonIsGreat
  • 7,529
  • 7
  • 21
  • 26
1

To Expand on what @PythonIsGreat said, I create a global function that will do it for me:

var css = function(){
    var args = $.merge([true, {}], Array.prototype.splice.call(arguments, 0));
    return $.extend.apply(null, args);
}

This deeply extends the objects into a new object and allows for a variable number of objects as parameters. This allows you to do something like this:

return(
<div style={css(styles.base, styles.first, styles.second,...)} ></div>
);

var styles = {
  base:{
    //whatever
  },
  first:{
    //whatever
  },
  second:{
    //whatever
  }
}
timthez
  • 174
  • 1
  • 8
1

To take this one even further, you could create a classnames-like helper function:

const styleRules = (...rules) => {
  return rules.filter(Boolean).reduce((result, rule) => {
    return { ...result, ...rule };
  }, {});
};

And then use it conditionally in your components:

<div style={

  styleRules(
    divStyle,
    (window.innerWidth >= 768) && divStyleMd,
    (window.innerWidth < 768) && divStyleSm
  )

}>Hello World!</div>
n1stre
  • 5,856
  • 4
  • 20
  • 41
1

Ways of inline styling:

<View style={[styles.red, {fontSize: 25}]}>
  <Text>Hello World</Text>
</View>

<View style={[styles.red, styles.blue]}>
  <Text>Hello World</Text>
</View>

  <View style={{fontSize:10,marginTop:10}}>
  <Text>Hello World</Text>
</View>
him
  • 3,325
  • 3
  • 14
  • 17
  • 3
    React doesn't support array from the beginning and now it doesn't work anymore. – witoong623 May 15 '19 at 00:43
  • the above comment is correct, this answer only works in React Native. it is possible to do something similar - like so, which React does support. – humans Nov 04 '20 at 19:16
0

I have built an module for this if you want to add styles based on a condition like this:

multipleStyles(styles.icon, { [styles.iconRed]: true })

https://www.npmjs.com/package/react-native-multiple-styles

-5

To have multiple Inline styles in React.

<div onClick={eleTemplate} style={{'width': '50%', textAlign: 'center'}}/>
  • 1
    In which way is this provide a multiple style? – Mahefa Mar 19 '21 at 11:44
  • The style accepts an object within curly braces, so you can have all your styles as a single object and assign it to one variable as below. const combinedStyles = {'width': '50%', textAlign: 'center'}
    – MANISH PARGANIHA May 27 '21 at 08:08