Awesome
React Inline Style
- About
- Features
- Basic Usage
- Style Definition
- Style Application
- Inheritance
- Namespaces / Nesting Styles
- Global Styles
- Conditionals / :pseudo classes
- Extend Style Classes
- API
- License
About
Inline styles are great for distributed react components via npm or just reusable components in general. Having everything you need to run the component requirable within javascript improves its usability greatly. Having to look for an external css file in the node_modules folder sucks.
However using inline styles, we quickly run into multiple problems. The main one being the missing possibility to adjust styles from outside the component but also the missing pseudo classes (mainly :hover) and media queries can sometimes be really handy and are duly missed. And while these last two can be substituted with javascript, there are situations where global css is needed (think: HTML API responses, 3rd party plugins etc).
There is a lot of discussion going on about these problems and the missing modularity of css in general. <br> Check out @Vjeux on CSS in JS as a good starting point.
React Inline Style focuses on reusable, self contained components, that dont require any external css file but are still adaptable and styleable by their owner / end user / developer.
Features
React Inline Style provides a practical solution for the following problems:
- Define ALL styles in JavaScript within the component/module.
- Owner component can influence/override its child components styles.
- Define global css rules and media-queries also from within a component.
- Easy substitution for conditional class definitions like :hover and :pressed.
What React Inline Style does not provide:
- Export styles into global stylesheet.
Basic Usage
React Inline Style is used as react mixin
. <br>
Styles can be defined with the define()
methods and are applied through the style property with the this.style()
method.
var React = require("react");
var Style = require("react-inline-style");
Style = Style.define({ // <-- make sure to redefine Style with the output of Style.define()
textComponent : {
fontWeight:"bold",
fontStyle:"italic"
}
});
var TextComponent = React.createClass({
mixins : [Style()], // <-- make sure to include the mixin
click : function(){
this.style.define({
textComponent : {
fontStyle:"normal",
letterSpacing:"2px"
}
});
this.forceUpdate();
},
render : function (){
return (
<p
style={this.style("textComponent")}
onClick = {this.click}>
textComponent
</p>
);
}
});
React.render(<TextComponent />, document.body);
Style Definition
Styles can be defined on a module-level
or the instance-level
of the component.
var React = require("react");
var Style = require("react-inline-style");
Style = Style.define({...}); // <-- module-level
React.createClass({
mixins : [Style()],
render : function (){
this.style.define({...}); // <-- instance-level
[...]
}
});
Styles defined on module-level
will apply to all instances of the component (Think: Static styles)
while instance-level
styles only apply to the current instance/placement (Think: Dynamic styles).
Both define()
methods take the same parameters. See API: Style.define(); for more info.
Style Application
Styles are applied through the style
property with the this.style()
method.
this.style()
takes either "class names" whos definitions can be modified and overridden by parent/owner components, or style definitions as object literals. The later cant be overridden from the outside.
Styles passed to this.style()
are applied/override each other in the order they were passed in.
var React = require("react");
var Style = require("react-inline-style");
Style = Style.define({
myStyle : {
fontWeight:"bold",
color:"blue"
}
});
React.createClass({
mixins : [Style()],
render : function (){
return (<p style={this.style("myStyle", {color:"red"})}>textComponent</p>);
}
});
Inheritance
Defined styles are passed down the component tree and override its child components style definitions. This makes it possible to adjust and influence components without changing their code.
The inheritance also works through RandomComponent
s that do neither use nor include the react-inline-style mixin.
var React = require("react");
var Style = require("react-inline-style");
var TextComponent = require("./TextComponent"); // See definition in "Basic Usage".
var RandomComponent = require("RandomComponent"); // This can be any component.
Style = Style.define({
textComponent : {
color : "red"
}
});
var RootComponent = React.createClass({
mixins : [Style()],
render : function (){
return (
<RandomComponent>
<TextComponent \>
</RandomComponent>
);
}
});
React.render(<RootComponent />, document.body);
Namespaces / Nesting Styles
Namespacing is super useful and even necessary when using modular css.
There are two ways of namespacing a component with React Inline Style:
Namespaceing from inside a component
Within your component you can nest your style definitions in order to create namespaces:
Style.define({
myNamespace : {
textComponent : {
color :"red"
}
}
});
// available through
this.style("myNamespace.textComponent")
And namespaces can also be passed in as the first parameter:
Style.define("myNamespace.textComponent", {
color :"red"
});
// also available through
this.style("myNamespace.textComponent")
styleNamespace Property (Namespacing from outside a component)
When using multiple components within one parent component, namespace collisions can happen and styles can't be defined for a particular component alone.
To prevent this you can use the property styleNamespace
to define a namespace for this component instance from the ouside:
var React = require("react");
var Style = require("react-inline-style");
var TextComponent = require("./TextComponent"); // See definition in "Basic Usage".
Style = Style.define({
first : {
textComponent : {
color : "red"
}
},
second : {
textComponent : {
color : "blue"
}
}
});
var RootComponent = React.createClass({
mixins : [Style()],
render : function (){
return (
<TextComponent styleNamespace = "first" \>
<TextComponent styleNamespace = "second" \>
);
}
});
React.render(<RootComponent />, document.body);
Global Styles
In some situations global styles are necessary (3rd party html) in others they are useful or improve performance (media queries).
React inline style provides the possibility to define global styles from within a component through Style.global()
. Style definitions passed to Style.global()
are transformed to normal css definitions and are added to the document <head>
.
Style.global({
".example" : {
color : "red",
"p, a" : {
fontWeight:"bold"
}
},
"@media (max-width: 600px)":{
".example" : {
color:"blue"
}
}
});
// Becomes in <head />
<style id="mgy3joepeffuhaor" class="react-inline-style global-css">
.example {
color:"red";
}
.example p {
font-weight:bold;
}
.example a {
font-weight:bold;
}
@media (max-width: 600px) {
.example {
color:"blue";
}
}
</style>
Style.global()
only exists on module-level
. Although it can be updated at any time on instance-level
. these styles are global and affect all instances.
Conditionals / :pseudo classes
Using inline styles, :pseudo classes are not available. However they can be substitued easily with react's this.state
.
Doing so, often requires tests like this.state.hover && "hoverStyle"
to apply hoverStyle
only if this.state.hover
is actually true
.
React Inline Style makes this easier by reintroducing :pseudo classes. When applying a style class through this.style()
, you can add any pseudo :variableName
to it. Doing so results in a check for this.state.variableName
and the styles are only applied if it returned true
:
"hoverStyle:hover" === this.state.hover && "hoverStyle"
"hoverStyle:myState" === this.state.myState && "hoverStyle"
Also the two most common :pseudo classes :hover and :pressed are already implemented for you. Just use them and all the required event handlers will be attached once their needed and removed when their not. (Still no solution for :focus though)
Extend Style Classes
Style definitions can _extend
other styles.
Style.define({
defaults : {
myStyle : {
color:"blue",
fontWeight: "bold"
}
},
myStyle : {
_extend:"defaults.myStyle",
color:"red"
}
});
this.style("myStyle")
now results in:
{ color:"red", fontWeight:"bold" };
API
React Inline Style is a React mixin. Make sure to include it into your component:
Style = require("react-inline-style");
React.createClass({
mixins : [Style()],
...
});
Style.define( [ namespace, ] styles);
RETURNS function
: New Style
instance.<br>
Defines styles on module-level
namespace optional
TYPE
string
/array
Onle or multiple namespaces to encapsulate this definition
["namespace", "another.namespace"] or "namespace, another.namespace"
styles required
TYPE
object
Style definitions
{ styleClass : { color: "red", backgroundColor:"red", nestedStyle : { fontWeight: "bold" } }, anotherStyle: { _extend : "styleClass.nestedStyle", color: "purple" } }
See Style Definition for more info.
Style.global( [ namespace, ] styles);
RETURNS function
: New Style
instance.<br>
Defines global styles that will be placed in <head>
namespace optional
TYPE
string
/array
Onle or multiple namespaces to encapsulate this definition
[".namespace", ".another .namespace"] or ".namespace, .another .namespace"
styles required
TYPE
object
Style definitions:
{ ".styleClass" : { color: "red", backgroundColor:"red", ... ".nestedStyle" : { fontWeight: "bold" } }, ".anotherStyle": { color: "purple" } }
See Global Styles for more info.
this.style([ styleClass, ][ styleDefinition, ][ styleGroup, ]);
RETURNS object
: Style definition.<br>
Takes any number of parameters/styles and combines them to one valid style definition that can be passed to the style property. <br>
Style definitions override each other in the order they were passed into the function.
styleClass optional
TYPE
string
StyleClass string.
"myStyle" "namespace.myStyle" "namespace.myStyle:hover" "myStyle:conditional"
styleDefinition optional
TYPE
object
Style definitions
{ color: "red", backgroundColor: "white", fontWeight: "bold", fontStyle: "italic", }
styleGroup optional
TYPE
array
A collection of
styleClasses
,styleDefinitions
andstyleGroups
[ "myStyle", "namespace.myStyle:hover", {color:"red"} ]
See Style Application for more info.
this.style.define( [ namespace, ] styles);
RETURNS null
<br>
Defines styles on instance-level
namespace optional
TYPE
string
/array
Onle or multiple namespaces to encapsulate this definition
["namespace", "another.namespace"] or "namespace, another.namespace"
styles required
TYPE
object
Style definitions
{ styleClass : { color: "red", backgroundColor:"red", nestedStyle : { fontWeight: "bold" } }, anotherStyle: { _extend : "styleClass.nestedStyle", color: "purple" } }
See Style Definition for more info.
this.style.log();
RETURNS null
<br>
Logs the current "virtual stylesheet" and namespace into the console
License
License: MIT
Released in 2015 by Philipp Adrian @ Dow Jones