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 @navbarCollapseWidthsince 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