Created
June 14, 2019 16:03
-
-
Save rynbyjn/ca05be5e4f95e04acfc1d902fe9782db to your computer and use it in GitHub Desktop.
A stylis.js plugin to convert pixel values to rem values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on the [postcss-pxtorem plugin](https://github.com/cuth/postcss-pxtorem) | |
const minPixelValue = 4 | |
export const ROOT_VALUE = 16 | |
const unitPrecision = 5 | |
// See https://github.com/cuth/postcss-pxtorem/blob/master/lib/pixel-unit-regex.js | |
const pxRegExp = /"[^"]+"|'[^']+'|url\([^)]+\)|(\d*\.?\d+)px/gi | |
// Not an exhaustive list but should cover most use cases: | |
// https://developer.mozilla.org/en-US/docs/Web/CSS/Reference | |
const blacklist = [ | |
'column-count', | |
'columnCount', | |
'counter-increment', | |
'counter-reset', | |
'counterIncrement', | |
'counterReset', | |
'flex', | |
'flex-grow', | |
'flex-order', | |
'flex-shrink', | |
'flexGrow', | |
'flexOrder', | |
'flexShrink', | |
'font-weight', | |
'fontWeight', | |
'opacity', | |
'order', | |
'stroke-miterlimit', | |
'stroke-width', | |
'strokeMiterlimit', | |
'strokeWidth', | |
'z-index', | |
'zIndex', | |
] | |
const isNumberPropBlacklisted = prop => | |
blacklist.some(property => property === prop) | |
const isValueInRange = value => Math.abs(value) > minPixelValue | |
const toFixed = (num, precision) => { | |
const multiplier = 10 ** (precision + 1) | |
const wholeNumber = Math.floor(num * multiplier) | |
return (Math.round(wholeNumber / 10) * 10) / multiplier | |
} | |
const toRem = value => { | |
const fixed = toFixed(Number(value) / ROOT_VALUE, unitPrecision) | |
return fixed === 0 ? '0' : `${fixed}rem` | |
} | |
const pixelReplace = () => (pxValue, numValue) => { | |
if (!numValue) { | |
return pxValue | |
} | |
if (!isValueInRange(numValue)) { | |
return pxValue | |
} | |
return toRem(numValue) | |
} | |
export default (context, content) => { | |
if (context !== 1) { | |
return | |
} | |
const newStyleArr = content.split(':') | |
const pxReplace = pixelReplace() | |
const prop = newStyleArr[0] | |
const value = newStyleArr[1] | |
const numValue = Number(value) | |
if ( | |
!isNaN(numValue) && | |
isValueInRange(numValue) && | |
!isNumberPropBlacklisted(prop) | |
) { | |
newStyleArr[1] = toRem(numValue) | |
} else if (typeof value === 'string' && value.includes('px')) { | |
newStyleArr[1] = value.replace(pxRegExp, pxReplace) | |
} | |
return newStyleArr.join(':') | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment