Skip to content

Instantly share code, notes, and snippets.

@threepointone
Last active September 14, 2017 18:54
Show Gist options
  • Save threepointone/9846ad2b2bc889decff399be8cce3121 to your computer and use it in GitHub Desktop.
Save threepointone/9846ad2b2bc889decff399be8cce3121 to your computer and use it in GitHub Desktop.
rulegroup

Something about css-in-js libs I noticed, but no one really talks about. There exists an implicit idea of a grouped-ruleset, ie - a set of rulesets that apply either directly to an element, or are meant to be composed with other rulesets. an example with 2 libs -

// glamor

const button = css({
  color: 'red',
  ':hover': {
    color: 'blue'
  },
  '.active': {
    color: 'green'
  }
})


// SC

const Button = styled.button`
  color: red;
  &:hover {
    color: blue
  }
  &.active {
    color: green
  }
`

What would the equivalent be in 'pure css' options like css modules / BEM / sass / less / etc? You could make a classname that implies it, like so -

.button {
  color: red;
}
.button:hover {
  color: blue
}
.button.active {
  color: green
}

but this is just a convention, and a brittle one. further it's not amenable to further analysis/composition (what really is the difference between .button and .active?)

What would you call this abstraction? a rulegroup?

This is what the cssinjs gang really refers to when they say 'no more classnames' I think; that there's no classname they worry about when grouping styles, the computer handles it, and makes it easy to use for further composition.

Something to think about.

@geelen
Copy link

geelen commented Sep 13, 2017

I call this sort of thing a "trait". Composition in CSS Modules was an attempt to bring this kind of thinking to the forefront, but it's too inflexible as implemented there.

But you're right, you often get multiple declarations, some pseudos, etc, all in one logical item. I particularly like this one:

const horizontalFill = css`
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  padding: 1rem;
  > * {
    flex-grow: 1;
    :not(:first-child) {
      margin-left: 1rem;
    }
  }
`

const verticalStack = css`
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1rem;
  > *:not(:first-child) {
    margin-top: 1rem;
  }
`

const Menu = styled.nav`
  @media (max-width: 599px) {
    ${ verticalStack }
  }
  @media (min-width: 600px) {
    ${ horizontalFill }
  }
`

To me, a lot of styling behaviour is better captured at this "trait" level rather than having to use a full component for everything...

@oliverturner
Copy link

The binding is a little more explicit with BEM in pure CSS: a rulegroup would be

.button {
  color: #ccc;
}

.button--active {
  color: #fff;
}

Granted, the brittleness is still there because the connection is incidental (i.e. subject to typos, etc), but the linkage is a little more obvious than a random .active tacked on to a class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment