When working on a responsive site, you'll often find yourself modifying a single class to change the layout at a specific breakpoint (i.e. adding extra padding or margin, changing the colour or font size etc.).

This is fine but isn't scalable or particular efficient when using a modular naming strategy like BEM or SMACSS.

The BEMIT Solution

BEMIT tries to solve the challenge by adding another type of modifier. By using the @ symbol in a classname, you can specifiy at which breakpoint the class is applied.

The @ is a human readable and logical way of denoting conditional states. It allows developers to learn about any potential permutations or appearances that the piece of UI in question might have, just at a glance.

While semantically this makes sense, the downside is that you need to escape the @ in the CSS: .u-hidden\@tablet {}. And that just doesn't seem like a good solution; especically when trying to generate the classes using a mixin.

Instead something like .u-hidden---MQmobile seems like a better fit with the BEM strategy. Of course you can replace the media query extension with whatever you feel comfortable with; ---ATalpha, ---BP_large etc.

Generate all the things

It's possible to use these classes and keep your stylesheets maintainable by generating them using SASS.

  // The key can be whatever you like
// You just need to pass it in to rwd mixin
$breakpoints: (
  mobile: max-width 47.9375em,
  tablet: 48em,
  hd: 62em
);

@mixin rwd( $names: () ) {
  @content;

  @each $name in $names {
    @each $bp in $breakpoints {
      @if nth($bp,1) == $name {
        // Edit before the #{} to change the class extension
        &---MQ#{nth($bp, 1)} {
          @include media( nth($bp, 2) ) {
            @content;
          }
        } 
      }
    }
  }
}

.black {
  @include rwd( mobile tablet hd ) {
    color: white;
    background: black;
  }
}

The result

The mixin iterates over the classnames passed in and compares them to the keys in the $breakpoints map. When there's a match it produces a class using the key as the name of the class and the value is passed into the media mixin.

Just in case you want to use the class across all breakpoints, the mixin outputs the original @content without scoping it to a media query.

Caveat

The only caveat to this approach is that now you can't simply use a $mobile variable in the media mixin, you have to use map-get on $breakpoints.

There are workarounds:

Create a helper function that gets the parameter from the $breakpoints map (and you can give it a really short name for convenience).

  @function bp( $bp ) {
  @return map-get( $breakpoints, $bp );
}

.blue {
  @include media ( bp(mobile) ) {
    background: blue;
    color: white;
  }
}

Create a variable and assign a map-get to the desired map key.

  $mobile: map-get( $breakpoints, mobile );

.red {
  @include media ( $mobile ) {
    background: red;
    color: white;
  }
}

I have made this available on Bower and NPM

Further reading:


1,995 0 14