typeplate/starter-kit

Unable to extend classes inside media queries

Closed this issue · 6 comments

Sometimes you want to be able to use a smaller font for a heading on a small screen and a larger on on large screens while still keeping body copy relatively stable.

Currently you are unable to @extend the classes within a new media query context.

Is there some way we can use @Mixins instead and bypass this issue?

.heading {
  @extend .alpha;
}

@media( min-width: 768px; ) {
  .heading {
    @extend .giga; // Currently not allowed
  }
}
.heading {
  @include alpha;
}

@media( min-width: 768px; ) {
  .heading {
    @include giga; // Works fine
  }
}

The only downside I can see is overriding styles from the previous media context, but I think that's ok.

I'm still mulling this over. Not sure how I feel about it just yet. Any other options or suggestions you might have besides a mixin were not thinking of still?

Hi, this is a Sass known issue @extend and placeholders don't work as expected in media-queries :
http://www.sitepoint.com/cross-media-query-extend-sass/
Hugo Giraudel point a hack to this in this article ...

in my projects i use @mixin and no hacks if possible ... and i've stop to over used placeholders.

@mistergraphx Yeah, I'm aware of the faults with Sass extends. I'm just talking out loud to figure out any other options we're not thinking of ATM.

The only way I have got this to work in an acceptable way for me is to use SASS maps.

The implementation is a different as I have taken the core principles and created my own typography kit.

$scale: (
  tera: 91,
  giga: 72,
  mega: 60,
  alpha: 48,
  bravo: 40,
  charlie: 32,
  delta: 24,
  echo: 21,
  foxtrot: 18,
  golf: 14,
  hotel: 12
);
h1 {
  @extend .charlie;

  @media( min-width: 768px; ) {
    font-size: rem( map-get($scale, mega) );
  }
}

Where rem() is a simple conversion utility.

This doesn't account for margins or line-height and I could be completely wrong but hey, call it a work-in-progress.

Hopefully this might spark some ideas for a way forward; some kind of reusable utility that's used in the initial creation of the classes but also can be called independently.

@craigmdennis
I really like the path you're on. Code below is pretty close to what I might integrate into the starter kit. It is the progress I have currently for the namespacing branch. Demo http://codepen.io/grayghostvisuals/full/33b5ba511ab59981b83e34261b9d9bce

$typl8-serif-boolean: true !default;
$typl8-custom-font: false !default;
$typl8-font-family: if($typl8-serif-boolean, serif, sans-serif) !default;
$typl8-font-weight: normal !default;
$typl8-line-height: 1.65 !default;
$typl8-font-size: 112.5 !default;
$typl8-font-base: 16 * ($typl8-font-size/100) !default;
$typl8-measure: $typl8-font-base * $typl8-line-height;
$typl8-prefixes: -webkit-, -moz-, -ms-, '';

// Use modularscale.com to generate a list of font-sizes
$typl8-scale: (
  tera: 91,
  giga: 72,
  mega: 60,
  alpha: 48,
  bravo: 40,
  charlie: 32,
  delta: 24,
  echo: 21,
  foxtrot: 18,
  golf: 14,
  hotel: 12
);

// Assign sizes to elements
$typl8-headings: (
  h1: mega,
  h2: alpha,
  h3: bravo,
  h4: charlie,
  h5: delta,
  h6: echo
);

$typl8-typescale-unit: rem !default;


@function context-calc($scale, $base, $value) {
    @return ($scale/$base)#{$value};
}

@function measure-margin($scale, $measure, $value) {
    $pixelValue: $measure/$scale;
    $remValue: $pixelValue * $typl8-font-base;

    @if $value == rem {
        @return $pixelValue#{$value};
    } @else if $value == em {
        @return ($remValue/$scale)#{$value};
    } @else {
        @return $remValue#{$value};
    }
}

%hN {
    text-rendering: optimizeLegibility; // voodoo to enable ligatures and kerning
    line-height: 1; // this fixes huge spaces when a heading wraps onto two lines
    margin-top: 0;
}

@mixin type-scale($scale, $base, $value, $measure:"") {
    @if $value == rem {
        font-size: $scale#{px};
        font-size: context-calc($scale, $base, $value);
    } @else if $value == em {
        font-size: context-calc($scale, $base, $value);
    } @else {
        font-size: $scale#{px};
    }

    @if $measure != "" {
        @if $value == rem {
            margin-bottom: measure-margin($scale, $measure, $value: px);
            margin-bottom: measure-margin($scale, $measure, $value);
        } @else if $value == em {
            margin-bottom: measure-margin($scale, $measure, $value: em);
        } @else {
            margin-bottom: measure-margin($scale, $measure, $value);
        }
    }
}

@mixin scale() {
  @each $name, $size in $typl8-scale {
    .#{$name} {
      @extend %hN;
      @include type-scale(
        $size,
        $typl8-font-base,
        '#{$typl8-typescale-unit}',
        $typl8-measure
      );
    }
  }
}

@mixin headings() {
  @each $h, $size in $typl8-headings {
    #{$h} {
      @extend .#{$size};
    }
  }
}


@include headings;
@include scale;


.title {
  @extend .bravo;

  @media( min-width: 768px ) {
    @include type-scale(
        map-get($typl8-scale, tera),
        $typl8-font-base,
        '#{$typl8-typescale-unit}',
        $typl8-measure
      );
  }
}

.sub-title {
  @extend .charlie;

  @media( min-width: 768px ) {
    @include type-scale(
        map-get($typl8-scale, mega),
        $typl8-font-base,
        '#{$typl8-typescale-unit}',
        $typl8-measure
      );
  }
}

This is now integrated in the namespacing branch. Thanks for the idea to use maps. Works out quite well.