Search code examples
cssoptimizationsasscss-selectorsbreakpoints

Address the same group of CSS selectors on each breakpoint. How to keep the CSS DRY?


I've been writing CSS (SASS) for several years now and would say that I'm quite proficient at it. However, I can't think of a good alternative for the following code.

My SASS right now, somewhat simplified for Stackoverflow:

.container {
  &.-left {
    h1, 
    h2,
    h3,
    h4,
    h5,
    h6,
    p,
    ul,
    ol {
      left: 0;
    }
  }

  &.-right {
    h1, 
    h2,
    h3,
    h4,
    h5,
    h6,
    p,
    ul,
    ol {
      right: 0;
    }
  }
}



@include breakpoint(small) {
  .container {
    &.-left {
      h1, 
      h2,
      h3,
      h4,
      h5,
      h6,
      p,
      ul,
      ol {
        left: 10px;
      }
    }

    &.-right {
      h1, 
      h2,
      h3,
      h4,
      h5,
      h6,
      p,
      ul,
      ol {
        right: 10px;
      }
    }
  }
}



@include breakpoint(medium) {
  .container {
    &.-left {
      h1, 
      h2,
      h3,
      h4,
      h5,
      h6,
      p,
      ul,
      ol {
        left: 20px;
      }
    }

    &.-right {
      h1, 
      h2,
      h3,
      h4,
      h5,
      h6,
      p,
      ul,
      ol {
        right: 20px;
      }
    }
  }
}



@include breakpoint(large) {
  .container {
    &.-left {
      h1, 
      h2,
      h3,
      h4,
      h5,
      h6,
      p,
      ul,
      ol {
        left: 30px;
      }
    }

    &.-right {
      h1, 
      h2,
      h3,
      h4,
      h5,
      h6,
      p,
      ul,
      ol {
        right: 30px;
      }
    }
  }
}

I'm not sure how, but I think that the code could be written in a more elegant way. It feels very cumbersome to list and address the same group of selectors multiple times for each breakpoint. Do you have an idea how I could shorten this code and make it more readable? I suppose with CSS variables or SASS functions?


Solution

  • 1. With a mixin

    You can use a @mixin to store the selectors and then @include it where you need:

    @mixin defaultSelectors() {
      & {
        h1, 
        h2,
        h3,
        h4,
        h5,
        h6,
        p,
        ul,
        ol {
          @content;
        }
      }
    }
    
    .container {
      &.-left {
        @include defaultSelectors {
          left: 0;
        }
      }
    
      &.-right {
        @include defaultSelectors {
          right: 0;
        }
      }
    }
    
    [...]
    

    2. With a variable

    You can also store the selectors in a variable as a list and then use interpolation:

    $defaultSelectors: h1, h2, h3, h4, h5, h6, p, ul, ol;
    
    .container {
      &.-left {
        #{$defaultSelectors} {
          left: 0;
        }
      }
    
      &.-right {
        #{$defaultSelectors} {
          right: 0;
        }
      }
    }
    
    [...]