Import Bootstrap 4 Sass Media Breakpoints for npm webpack

September 15, 2017

There are 2 ways to do this:

  • Install bootstrap npm packages
  • Extract partial bootstrap scss

Install bootstrap npm

# https://getbootstrap.com/docs/4.0/getting-started/download/#npm
npm install bootstrap@4.0.0-beta --save-dev

Include bootstrap scss into your sass/scss files.

// avoid importing entire .scss as it might cause duplicate css styles
// @import '~bootstrap/scss/bootstrap.scss'
// safer to import variables and mixins only to avoid duplicate css styles
@import '~bootstrap/scss/_functions'
@import '~bootstrap/scss/_variables'
@import '~bootstrap/scss/mixins/_breakpoints'

// only affects xs and below
@include media-breakpoint-down(xs)
  .lua-moment-result
    margin-left: -15px
    margin-right: -15px

You have access to the following media breakpoint functions.

  • media-breakpoint-up
  • media-breakpoint-down
  • media-breakpoint-between
  • media-breakpoint-only

With the following breakpoints.

  • xs: 0
  • sm: 576px
  • md: 768px
  • lg: 992px
  • xl: 1200px

Extract partial bootstrap scss

Access the bootstrap github to extract the following files to your project’s sass/css directory.

  • scss/_functions.scss
  • scss/_variables.scss
  • scss/mixins/_breakpoints.scss

Content of scss/_functions.scss required..

// Ascending
// Used to evaluate Sass maps like our grid breakpoints.
@mixin _assert-ascending($map, $map-name) {
  $prev-key: null;
  $prev-num: null;
  @each $key, $num in $map {
    @if $prev-num == null {
      // Do nothing
    } @else if not comparable($prev-num, $num) {
      @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !";
    } @else if $prev-num >= $num {
      @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !";
    }
    $prev-key: $key;
    $prev-num: $num;
  }
}

// Starts at zero
// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.
@mixin _assert-starts-at-zero($map) {
  $values: map-values($map);
  $first-value: nth($values, 1);
  @if $first-value != 0 {
    @warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}.";
  }
}

Content of scss/_variables.scss required.

// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.

$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
) !default;
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints);

Content of scss/mixins/_breakpoints.scss required.

// FROM: mixins/_breakpoints.scss
// Breakpoint viewport sizes and media queries.
//
// Breakpoints are defined as a map of (name: minimum width), order from small to large:
//
//    (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
//
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.

// Name of the next breakpoint, or null for the last breakpoint.
//
//    >> breakpoint-next(sm)
//    md
//    >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
//    md
//    >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))
//    md
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
  $n: index($breakpoint-names, $name);
  @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
}

// Minimum breakpoint width. Null for the smallest (first) breakpoint.
//
//    >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
//    576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
  $min: map-get($breakpoints, $name);
  @return if($min != 0, $min, null);
}

// Maximum breakpoint width. Null for the largest (last) breakpoint.
// The maximum value is calculated as the minimum of the next one less 0.1.
//
//    >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
//    767px
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
  $next: breakpoint-next($name, $breakpoints);
  @return if($next, breakpoint-min($next, $breakpoints) - 1px, null);
}

// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
// Useful for making responsive utilities.
//
//    >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
//    ""  (Returns a blank string)
//    >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
//    "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
  @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}

// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider.
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($name, $breakpoints);
  @if $min {
    @media (min-width: $min) {
      @content;
    }
  } @else {
    @content;
  }
}

// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
// Makes the @content apply to the given breakpoint and narrower.
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
  $max: breakpoint-max($name, $breakpoints);
  @if $max {
    @media (max-width: $max) {
      @content;
    }
  } @else {
    @content;
  }
}

// Media that spans multiple breakpoint widths.
// Makes the @content apply between the min and max breakpoints
@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($lower, $breakpoints);
  $max: breakpoint-max($upper, $breakpoints);

  @media (min-width: $min) and (max-width: $max) {
    @content;
  }
}

// Media between the breakpoint's minimum and maximum widths.
// No minimum for the smallest breakpoint, and no maximum for the largest one.
// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($name, $breakpoints);
  $max: breakpoint-max($name, $breakpoints);

  @if $min != null and $max != null {
    @media (min-width: $min) and (max-width: $max) {
      @content;
    }
  } @else if $max == null {
    @include media-breakpoint-up($name)
  } @else if $min == null {
    @include media-breakpoint-down($name)
  }
}

Sample Usage.

@import "bootstrap/_functions"
@import "bootstrap/_variables"
@import "bootstrap/mixins/_breakpoints"

// only affects xs and below
@include media-breakpoint-down(xs)
  .lua-moment-result
    margin-left: -15px
    margin-right: -15px
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.