Login with github
Forum /

When i first started using BEM, i found it to be really refreshing at how it brings semantic meaning to our CSS. It's so easy at a glance to see what styles will applied to each state, for every block and element.

Nowadays we are all using libraries like styled-components and emotion, all of a sudden it seems like people forgot about the things we learned with BEM and SMACSS. As a result CSS-in-JS that you encounter in the wild is hard to read and reason about.

For example:

const Button = styled.button`
  /* Adapt the colors based on primary prop */
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
`;

IMO these methodologies are even more relevant in the component era, particularly with tools like React and Vue. So I had a go at trying to build a library that lets you use BEM in CSS-in-JS and maintain that precious semanticity.

Think of Trousers like styled-components + classnames + BEM, wrapped in a lovely React Hooks API ❤️. Trousers is designed to help you co-locate CSS and JS but opinionated in that it helps you avoid using JavaScript where CSS can take over. It loosely follows a BEM-like methodology, borrowing the concept of Blocks (the component), Elements (the child node you want to apply styles to) and Modifiers (apply styles when your component has particular props or state) to reduce the complexity that normally comes with CSS-in-JS.

Github Storybook

import { trousers, useTrousers } from 'trousers';

const styles = trousers('button')
    .element`
        background-color: ${theme => theme.backgroundColor};
        border: none;
        color: ${theme => theme.textColor};
        margin: 0 10px;
        padding: 10px 20px 14px 20px;

        :hover {
            background-color: ${theme => theme.hoverColor};
            color: rgba(255, 255, 255, 0.8);
        }
    `
    .modifier(props => !!props.primary)`
        background-color: #f95b5b;
        color: #ffffff;

        :hover {
            background-color: #e45454;
        }
    `;

const spanStyles = trousers('button-span')
    .element`
        font-size: 20px;
        font-style: italic;
    `;

const Button = props => {
    const buttonClassNames = useTrousers(styles, props);
    const spanClassNames = useTrousers(spanStyles, props);

    return (
        <button className={buttonClassNames}>
            <span className={spanClassNames}>
                {props.children}
            </span>
        </button>
    );
};

export default Button;

I hope it is useful to you BEM fans out there,

Thanks for reading.