BEMed Components

Reusing CSS#

Whenever possible you should use the components for CSS reuse.

But sometimes one just needs share bits of common CSS between components and BEMed embraces the nature of CSS for that with CSS selectors. So do not create JavaScript variables with bits of CSS code and stick them to the template literals.

Eg. this is bad

// XXX Bad code!
const rounded = `
border-radius: 10px;
`;
const ButtonList = bemed({
name: "ButtonList",
css: css`
flex-direction: column;
`,
elements: {
Save: bemed({
as: "button",
css: css`
${rounded} /* XXX Bad code! */
color: green;
`,
}),
Cancel: bemed({
as: "button",
css: css`
${rounded} /* XXX Bad code! */
color: red;
`,
}),
},
});

It will not work with the Babel precompiler option and will duplicate styles sent over the network when server-rendering critical CSS.

Scoped CSS Selectors#

Slightly better way to do this is to use the scoped CSS selectors

const ButtonList = bemed({
name: "ButtonList",
css: css`
flex-direction: column;
button {
border-radius: 10px;
}
`,
elements: {
// ...
},
});

But this is bit broad as it will match any buttons passed as the <ButtonList> children.

We can use class names to be more specific

const ButtonList = bemed({
css: css`
flex-direction: column;
.rounded {
border-radius: 10px;
}
`,
elements: {
Save: bemed({
as: "button",
className: "rounded",
css: css`
color: green;
`,
}),
Cancel: bemed({
as: "button",
className: "rounded",
css: css`
color: red;
`,
}),
},
})("ButtonList");

Custom Element Selectors#

BEMed also defines custom CSS selectors using the CSS Extensions specification for child elements

const ButtonList = bemed({
name: "ButtonList",
css: css`
flex-direction: column;
:--Save,
:--Cancel {
border-radius: 10px;
}
`,
// ...
});

This will correspond with following CSS

.ButtonList__Save,
.ButtonList__Cancel {
border-radius: 10px;
}

The selectors are implemented within the CSS compiler so they will work in all browsers.

CSS Utility Classes#

If you need to share CSS between different BEMed blocks you can just use standalone CSS classes you have defined in some external stylesheet.

Multiple classes can be defined with arrays

const Button = bemed({
as: "button",
className: ["rounded", "button-font"],
css: css`
color: green;
`,
});

However a createClassName() helper is provided

import { createClassName } from "react-bemed/css";
const Rounded = createClassName(
"rounded",
css`
border-radius: 10px;
`,
);
const Button = bemed({
as: "button",
className: Rounded,
css: css`
color: green;
`,
});

There are two benefits to using this helper as opposed to external classes.

    TypeScript and ESLint will catch the error if you make a typo with variable name

    Because BEMed creates these styles it can skip injecting them completely when doing critical CSS server-side rendering if they are not used in the initial render

Edit on Github