Usage with React

Fela was always designed with React in mind, but is not bound to React by default.
If you want to use it with React, you should also install the official React bindings for Fela(new tab).

yarn add react-fela

Passing the Renderer

In order to style components, we first need to wrap our application with the RendererProvider component.
It leverages React's context(new tab) APIs to pass our Renderer to all child components.

App.js

import { createRenderer } from 'fela'
import { RendererProvider } from 'react-fela'
import MyApp from './MyApp'
const renderer = createRenderer()
export default () => (
<RendererProvider renderer={renderer}>
<MyApp />
</RendererProvider>
)

Styling Components

With hooks(new tab) being added to React, styling your components with Fela has never been easier.
react-fela ships the

useFela
hook which returns an object containing a
css
function.
Calling that function will render all passed styles and return the generated class names.

Button.js

import React from 'react'
import { useFela } from 'react-fela'
function Button({ children, fontSize = 16 }) {
const { css } = useFela()
return (
<button
className={css({
padding: 10,
fontSize,
color: 'darkblue',
':hover': {
color: 'blue',
},
})}>
{children}
</button>
)
}

Using Rules

Instead of passing style objects directly, you might want to extract your styles into rules.
The

css
function also accepts rules. We can pass our props to
useFela
in order to access them inside our rules.

Button.js

import React from 'react'
import { useFela } from 'react-fela'
const rule = ({ fontSize }) => ({
padding: 10,
fontSize,
color: 'darkblue',
':hover': {
color: 'blue',
},
})
function Button({ children, fontSize = 16 }) {
const { css } = useFela({ fontSize })
return <button className={css(rule)}>{children}</button>
}

Composition

The

css
function does not only take a single argument, but can take an array of style objects and rules.
They are merged using
combineRules
thus the order of arguments matters.

Button.js

import React from 'react'
import { useFela } from 'react-fela'
const baseStyle = ({ fontSize }) => ({
padding: 10,
fontSize: 16,
})
const hoverStyle = {
color: 'darkblue',
':hover': {
color: 'blue',
},
}
function Button({ children, fontSize = 16, extend }) {
const { css } = useFela({ fontSize })
return (
<button className={css([baseStyle, hoverStyle, extend])}>{children}</button>
)
}
// extending the Button styles for a more specific big button
const BigButton = ({ children }) => (
<Button fontSize={20} extend={{ padding: 16 }}>
{children}
</Button>
)

Fonts & Keyframes

The

useFela
hook also returns our Renderer instance, so we can use that to render fonts, keyframes and static styles directly within our components.

Tip: We can also use fela-plugin-embedded(new tab) to render fonts and keyframes from within our style object.

Button.js

import React from 'react'
import { useFela } from 'react-fela'
function Button({ children, fontSize = 16 }) {
const { css, renderer } = useFela()
// since fonts and keyframes are cached, they are only rendered once
const fontFamily = renderer.renderFont('Arial', [
'/fonts/Arial.ttf',
'/fonts/Arial.woff',
'/fonts/Arial.woff2',
])
return (
<button
className={css({
padding: 10,
fontSize,
fontFamily,
color: 'darkblue',
':hover': {
color: 'blue',
},
})}>
{children}
</button>
)
}

Theming

Passing the Theme

In order to access our theme, we need to wrap our application with the ThemeProvider component.
Similar to the

RendererProvider
it uses React's context API to pass the theme to every child component.

Tip: We can also wrap specific sub-trees with different themes e.g. if only a specific part of our application should be rendered in dark mode. Multiple nested ThemeProvider instances will automatically deep-merge the theme objects unless a

overwrite
prop is passed with
false
.

App.js

import { createRenderer } from 'fela'
import { RendererProvider, ThemeProvider } from 'react-fela'
import MyApp from './MyApp'
import theme from './theme'
const renderer = createRenderer()
export default () => (
<RendererProvider renderer={renderer}>
<ThemeProvider theme={theme}>
<MyApp />
</ThemeProvider>
</RendererProvider>
)

Using the Theme

Next to the

css
function,
useFela
also provides the current
theme
object.

Note: Rules get the theme passed automatically via

props.theme
.

Button.js

import React from 'react'
import { useFela } from 'react-fela'
function Button({ children, fontSize = 16 }) {
const { css, theme } = useFela()
return (
<button
className={css({
padding: 10,
fontSize,
color: theme.colors.blueDark,
':hover': {
color: theme.colors.blue,
},
})}>
{children}
</button>
)
}

Pre-hooks APIs

Prior to hooks, Fela shipped a couple of Higher-order and Render-props components to style React components.
While we recommend using the

useFela
hook whenever possible, they are still valid APIs and can be used interchangable.

Tips & Tricks

Presentational Components

While not required, we highly recommend to split your components into presentational and container components(new tab). Where container components manage the application logic, presentational components should only describe how your application is displayed (markup & styling). They get data passed as

props
and return a representation of your view for those props. If we strictly separate our components, we actually only use Fela for presentational components.