← Snippets - Styles

Rem-Calc Updates (BS2/BS3 Only)

On older BS3 and BS2 sites, we didn’t have a way to convert pixels to rem smoothly, so we had to use other methods. If you come across a site that either needs this or needs updates to it, here is how it works.

Bootstrap 3

To convert, you can put rem-calc(0px) around whatever pixel size it is.

You can also do it for shorthand, like margin: rem-calc(10px 0 30px)

You can also do negatives, like margin-top: rem-calc(-2px)

You can also put it around media queries. @media (min-width: rem-calc($screen-xs))

Ignore stuff with backslashes, those are escapes for IE.

For addition/subtraction, you can just include it in the rem-calc. rem-calc(30px + 1)

Don’t put it around line-height-computed, it won’t work.

Don’t worry about most of the mixin files, BUT you will need to edit things in _grid-framework.scss and _grid.scss to get the grid width/margins into rems

Styles

scaffolding.scss

Add font-size: 100% to the html declaration as shown.

html {
  font-size: 100%;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
}

Mixins folder

Create a new sass file called _relative-size.scss, and add it to the scss > bootstrap > mixins folder.

$rem-base: 16px !default;


// STRIP UNIT
// It strips the unit of measure and returns it
@function strip-unit($num) {
  @return $num / ($num * 0 + 1);
}

// CONVERT TO REM
@function convert-to-rem($value, $base-value: $rem-base) {
  $value: strip-unit($value) / strip-unit($base-value) * 1rem;
  @if ($value == 0rem) { $value: 0; } // Turn 0rem into 0
  @return $value;
}

@function rem-calc($values, $base-value: $rem-base) {
  $max: length($values);

  @if $max == 1 { @return convert-to-rem(nth($values, 1), $base-value); }

  $remValues: ();
  @for $i from 1 through $max {
    $remValues: append($remValues, convert-to-rem(nth($values, $i), $base-value));
  }
  @return $remValues;
}


@function em-calc($values, $base-value: $rem-base) {
  $remValues: rem-calc($values, $base-value: $rem-base);

  $max: length($remValues);

  @if $max == 1 { @return strip-unit(nth($remValues, 1)) * 1em; }

  $emValues: ();
  @for $i from 1 through $max {
    $emValues: append($emValues, strip-unit(nth($remValues, $i)) * 1em);
  }
  @return $emValues;
}

Example Sites

Bootstrap 2

Rem conversion function is different. Place the remixins.less file on the same level as style.less, directly within the less folder.

// ===== REM UNIT MIXINS ====
@base-font-size-px: 16; // root's font size. @base-font-size-px MUST BE AN INTEGER.


@pxtorem-js-function: ~`pxtorem = function(px){ if (typeof rmxsBaseFontSize == 'undefined')  rmxsBaseFontSize = @{base-font-size-px}; return (parseInt(px.replace(/(^\d+)(.+$)/i,'$1')) / rmxsBaseFontSize + 'rem') }`;

// .rem-calc(@value) {
//     @rem-value: ~`pxtorem('@{value}')`; 
// }

// .rem-calc(@x) {
//   @remVal: ((@x) / 16rem);
// }
// ===== FONT MIXINS =====
.font-size(@value) {
    font-size: @value;
}

.font-size(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    font-size: @rem-value;
}

.line-height(@value) {
    line-height: @value;
}

.line-height(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    line-height: @rem-value;
}

.text-indent(@value) {
    text-indent: @value;
}

.text-indent(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    text-indent: @rem-value;
}


// ===== MARGIN MIXINS =====
.margin(@value) {
    margin: @value;
}

.margin(@vvalue, @hvalue) {
    margin: @arguments;
}

.margin(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    margin: @rem-value;
}

.margin(@vertical, @horizontal) when (ispixel(@vertical)) and (ispixel(@horizontal)) {
    @rem-vvalue: ~`pxtorem('@{vertical}')`;
    @rem-hvalue: ~`pxtorem('@{horizontal}')`;
    margin: @rem-vvalue @rem-hvalue;
}
// 3 Arguments
.margin(@tvalue, @svalue, @bvalue) when (ispixel(@tvalue)) and (ispixel(@svalue)) and (ispixel(@bvalue)) {
    @rem-tvalue: ~`pxtorem('@{tvalue}')`;
    @rem-svalue: ~`pxtorem('@{svalue}')`;
    @rem-bvalue: ~`pxtorem('@{bvalue}')`;
    margin: @rem-tvalue @rem-svalue @rem-bvalue;
}

