Radium

One of the first libraries that was created to solve the problems of inline styles we encountered in the previous section is Radium. It is maintained by the great developers at Formidable Labs, and it is still one of the most popular solutions.

In this section, we will look at how Radium works, which problems it solves, and why it is a great library to use in conjunction with React for styling components.

We are going to create a very simple button, similar to the one we built in the example earlier in this chapter.

We will start with a basic button without styling, and we will add some basic styling, as well as pseudo-classes and media queries so that we can learn about the main features of the library.

The button we will start with is created as follows:

  const Button = () => <button>Click me!</button>;

First, we have to install Radium using npm:

  npm install --save radium

Once the installation is complete, we can import the library and wrap the button into it:

  import radium from 'radium';

const Button = () => <button>Click me!</button>;

export default radium(Button);

The radium function is an HoC (see Chapter 4Compose All the Things), which extends the functionalities of our Button, returning a new enhanced component.

If we render the button inside the browser, we will not see anything in particular at the moment, because we are not applying any styles to it.

Let's start with a simple style object, where we set the background color, the padding, the size, and a couple of other CSS properties.

As we saw in the previous section, inline styles in React are defined using JavaScript objects with camelCased CSS properties:

  const styles = { 
backgroundColor: '#ff0000',
width: 320,
padding: 20,
borderRadius: 5,
border: 'none',
outline: 'none'
};

The preceding snippet is no different from plain inline styles with React, and if we pass it to our button as follows, we can see all the styles applied to the button inside the browser:

  const Button = () => <button style={styles}>Click me!</button>;

The result is the following markup:

<button data-radium="true" style="background-color: rgb(255, 0, 0); width: 320px; padding: 20px; border-radius: 5px; border: none; outline: none;">Click me!</button>

The only difference you can see here is that there is a data-radium attribute set to true attached to the element.

Now, we have seen that inline styles do not let us define any pseudo-classes; let's take a look at how to solve the problem using Radium.

Using pseudo-classes, such as :hover, with Radium is pretty straightforward.

We have to create a :hover property inside our style object, and Radium will do the rest:

  const styles = { 
backgroundColor: '#ff0000',
width: 320,
padding: 20,
borderRadius: 5,
border: 'none',
outline: 'none',
':hover': {
color: '#fff'
}
};

If you apply this style object to your button and render it on the screen, you can see that passing the mouse over the button results in a button with white text, as opposed to the default black one.

That is great—we can use pseudo-classes and inline styles together.

However, if you open your DevTools and try to force the :hover status in the Styles panel, you will see that nothing happens.

The reason you can see the hover effect but you cannot simulate it with CSS is that Radium uses JavaScript to apply and remove the hover state defined in the style object.

If you hover over the element with the DevTools open, you can see that the style string changes and the color gets added to it dynamically:

<button data-radium="true" style="background-color: rgb(255, 0, 0); width: 320px; padding: 20px; border-radius: 5px; border: none; outline: none; color: rgb(255, 255, 255);">Click me!</button> 

The way Radium works is by adding an event handler for each one of the events that can trigger the behavior of pseudo-classes and listening to them.

As soon as one of the events gets fired, Radium changes the state of the component, which re-renders with the right style for the state. This might seem weird in the beginning, but there are no real downsides to this approach, and the difference regarding performance is not perceivable.

We can add new pseudo-classes, for example, :active, and they will work as well:

  const styles = { 
backgroundColor: '#ff0000',
width: 320,
padding: 20,
borderRadius: 5,
border: 'none',
outline: 'none',
':hover': {
color: '#fff'
},
':active': {
position: 'relative',
top: 2
}
};

Another critical feature that Radium enables is media queries. Media queries are crucial for creating responsive applications, and Radium again uses JavaScript to enable that CSS feature in our application.

Let's look at how it works—the API is pretty similar; we have to create a new attribute on our style object and nest the styles that must be applied when the media query matches inside it:

  const styles = { 
backgroundColor: '#ff0000',
width: 320,
padding: 20,
borderRadius: 5,
border: 'none',
outline: 'none',
':hover': {
color: '#fff'
},
':active': {
position: 'relative',
top: 2
},
'@media (max-width: 480px)': {
width: 160
}
};

There is one thing we must do to make media queries work, and that is wrapping our application into the StyleRoot component provided by Radium.

For the media queries to work properly, especially with server-side rendering, Radium will inject the rules related to the media query in a style element inside the DOM, with all the properties set as !important.

This is to avoid flickering between the different styles that are applied to the document before the library figures out which is the matching query. Implementing the styles inside a style element prevents this by letting the browser do its regular job.

So, the idea is to import the StyleRoot component:

  import { StyleRoot } from 'radium';

Then, we can wrap our entire application inside it:

  class App extends Component { 
render() {
return (
<StyleRoot>
...
</StyleRoot>
)
}
}

As a result of this, if you open the DevTools, you can see that Radium injected the following style into the DOM:

<style>@media (max-width: 480px) { .rmq-1d8d7428{width: 160px !important;}}</style>

The rmq-1d8d7428 class has been applied to the button automatically, as well:

<button class="rmq-1d8d7428" data-radium="true" style="background-color: rgb(255, 0, 0); width: 320px; padding: 20px; border-radius: 5px; border: none; outline: none;">Click me!</button>

If you now resize the browser window, you can see that the button becomes smaller for small screens, as expected.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.23.130