react-native-styl
react-native-styl is a micro-library for React Native developers whose goal is to write stylesheets with a non-opinionated library, free of dependencies, and in the easiest way possible.
import styl from 'react-native-styl'
import { Text } from 'react-native'
const Title = styl(Text)({ color: 'blue' })
const App = () => <Title>Styl</Title>
Motivation
-
Keep the stylesheet simple: the recommended approach to writing stylesheets in React Native still needs too much boilerplate and it's a pain to maintain; styl provides a simple API where you'll be able to write the same stylesheets you are used to – with fewer lines of code;
-
Performance: no magic or tricks here, styl just maps the stylesheet (which can come from inline-style, the function argument or even props) to the style prop in the component: one of the most performative ways to write styles in React Native;
-
Versatility: styl uses the context API to bring full theme support, which can be used throughout the application; components can also be easily extended and styled overrided when needed;
-
Ultralightweight: about 1kb.
Usage
To get started using react-native-styl
, first install the package:
yarn add react-native-styl
or npm i react-native-styl
Styling native elements:
Styl is a high-order function that receives any component that supports the style
prop, and returns a function that expects a plain object stylesheet. It will return a styled React component with the same props of the original component:
import styl from "react-native-styl"
import { ScrollView } from "react-native"
const Wrapper = styl(ScrollView)({
padding: 16
})
<Wrapper indicatorStyle="black">
<View />
</Wrapper>
Dynamic styles:
Easily create dynamic stylesheets. Use a callback function to access the component props
when creating the styles:
import styl from "react-native-styl"
import { Text } from "react-native"
const ColoredText = styl(Text)(({ props }) => ({
color: props.color,
}))
<ColoredText color="red">Lorem ipsum</ColoredText>
Theming:
Wrap your application with the Provider and every component will also have access to the theme
in the callback function:
import { styl, Provider as StyleProvider } from "react-native-styl"
import { Text } from "react-native"
const Theme = ({ children }) => (
<StyleProvider theme={{ primary: 'blue' }}>
{children}
</StyleProvider>
)
const ThemeColorText = styl(Text)(({ theme }) => ({
color: theme.primary
}))
<ThemeColorText>Lorem ipsum</ThemeColorText>
useTheme:
The useTheme
hook let you access the currently active theme.
import { useTheme, Provider as StyleProvider } from 'react-native-styl'
const Main = ({ children }) => {
const theme = useTheme()
return <Text style={{ color: theme.brand }}>Foo</Text>
}
const App = () => {
return (
<StyleProvider theme={{ color: { brand: 'blue' } }}>
<Main />
</StyleProvider>
)
}
Extends:
Given that styl accepts any component that supports the style
prop, every component created by the library can be styled again. It will inherit the original component style that can be extended:
import styl from "react-native-styl"
import { Text } from "react-native"
const BaseText = styl(Text)({
color: 'red',
padding: 16,
})
const ExtendedText = styl(BaseText)({
color: 'green',
})
<ExtendedText>Lorem ipsum</ExtendedText>
Polymorphic elements: `as` prop
Render a new styled component passing a valid React component to as
prop:
import styl from "react-native-styl"
import { Text, TouchableOpacity } from "react-native"
const Base = styl(Text)({
padding: 16
})
<Base as={TouchableOpacity} onPress={() => null}>
<Text>TouchableOpacity</Text>
</Base>
Presets components:
The first argument of react-native-styl
accepts any valid React component. This means it's possible to pass a custom function component:
import styl from "react-native-styl"
import { Text } from "react-native"
const PresetComp = styl((props) => (
<Text ellipsizeMode="tail" numberOfLines={1} {...props} />
))({ padding: 16 })
<PresetComp>Lorem ipsum</PresetComp>
TypeScript:
react-native-styl
fully supports TypeScript for both theme definitions and custom props.
Theme definition:
The first step is to create a declarations file (e.g.: theme.d.ts
), with the following content:
// import original module declarations
import 'react-native-styl'
// and extend it
declare module 'react-native-styl' {
export interface DefaultTheme {
colors: {
main: string
secondary: string
}
}
}
Custom props:
Define the component props and pass it to the main function:
import styl from "react-native-styl"
import { Text } from "react-native"
interface TitleProps {
color: string
}
const Title = styl(Text)<TitleProps>(({ props }) => ({
color: props.color,
}))
<Title color="blue">Lorem ipsum</Title>
as
prop
Typescript is not yet supported Help is needed to implement it.
Styled-API-like:
Create a custom library to suit your own goals:
import styl from 'react-native-styl'
import * as RN from 'react-native'
const UI = {
View: styl(RN.View),
Text: styl(RN.Text),
}
const Title = UI.Text({ color: 'red' })
More examples in examples/src
.
Benchmark
Internal tests rendering 5k views and 10k views into a Scrollview, styl shows to be one of the most performative ways to write stylesheets in React Native, losing only to the native approaches. The results below are the average of 5 complete renders measured in milliseconds:
Library | Rendering 5k Views | Rendering 10k Views |
---|---|---|
StyleSheet | 2068ms | 4095ms |
Inline-style | 2317ms | 4507ms |
react-native-styl | 2754ms | 5432ms |
Styled-components | 3102ms | 6460ms |
See the tests in
examples/src