// 4 Arguments
.margin(@tvalue, @rvalue, @bvalue, @lvalue) when (ispixel(@tvalue)) and (ispixel(@rvalue)) and (ispixel(@bvalue)) and (ispixel(@lvalue)) {
    @rem-tvalue: ~`pxtorem('@{tvalue}')`;
    @rem-rvalue: ~`pxtorem('@{rvalue}')`;
    @rem-bvalue: ~`pxtorem('@{bvalue}')`;
    @rem-lvalue: ~`pxtorem('@{lvalue}')`;
    margin: @rem-tvalue @rem-rvalue @rem-bvalue @rem-lvalue;
}


.margin(@vertical, @horizontal) when (ispixel(@vertical)) {
    @rem-value: ~`pxtorem('@{vertical}')`;
    .margin(@rem-value, @horizontal);
}

.margin(@vertical, @horizontal) when (ispixel(@horizontal)) {
    @rem-value: ~`pxtorem('@{horizontal}')`;
    .margin(@vertical, @rem-value);
}

.margin-top(@value) {
    margin-top: @value;
}

.margin-top(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    margin-top: @rem-value;
}

.margin-right(@value) {
    margin-right: @value;
}

.margin-right(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    margin-right: @rem-value;
}

.margin-bottom(@value) {
    margin-bottom: @value;
}

.margin-bottom(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    margin-bottom: @rem-value;
}

.margin-left(@value) {
    margin-left: @value;
}

.margin-left(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    margin-left: @rem-value;
}


// ===== PADDING MIXINS =====
.padding(@value) {
    padding: @value;
}

.padding(@vvalue, @hvalue) {
    padding: @arguments;
}

// 3 arguments
.padding(@tvalue, @svalue, @bvalue) when (ispixel(@tvalue)) and (ispixel(@svalue)) and (ispixel(@bvalue)) {
    @rem-tvalue: ~`pxtorem('@{tvalue}')`;
    @rem-svalue: ~`pxtorem('@{svalue}')`;
    @rem-bvalue: ~`pxtorem('@{bvalue}')`;
    padding: @rem-tvalue @rem-svalue @rem-bvalue;
}

// 4 arguments
.padding(@tvalue, @rvalue, @bvalue, @lvalue) when (ispixel(@tvalue)) and (ispixel(@rvalue)) and (ispixel(@bvalue)) and (ispixel(@lvalue)) {
    @rem-tvalue: ~`pxtorem('@{tvalue}')`;
    @rem-rvalue: ~`pxtorem('@{rvalue}')`;
    @rem-bvalue: ~`pxtorem('@{bvalue}')`;
    @rem-lvalue: ~`pxtorem('@{lvalue}')`;
    padding: @rem-tvalue @rem-rvalue @rem-bvalue @rem-lvalue;
}


.padding(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    padding: @rem-value;
}

.padding(@vertical, @horizontal) when (ispixel(@vertical)) and (ispixel(@horizontal)) {
    @rem-vvalue: ~`pxtorem('@{vertical}')`;
    @rem-hvalue: ~`pxtorem('@{horizontal}')`;
    padding: @rem-vvalue @rem-hvalue;
}

.padding(@vertical, @horizontal) when (ispixel(@vertical)) {
    @rem-value: ~`pxtorem('@{vertical}')`;
    .padding(@rem-value, @horizontal);
}

.padding(@vertical, @horizontal) when (ispixel(@horizontal)) {
    @rem-value: ~`pxtorem('@{horizontal}')`;
    .padding(@vertical, @rem-value);
}

.padding-top(@value) {
    padding-top: @value;
}

.padding-top(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    padding-top: @rem-value;
}

.padding-right(@value) {
    padding-right: @value;
}

.padding-right(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    padding-right: @rem-value;
}

.padding-bottom(@value) {
    padding-bottom: @value;
}

.padding-bottom(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    padding-bottom: @rem-value;
}

.padding-left(@value) {
    padding-left: @value;
}

.padding-left(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    padding-left: @rem-value;
}


// ===== POSITION MIXINS =====
.height(@value) {
    height: @value;
}

.height(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    height: @rem-value;
}

