Skip to main content

Using BEM names in React Native

When writing CSS classes, I prefer BEM’s naming system. The pattern is clear to read and names are easy to generate. I believe the unwieldy length of some names is offset by the benefits.

React Native doesn’t use CSS but JSON-based stylesheets that are applied directly to elements. This system has some advantages, notably co-locating concerns within the component file.

But you still have to name things within you style objects, and I find myself reaching for BEM even when removed from CSS.

For a quick overview of BEM, checkout the official documentation. The page is pretty short and summarizes the system with images. Okay, 1… 2… 3… I’m going to assume you’re familiar with BEM.

To be fair, this is perfectly valid JavaScript and works out of the box:

const styles = StyleSheet.create({
    message: {},
    'message--warning': {},
    message__text: {},
})

<View style={[ styles.message, type === 'warning' && styles['message--warning'] ]}>
    <Text style={styles.message__text}>{text}</Text>
</View>

Here I’m following the pattern from BEM of naming blocks at the top level, using underscores for elements within a block, and hyphens for modifiers. And again, this works fine.

But I really dislike using strings as properties for an object. They’re annoying to create and even worse to reference. And when we use hyphens to create modifier names, we’re stuck with styles['message--warning']. I just want to use BEM without the added discomfort of string keys. What are our alternatives?

Turns out, there aren’t many options. The underscore is taken, and most special characters are not valid in object properties. Numbers are an option, but none of them seemed to fit. The only other option on my keyboard was, perhaps surprisingly, the dollar sign: $. (Side note: Are all currency symbols valid for object properties?)

jQuery and Svelte both use the $ symbol for JavaScript, so why not here in React Native? If we swap double hyphens for double dollar signs in the previous snippet, we get:

const styles = StyleSheet.create({
    message: {},
    message$$warning: {},
    message__text: {},
})

<View style={[ styles.message, type === 'warning' && styles.message$$warning ]}>
    <Text style={styles.message__text}>{text}</Text>
</View>

Not bad. And I’d much rather use a slightly foreign symbol in a familiar system than string properties.

What do you think: good idea or bad idea? Or should I just use styled components already? Or maybe something else entirely? Let me know.

Until then, happy naming!