Home > Back-end >  Loop two-level nested lists in SCSS to create a dynamic @font-face
Loop two-level nested lists in SCSS to create a dynamic @font-face

Time:04-17

I have a list like:

$fonts: (
  primary: (
    extra-light: (
      family:'Literata',
      weight: 200,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Literata-Regular.woff2'),
    ),
    light: (
      family: 'Literata',
      weight: 300,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Literata-Regular.woff2'),
    ),
    regular: (
      family: 'Literata',
      weight: 400,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Literata-Regular.woff2'),
    ),
    bold: (
      family: 'Literata',
      weight: 700,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Literata-Regular.woff2'),
    ),
  ),
  secondary: (
    light: (
      family: 'Zilla Slab',
      weight: 300,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Zilla-Slab-Regular.woff2'),
    ),
    regular: (
      family: 'Zilla Slab',
      weight: 400,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Zilla-Slab-Regular.woff2'),
    ),
    bold: (
      family: 'Zilla Slab',
      weight: 700,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Zilla-Slab-Bold.woff2'),
    ),
),
  tertiary: (
    regular: (
      family: 'Montserrat',
      weight: 400,
      style: normal,
      display: swap,
      src: url('/assets/fonts/Montserrat-Regular.woff2'),
    ),
  ),
);

My goal is to loop through each font type (primary, secondary and tertiary) and then through each variant (extra-light, light, regular, bold) of each type.

I want to build a dynamic @font-face property based on each font data.

I've tried something like this without success:

@each $font-types in $fonts {
  $properties: family weight style src;

  @each $property, $values in $font-types {
    @if contains($properties, $property) {
      @font-face {
        @if $property != 'src' {
          font-#{$property}: map-get($font-properties, $property);
        } @else{
          src: map-get($font-properties, $property) format('woff2');
        }
      }
    }
  }
}

For the record: contains is a helper function:

@function contains($list, $values...) {
  @each $value in $values {
    @if type-of(index($list, $value)) != 'number' {
      @return false;
    }
  }

  @return true;
}

CodePudding user response:

For those who might help: I ended up using the following approach:

@each $font-type, $font-variants in $fonts {
  @each $properties, $font-variant in $font-variants {
    @font-face {
      @each $property, $value in $font-variant {
        @if $property != 'src' {
          font-#{$property}: $value;
        } @else {
          #{$property}: $value format('woff2');
        }
      }
    }
  }
}

It outputs the following:

enter image description here

  • Related