Skip to content

Instantly share code, notes, and snippets.

@RobinMalfait
Last active November 16, 2017 16:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobinMalfait/4a40c5fe1b20e54d08a37029a3c53ee5 to your computer and use it in GitHub Desktop.
Save RobinMalfait/4a40c5fe1b20e54d08a37029a3c53ee5 to your computer and use it in GitHub Desktop.
Brilliant or bananas: deterministic classNames
  1. Determenistic classNames
  2. No context switching, the styles are in the same file as the component
  3. Allows for easy deletability (if that's a word), in pure CSS files you can have the problem that you don't (always) know if you can uberhaupt delete the css or not
  4. We still allow for nested styles like:
import { Button } from './Button';
const Accordion = styled.div`
  // We don't need to know which class `.Button` uses, in pure css we _do_ need to know which one
  ${Button} {
    border: none;
  }
`
  1. We can do variables/theming (okay we can use scss/sass/less, but that's an extra step as well)
import theme from './theme';
const Button = styled.div`
  color: ${theme.color};
`
  1. We can apply some magic with props
const Button = styled.button('Button')`
  background-color: transparent;

  disabled {
    background-color: grey;
  }
`

// <Button disabled /> -> <button class="Button Button--disabled"></button>
// <Button /> -> <button class="Button"></button>
  1. We only have to think about "single" names for BEM (Blocks, Elements, Modifiers)
  • We have seen in our codebases that the naming conventions was different throughout the months/years, now we kind of force the BEM structure implicitely
  1. We don't allow for hacks, or styling tags directly, we need to define a className  - "hacks" might be a bit strange here, but out of lasyness we've seen styled css directly on tags and nested children div > * which is not that great for specifity.
  2. The generated css tries to be the lowest specifity, because we need the ability to override it later (if that makes sense somehow, more context maybe be required)

Styled components with deterministic classNames

Use case: we want to use the ease of development of styled components, but we're building a library instead of an isolated app. That's why we need predictable, deterministic classNames. The generated classnames are inspired by BEM.

const Button = styled.button('Button')`
  background-color: transparent;
  border: 1px solid black;
  border-radius: 2px;
  padding: .5em 1em;

  /** If there is a prop named disabled, and it is truthy */
  disabled {
    background-color: grey;
  }
`

IN

<Button disabled />

OUT

<button class="Button Button--disabled"></button>

IN

<Button />

OUT

<button class="Button"></button>

Modifications

const SmallButton = Button.modify('small')`
  padding: 1px 2px;
`

IN

<SmallButton disabled />

OUT

<button class="Button Button--small Button--disabled"></button>

IN

<SmallButton />

OUT

<button class="Button Button--small"></button>

Nested Elements

const ButtonIcon = Button.i('Icon')`
  font-family: FontAwesome;
`

IN

<Button>
  <ButtonIcon />
</Button>

OUT

<button class="Button">
  <i class="Button__Icon"></i>
</button>

With predefined contents

const IconButton = Button
  .withContents(Root => ({ icon, children, ...rest }) => (
    <Root {...rest}>
      <ButtonIcon className={`fa-${icon}`} />
      {children}
    </Root>
  ))``

IN

<IconButton icon="house">
  My House
</IconButton>

OUT

<button class="Button">
  <i class="Button__Icon fa-house"></i>
  My House
</button>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment