Modularise CSS the React way

Status Quo for styling React Components

var React = require('react');
var _ = require('lodash');
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;
// Render the notification box.
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 &hearts; modular CSS.",
hint="And so should you!" color="green"/>,
document.querySelector('#app-root'));

Going one step back…

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>);
}
}

… and two steps forward

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>);
}
}
<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'
}

Sprinting for performance

 <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>
<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>
// For the case of <MyNotification ... color="green">:
var
styleMap = {
notification: 'notification_12_42_common notification_12',
notificationHint: '.notification-hint_12_42_common'
}

And adding inline styles to the mix again

  // 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.]
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'
}
}
class MyNotification extends React.CSSComponent {
render() {
var styleMap = this.mountStyles`... same as before ...`;

return (
<div css={styleMap.notification}>
{this.props.prompt}
<span css={styleMap.notificationHint}>
{this.props.hint}
</span>
</div>);
}
}

Final word about modularity

Summary

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store