.min-height(@value) {
    min-height: @value;
}

.min-height(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    min-height: @rem-value;
}

.max-height(@value) {
    max-height: @value;
}

.max-height(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    max-height: @rem-value;
}


.width(@value) {
    width: @value;
}

.width(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    width: @rem-value;
}

.min-width(@value) {
    min-width: @value;
}

.min-width(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    min-width: @rem-value;
}

.max-width(@value) {
    max-width: @value;
}

.max-width(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    max-width: @rem-value;
}

.top(@value) {
    top: @value;
}

.top(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    top: @rem-value;
}

.left(@value) {
    left: @value;
}

.left(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    left: @rem-value;
}

.right(@value) {
    right: @value;
}

.right(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    right: @rem-value;
}

.bottom(@value) {
    bottom: @value;
}

.bottom(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    bottom: @rem-value;
}


// ===== BORDER MIXINS =====
.border(@value, @color) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    border: @rem-value solid @color;
}
.border-bottom(@value, @color) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    border-bottom: @rem-value solid @color;
}

.border-left(@value, @color) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    border-left: @rem-value solid @color;
}

.border-right(@value, @color) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    border-right: @rem-value solid @color;
}

.border-top(@value, @color) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    border-top: @rem-value solid @color;
}

.border-radius-rem(@value) when (ispixel(@value)) {
    @rem-value: ~`pxtorem('@{value}')`;
    border-radius: @rem-value;
}
.border-radius-rem(@tvalue, @rvalue, @bvalue, @lvalue) when (ispixel(@tvalue)) and (ispixel(@rvalue)) and (ispixel(@bvalue)) and (ispixel(@lvalue)) {
    @rem-tvalue: ~`pxtorem('@{tvalue}')`;
    @rem-rvalue: ~`pxtorem('@{rvalue}')`;
    @rem-bvalue: ~`pxtorem('@{bvalue}')`;
    @rem-lvalue: ~`pxtorem('@{lvalue}')`;
    border-radius: @rem-tvalue @rem-rvalue @rem-bvalue @rem-lvalue;
}



// ===== BACKGROUND MIXINS =====
.background-size(@wvalue, @hvalue) when (ispixel(@wvalue)) and (ispixel(@hvalue)) {
    @rem-wvalue: ~`pxtorem('@{wvalue}')`;
    @rem-hvalue: ~`pxtorem('@{hvalue}')`;
    background-size: @rem-wvalue @rem-hvalue;
}
.background-position(@xvalue, @yvalue) when (ispixel(@xvalue)) and (ispixel(@yvalue)) {
    @rem-xvalue: ~`pxtorem('@{xvalue}')`;
    @rem-yvalue: ~`pxtorem('@{yvalue}')`;
    background-position: @rem-xvalue @rem-yvalue;
}
/*
.rem-mixins-test-class {
    .font-size(10px);
    .line-height(20px);
    .margin(10px);
    .margin(3em);
    .margin(10px, 20px);
    .margin(10px, 20%);
    .margin(0px , 20px);
    .margin-top(2%);
    .margin-top(2px);
    .padding(10px);
    .padding(3em);
    .padding(10px, 20px);
    .padding(10px, 20%);
    .padding(3em, 20px)
}
*/

You set them up like mixins. So .font-size(10px);

You can enclose variables too. .font-size(@baseFontSize);

You can also do shorthand, but it’s comma-separated. .padding(0px, 0px, 10px); or you can do .border-top(3px, #000) — it’s “solid” by default so no need to specify that.

If there’s a 0 in any of those, you have to add “px” after it for the conversion to work.

Some things need to have the rems put straight in there.

  • All the border radius values: @baseBorderRadius, @borderRadiusLarge, @borderRadiusSmall
  • @tooltipArrowWidth
  • All the grid px values: @gridColumnWidth, @gridGutterWidth, @gridColumnWidth1200, @gridGutterWidth1200, @gridColumnWidth768, @gridGutterWidth768
  • @navbarCollapseWidth since it’s a media query
  • In the mixins.less file, line 705, there’s a line that has “- 14” in it, that 14 needs to be changed to 0.875
  • Shorthand stuff for fonts can’t be used, you have to expand it out into font size, weight, line height, etc etc
  • All media queries
  • The logo width/height if those are in variables

Tags: bs2, bs3, less, sass, rem, px, ada