Creating a Repeatable Style Pattern with Sass: Placeholders vs. Mixins
One the biggest benefits of Sass its ability to create reusable blocks of code. I often use %placeholders
or @mixins
to create reusable code modules. (Here’s a great article on the difference between placeholders and mixins. My short version: use mixins when you need to pass variables and placeholders when you don’t.)
I’m working on a site now that uses the same grid pattern in multiple pages: products, services, and industries all have the same archive layout. I don’t need any variable-controlled style, so my first thought was to use a placeholder. With Sass 3.3, you can create OOCSS/BEM selectors by referencing parent selectors with &
. In previous versions, you could create nested selectors, now you can create new selectors:
Play with this gist on SassMeister.
I wondered if I could do use a %placeholder
at the top of a &
-nested set of styles, extend that top placeholder in the container selector, and let Sass generate all the new &
-selectors I need. Turns out that doesn’t work with generated selector names. (It would work just fine if my nested selectors were parent/child selectors.) See what I mean:
Play with this gist on SassMeister.
Now I could use a @mixin
to get what I want here. That would work, but it would duplicate code: each time I run the @mixin
, I’ll get the same style properties repeated in a new place in my stylesheet. I don’t want to repeat myself. I can avoid repeating myself if I comma-chain all my parent selectors and call the @mixin
just once:
Play with this gist on SassMeister.
That’s almost the DRY-est way I know to do this. If you don’t need to keep your parent selectors in separate partials, you can declare them all together and run the @mixin
on them all at once. However, if you like advanced Sass and don’t mind working extra hard, keep reading for the bonus content!
If you need to keep your parent/container selectors in separate partials, but still want to avoid repeating identical style properties, you could set an empty list variable early in your project, add parent classes to it on each individual partial where appropriate, then call the @mixin
on that list toward the end. This gist shows what I mean:
Play with this gist on SassMeister.
The final @if
loop (1) makes sure $parent-classes
isn’t empty, (2) converts all its items into a comma-separated string, and (3) calls the @mixin
on the classes that the string contains. Now none of the @mixin
code is repeated, all the parent classes can “live” in their own partials, and all the OOCSS/BEM sub-item classes are generated correctly.
Of course, this isn’t just for grid patterns: it applies to any nested styles you need repeated for elements with different class names. Leave a comment to let me know how else you might use this pattern. Or, if you see a better way to do this, share that too, thanks!
Update:
Thanks to Kitty & Stuart – Kitty posted a comment with a cleaner version that handles the parent class list in a stringier way and makes the final @if
loop unnecessary. Stuart recommended including the comma
to keep the list of classes comma-separated in the output.