DEV Community

loading...

Easily select h1, h2, ... through SCSS functions

Nir Lanka ニル
I design compilers, write mobile and web apps, make distributed apps, develop augmented reality and design. I write, paint and read. A lot. Huge Linux enthusiast. Blog: https://nirlanka.com
・1 min read

I was writing styles for formatting inside a rich-text web component.

There, due to limitations of the CMS and requirements, we wanted all h1, h2, ... h6 tags to have some similar presentations.

Also, we had selectors like this:

h1 + p, 
h2 + p, 
/*...*/
h6 + p { 
  /*...*/ 
}

Always writing selectors for all cases including all h# tags is a nightmare. It's hard to maintain, too. So I decided to look into how to fix this in the simplest way, while still complying to different use cases.

After going through forums and finding similar solutions, this is my end .scss code:

selector-helpers.scss:

/**
 *  Select any range in {h1, h2, h3, h4, h5, h6}.
 * 
 *  e.g. usage
 *    #{headings('', 1, 6, '.--attr')} { ... }
 */

@function headings($before:'', $from:1, $to:6, $after:'') {
    @if $from == $to {
        @return '#{$before} h#{$from}#{$after}';
    } @else {
        @return '#{$before} h#{$from}#{$after}, ' + headings($before, $from+1, $to, $after);
    }
}

Usage in x-rich-text.scss:

@import "./selector-helpers";

x-rich-text {

    // h1, ...
    #{headings()} {
        /* ... */
    }

    // h1:first-child, ...
    #{headings($after:':first-child')} {
        /* ... */
    }

    // h1 + p, ...
    #{headings($after:' + p')} {
        /* ... */
    }

    // h1, h2 (only)
    #{headings($from:1, $to:2)} {
        /* ... */
    }

    // img + p, ...
    #{headings($before:'img + ')} {
        /* ... */
    }

    // h1.--dark, h2.--dark, ...
    #{headings($after:'.--dark')} {
        /* ... */
    }

    // h1 code, h2 code, ...
    #{headings($after:' code')} {
        /* ... */
    }
}

I believe this can handle all cases with prefixes, suffixes and selective ranges in 1..6.

So yeah. :) Hope this helps you! Let me know if there's a better way of handling this.

Discussion (0)