(inline)Styling React
Contents
React inline style
MSS and Virtual CSS
Radium & others
React inline styles
var divStyle = {
color: 'magenta',
height: 200,
width: 300,
textAlign: 'center',
display: 'table-cell',
backgroundColor: 'pink',
verticalAlign: 'middle',
WebkitTransition: 'all', // note the capital 'W' here
msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};
ReactDOM.render(<div style={divStyle}>React inline styles</div>,
document.getElementById('container'));
React inline styles
class MyNotification extends React.Component {
render() {
// Clone the CSS styles and set the border-color CSS property.
var styles = _.cloneDeep(this.constructor.styles);
styles.notification.borderColor = this.props.color;
return (
<div style={styles.notification}>
{this.props.prompt}
<span style={styles.notificationHint}>{this.props.hint} />
</div>);
}
}
// Define the inline CSS styles for the notification here.
MyNotification.styles = {
notification: {
border: "5px solid green",
padding: 10, // Becomes "10px" when rendered.
color: "#333"
},
notificationHint: {
fontStyle: "italic"
}
};
React.render(
<MyNotification prompt="I ♥ modular CSS.", hint="And so should you!" color="green"/>,
document.querySelector('#app-root'));
React inline styles
Problems:
CSS pseudo classes and media queries are not supported
Break existing developer tools
Creating CSS files for deployment is not that easy
React inline styles
class MyNotification extends React.Component {
render() {
return (
<div className="notification">
<style>
@media (min-width: 600px) {
.notification {
padding: 15px;
}
}
.notification {
border: 1px solid ${this.props.color};
padding: 10px;
color: #333;
}
/* Use nested CSS selectors - because we can! */
.notification span {
font-style: italic;
}
</style>
{this.props.prompt}
<span>{this.props.hint}</span>
</div>);
}
}
Does not work because in JSX everything between {...} is interpreted as JavaScript
React inline styles
Problems:
The selectors are not modular
Global CSS namespace
MSS and VirtualCSS
class MyNotification extends React.CSSComponent {
render() {
var styleMap = this.mountStyles`
@media (min-width: 600px) {
.notification {
padding: 15px;
}
}
.notification {
border: 10px solid ${this.props.color};
padding: 10px;
color: #333;
}
/* ".notification span" is rejected by ModularCSS as it
* contains a nested CSS selectors. Therefore, need to
* use a new class name instead. */
.notification-hint {
font-style: italic;
}`;
return (
<div className={styleMap.notification}>
{this.props.prompt}
<span className={styleMap.notificationHint}>
{this.props.hint}
</span>
</div>);
}
}
MSS and VirtualCSS
<style>
@media (min-width: 600px) {
.notification_12 {
padding: 15px;
}
}
.notification_12 {
border: 1px solid green;
padding: 10px;
color: #333;
}
.notification-hint_12 {
font-style: italic;
}
</style>
var styleMap = {
notification: 'notification_12',
notificationHint: 'notification-hint_12'
}
Resulting CSS
Resulting style object (mapp classes)
MSS and VirtualCSS
<style>
/* Result from mountCSS with this.props.colour="green" */
@media (min-width: 600px) {
.notification_12 {
padding: 15px;
}
}
.notification_12 {
border: 1px solid green;
padding: 10px;
color: #333;
}
.notification-hint_12 {
font-style: italic;
}
/* Result from mountCSS with this.props.colour="red" */
@media (min-width: 600px) {
.notification_42 {
padding: 15px;
}
}
.notification_42 {
border: 1px solid red;
padding: 10px;
color: #333;
}
.notification-hint_42 {
font-style: italic;
}
</style>
MSS and VirtualCSS
<style>
/* Common styles for the colour="green" and colour="red"
* MyNotification container */
@media (min-width: 600px) {
.notification_12_42_common {
padding: 15px;
}
}
.notification_12_42_common {
border: 1px solid auto;
padding: 10px;
color: #333;
}
.notification-hint_12_42_common {
font-style: italic;
}
/* Specialised styles for the MyNotification container */
.notification_12 { border-color: green; }
.notification_42 { border-color: red; }
</style>
MSS and VirtualCSS
// For the case of <MyNotification ... color="green">:
var styleMap = {
notification: 'notification_12_42_common notification_12',
notificationHint: '.notification-hint_12_42_common'
}
// For <MyNotification ... color="green" />
.notification_12 { border-color: green; }
// For <MyNotification ... color="red" />
.notification_42 { border-color: red; }
// For <MyNotification ... color="xyz" />
[A lot of other classes to cover all possible colors go here.]
MSS and VirtualCSS
var styleMap = {
// NOTE: The .notification_12 class name is gone. Instead the
// border color as defined in .notification_12 is now inlined
// on the style object.
notification: {
style: { borderColor: 'green' }, // For inline styles
className: 'notification_12_42_common' // For class names
},
notificationHint: {
style: { },
className: 'notification-hint_12_42_common'
}
}
var StyleSheet = require('react-style')
var styles = StyleSheet.create({
foo: {
color: 'red',
backgroundColor: 'white'
}
})
React style
var React = require('react')
class HelloWorld extends React.Component{
render() {
var dynamicStyles = {color: this.props.color}
return <div styles={[styles.foo, dynamicStyles]}>Hello, world!</div>
}
}
same syntax as React Native StyleSheet
Notice that the property is styles, not style
var styles = StyleSheet.create`
.foo {
color: red;
background-color: white;
}
`
React style
var styles = StyleSheet.create({
foo: {
color: 'red',
backgroundColor: 'white'
}
})
which translates to:
React style
Problems:
No CSS selectors, pseudo-classes and CSS animation
Does not support React 0.14 :(
inline styles...
import StyleSheet from 'react-style';
const styles = StyleSheet.create({
primary: {
background: 'green'
},
warning: {
background: 'yellow'
},
button: {
padding: '1em'
},
// media queries
'@media (max-width: 200px)': {
button: {
width: '100%'
}
}
});
...
<button styles={[styles.button, styles.primary]}>Confirm</button>
React Inline
class ConfirmButton extends React.Component {
render() {
const {className} = this.props;
const classes = cx(styles.button, styles.primary, className);
return <button className={classes}>Confirm</button>;
}
}
React Inline
var {Block, Flex, InlineBlock, rgb} = require('jsxstyle');
var Theme = require('./MyTheme');
var hovered = false; // This could be dynamic
var avatar = (
<Flex
width={Theme.GRID_UNIT * 10}
marginLeft="auto"
marginRight="auto"
alignItems="center">
<img src="..." />
<Block marginLeft={Theme.GRID_UNIT}
color={Theme.primaryColor}
background={hovered && rgb(255, 0, 0)}>
<InlineBlock fontWeight="bold">Username here</InlineBlock>
subtitle here
</Block>
</Flex>
);
jsxstyle
Problems:
No CSS selectors, pseudo-classes and CSS animation, etc.
jsxstyle
.Avatar_1 {
/* display flex + style properties defined 8?
}
.Avatar_2 {
/* display block + style properties defined 8?
}
.Avatar_3 {
/* display inline-block + style properties defined 8?
}
External CSS - webpack loader
Radium
var Radium = require('radium');
var React = require('react');
var color = require('color');
@Radium
class Button extends React.Component {
static propTypes = {
kind: React.PropTypes.oneOf(['primary', 'warning']).isRequired
};
render() {
return (
<button
style={[
styles.base,
styles[this.props.kind]
]}>
{this.props.children}
</button>
);
}
}
@Radium decorator
Radium
// You can create your style objects dynamically or share them for
// every instance of the component.
var styles = {
base: {
color: '#fff',
// Adding interactive state couldn't be easier! Add a special key to your
// style object (:hover, :focus, :active, or @media) with the additional rules.
':hover': {
background: color('#0074d9').lighten(0.2).hexString()
}
},
primary: {
background: '#0074D9'
},
warning: {
background: '#FF4136'
}
};
Radium
<Button size="large" block={true}>
Cool Button!
</Button>
var styles = {
base: {
background: 'blue',
border: 0,
borderRadius: 4,
color: 'white',
padding: '1.5em'
},
block: {
display: 'block'
}
};
Modifiers
// Inside render
return (
<button
style={[
styles.base,
this.props.block && styles.block
]}>
{this.props.children}
</button>
);
Radium
Other stuff:
Comparison:
(inline) styling React
By Andrei Antal
(inline) styling React
- 1,644