Skip to content

Instantly share code, notes, and snippets.

@jakob-e
Last active October 26, 2022 17:20
Show Gist options
  • Save jakob-e/6579770 to your computer and use it in GitHub Desktop.
Save jakob-e/6579770 to your computer and use it in GitHub Desktop.
SCSS unit conversion functions
// ==========================================================
// Unit Conversion
// ==========================================================
//
// Functions:
// ----------------------------------------------------------
//
// NUMBER:
//
// isNaN($value) - returns true or false if type-of($value)==number
//
// number($value) - returns a unitless number.
//
// int($value) - returns a unitless integer.
//
// uint($value) - returns a unitless unsigned integer.
//
//
// UNITS:
//
// px($value) - converts a number or unit to px.
//
// em($args...) - converts a number or unit to em.
//
// To adjust for em compounds you can add
// aditional arguments to calculate the
// visual em size. em(visual-size,....)
//
// Example: em(2, 2em, 2em) => 0.5em
//
// rem($value) - converts a number or unit to rem.
//
// pt($value) - converts a number or unit to pt.
//
// pc($value) - converts a number or unit to pc.
//
// in($value) - converts a number or unit to in.
//
// cm($value) - converts a number or unit to cm.
//
//
// PERCENTAGE:
//
// pct($value,$base:100) - similar to precentage, but takes a base
// value (100%) to be used for calculating
// the precent value returned
//
// Example: pct(1,100) => 1%
// pct(1,1) => 100%
// pct(50,250) => 20%
// pct(10px,16px) => 62.5%
// pct(1em,16px) => 100%
//
// ANGLE:
//
// deg($value) - converts a number or angle unit to deg.
//
// grad($value) - converts a number or angle unit to grad.
//
// turn($value) - converts a number or angle unit to turn.
//
// rad($value) - converts a number or angle unit to rad.
//
//
// CONVERT:
//
// Allows conversion by based on unit parameter
//
// $unit:px !default;
// convert($unit,2em) - converts 2ems to pixels.
//
// ==========================================================
// Unit Conversion Table
// http://www.translatorscafe.com/cafe/units-converter/typography/
// 1px = 0.0625pc;
// 1px = 0.75pt;
// 1px = 0.010416667in;
// 1px = 0.264583333mm;
// 1px = 0.026458333cm;
//
// Angles
// http://www.w3.org/TR/css3-values/#angles
// Full circle = 360deg = 400grad = 1turn = 2πrad
// 1deg = 1.111111111grad (400/360)
// 1deg = 0.002777778turn (1/360)
// 1deg = 0.017453293rad (180/π)
//
// ==========================================================
// Base font size in percent (http://pxtoem.com/)
// - used when calculating em and rem
$base-font-scale:100% !default;
// Number
@function isNaN($val) { @return type-of($val)!=number; }
@function number($val){ @return if(isNaN($val), null, if(unitless($val), $val, $val/($val*0+1))); }
@function int($val){
@if(isNaN($val)){ @return null; }
$val:number($val);
@return if($val<0,ceil($val),floor($val));
}
@function uint($val){ @return if(isNaN($val), null, abs(int($val))); }
// Aliases
@function num($val){ @return number($val); }
@function parseFloat($val) { @return number($val);} // Really a math thing
@function parseInt($val) { @return int($val); } // Really a math thing
// Absolute lengths
@function px($val){ @return unit-handler($val,0px); }
@function pt($val){ @return unit-handler($val,0pt); }
@function pc($val){ @return unit-handler($val,0pc); }
@function in($val){ @return unit-handler($val,0in); }
@function mm($val){ @return unit-handler($val,0mm); }
@function cm($val){ @return unit-handler($val,0cm); }
// Relative lengths using px as base
@function rem($val) { @return 0rem + if(unitless($val), $val, number(px($val)) * 0.0625 * 100% / $base-font-scale); }
@function em($args...){
$val:nth($args,1);
$em:0em + if(unitless($val), $val, number(px($val)) * 0.0625 * 100% / $base-font-scale);
@for $i from 2 through length($args){ $em:$em / number(em(nth($args,$i))) }
@return $em;
}
// Percent
@function pct($val,$base:1){ @return if(isNaN($val), null, percentage(number(px($val))/number(px($base)))); }
// Length unit handler
@function unit-handler($val,$unit){
@if($val==null or type-of($val)!=number){ @return null; }
$u:unit($val);
@if($u==rem or $u==em){ @return 0px + number($val) / 0.0625 * 100% / $base-font-scale }
@return $unit + $val;
}
// Angle conversion using deg as base
@function deg($val){
@if(isNaN($val)){@return null;}
$u:unit($val);
$u:if($u==deg ,1,
if($u==grad,1.111111111,
if($u==turn,0.002777778,
if($u==rad, 0.017453293,
1))));
@return number($val) / $u * 1deg;
}
@function grad($val){ @return if(isNaN($val),null,if(unitless($val),$val * 1grad,number(deg($val)) * 1.11111111grad)); }
@function turn($val){ @return if(isNaN($val),null,if(unitless($val),$val * 1turn,number(deg($val)) * 0.002777778turn)); }
@function rad($val) { @return if(isNaN($val),null,if(unitless($val),$val * 1rad ,number(deg($val)) * 0.017453293rad)); }
// Convert using unit parameter
@function convert($unit,$args...){
@if($unit==number){ @return number($args...); }
@if($unit==num) { @return num($args...); }
@if($unit==int) { @return int($args...); }
@if($unit==uint){ @return uint($args...);}
@if($unit==px) { @return px($args...); }
@if($unit==pt) { @return pt($args...); }
@if($unit==pc) { @return pc($args...); }
@if($unit==in) { @return in($args...); }
@if($unit==mm) { @return mm($args...); }
@if($unit==cm) { @return cm($args...); }
@if($unit==em) { @return em($args...); }
@if($unit==rem) { @return rem($args...); }
@if($unit==pct) { @return pct($args...); }
@if($unit==deg) { @return int($args...); }
@if($unit==grad){ @return grad($args...);}
@if($unit==turn){ @return turn($args...);}
@if($unit==rad) { @return rad($args...); }
}
@KittyGiraudel
Copy link

Waw, nice job. I'll definitely have a closer look to this when I get a chance. :)

@jakob-e
Copy link
Author

jakob-e commented Sep 16, 2013

Added

isNaN instead of null check
pct($value, $base:100) - base used as 100% to calculate the percentage eg. pct(50, 250) => 20%
$base-font-scale:100% !default - to allow other than 16px based em+rem values

$base-font-scale:62.5%;  // or pct(10px,16px); 
html {
    font-size:$base-font-scale;
}

body {
    font-size: 16px;        /* Fallback for IE8 */
    font-size: rem(16px);
    padding: 20px 10px;     /* Fallback for IE8 */
    padding: rem(20px) rem(10px);
}


// Output 
html { font-size: 62.5%; }
body { 
    font-size: 16px;        /* Fallback for IE8 */ 
    font-size: 1.6rem; 
    padding: 20px 10px;     /* Fallback for IE8 */ 
    padding: 2rem 1rem;  
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment