diff options
author | Martijn Cuppens <martijn.cuppens@intracto.com> | 2018-01-28 01:35:36 +0300 |
---|---|---|
committer | Martijn Cuppens <martijn.cuppens@intracto.com> | 2018-01-28 01:35:36 +0300 |
commit | e30b0c141616b6df875da282c1fc056c42ff58a6 (patch) | |
tree | db435b7b039eb82861272dcba5b89a1732603037 | |
parent | 35e0b66d496864a9a3dcdf502a97b812cd557a0d (diff) |
combine all languages
-rw-r--r-- | examples/postcss/gulp/dest/main.css | 73 | ||||
-rw-r--r-- | examples/postcss/gulp/gulpfile.js | 20 | ||||
-rw-r--r-- | examples/postcss/gulp/src/main.css | 38 | ||||
-rw-r--r-- | examples/postcss/node/index.js | 24 | ||||
-rw-r--r-- | examples/postcss/node/main.css | 38 | ||||
-rw-r--r-- | examples/postcss/node/main.dest.css | 73 | ||||
-rw-r--r-- | less/rfs.less | 204 | ||||
-rw-r--r-- | package.json | 22 | ||||
-rw-r--r-- | postcss/rfs.js | 175 | ||||
-rw-r--r-- | stylus/_rfs.styl | 151 |
10 files changed, 814 insertions, 4 deletions
diff --git a/examples/postcss/gulp/dest/main.css b/examples/postcss/gulp/dest/main.css new file mode 100644 index 0000000..121ce9a --- /dev/null +++ b/examples/postcss/gulp/dest/main.css @@ -0,0 +1,73 @@ +/* responsive-font-size property with `px` unit */ +.selector-1, +.disable-responsive-font-size .selector-1, +.disable-responsive-font-size.selector-1 { + background-color: red; + width: 300px; + font-size: 2rem; +} +@media (max-width: 1200px) { + .selector-1 { + font-size: calc(1.2rem + 1.066667vw); + } +} + +/* responsive-font-size property with `rem` unit */ +.selector-2, +.disable-responsive-font-size .selector-2, +.disable-responsive-font-size.selector-2 { + font-size: 2rem; +} +@media (max-width: 1200px) { + .selector-2 { + font-size: calc(1.2rem + 1.066667vw); + } +} + +/* responsive-font-size property with !important */ +.selector-3, +.disable-responsive-font-size .selector-3, +.disable-responsive-font-size.selector-3 { + font-size: 2rem !important; +} +@media (max-width: 1200px) { + .selector-3 { + font-size: calc(1.2rem + 1.066667vw) !important; + } +} + +/* rfs shorthand */ +.selector-4, +.disable-responsive-font-size .selector-4, +.disable-responsive-font-size.selector-4 { + font-size: 2rem; +} +@media (max-width: 1200px) { + .selector-4 { + font-size: calc(1.2rem + 1.066667vw); + } +} + +/* not supported unit */ +.selector-5 { + font-size: 2em; +} + +/* special value */ +.selector-6 { + font-size: inherit; +} + +/* responsive-font-size property inside @support-query */ +@supports (display: flex) { + .selector-7, +.disable-responsive-font-size .selector-7, +.disable-responsive-font-size.selector-7 { + font-size: 1.75rem; + } + @media (max-width: 1200px) { + .selector-7 { + font-size: calc(1.15rem + 0.8vw); + } + } +} diff --git a/examples/postcss/gulp/gulpfile.js b/examples/postcss/gulp/gulpfile.js new file mode 100644 index 0000000..873a17d --- /dev/null +++ b/examples/postcss/gulp/gulpfile.js @@ -0,0 +1,20 @@ +const gulp = require('gulp'); +const postcss = require('gulp-postcss'); +const rfs = require('../..'); +const options = { + twoDimensional: false, + minimumFontSize: 16, + fontSizeUnit: 'rem', + breakpoint: 1200, + breakpointUnit: 'px', + factor: 5, + unitPrecision: 6, + remValue: 16, + propList: ['responsive-font-size', 'rfs'] +}; + +gulp.task('css', () => { + return gulp.src('./src/main.css') + .pipe(postcss([rfs(options)])) + .pipe(gulp.dest('./dest')); +}); diff --git a/examples/postcss/gulp/src/main.css b/examples/postcss/gulp/src/main.css new file mode 100644 index 0000000..ebc55d4 --- /dev/null +++ b/examples/postcss/gulp/src/main.css @@ -0,0 +1,38 @@ +/* responsive-font-size property with `px` unit */ +.selector-1 { + background-color: red; + width: 300px; + responsive-font-size: 32px; +} + +/* responsive-font-size property with `rem` unit */ +.selector-2 { + responsive-font-size: 2rem; +} + +/* responsive-font-size property with !important */ +.selector-3 { + responsive-font-size: 2rem !important; +} + +/* rfs shorthand */ +.selector-4 { + rfs: 2rem; +} + +/* not supported unit */ +.selector-5 { + responsive-font-size: 2em; +} + +/* special value */ +.selector-6 { + responsive-font-size: inherit; +} + +/* responsive-font-size property inside @support-query */ +@supports (display: flex) { + .selector-7 { + rfs: 28px; + } +} diff --git a/examples/postcss/node/index.js b/examples/postcss/node/index.js new file mode 100644 index 0000000..e0390b6 --- /dev/null +++ b/examples/postcss/node/index.js @@ -0,0 +1,24 @@ +const fs = require('fs'); +const postcss = require('postcss'); +const rfs = require('../..'); +const css = fs.readFileSync('main.css', 'utf8'); +const options = { + twoDimensional: false, + minimumFontSize: 16, + fontSizeUnit: 'rem', + // breakpoint: 1200, + breakpointUnit: 'px', + factor: 5, + unitPrecision: 6, + remValue: 16, + propList: ['responsive-font-size', 'rfs'] +}; + +const processedCss = postcss(rfs(options)).process(css).css; + +fs.writeFile('main.dest.css', processedCss, (err) => { + if (err) { + throw err; + } + console.log('Responsive font sizes generated.'); +}); diff --git a/examples/postcss/node/main.css b/examples/postcss/node/main.css new file mode 100644 index 0000000..ebc55d4 --- /dev/null +++ b/examples/postcss/node/main.css @@ -0,0 +1,38 @@ +/* responsive-font-size property with `px` unit */ +.selector-1 { + background-color: red; + width: 300px; + responsive-font-size: 32px; +} + +/* responsive-font-size property with `rem` unit */ +.selector-2 { + responsive-font-size: 2rem; +} + +/* responsive-font-size property with !important */ +.selector-3 { + responsive-font-size: 2rem !important; +} + +/* rfs shorthand */ +.selector-4 { + rfs: 2rem; +} + +/* not supported unit */ +.selector-5 { + responsive-font-size: 2em; +} + +/* special value */ +.selector-6 { + responsive-font-size: inherit; +} + +/* responsive-font-size property inside @support-query */ +@supports (display: flex) { + .selector-7 { + rfs: 28px; + } +} diff --git a/examples/postcss/node/main.dest.css b/examples/postcss/node/main.dest.css new file mode 100644 index 0000000..121ce9a --- /dev/null +++ b/examples/postcss/node/main.dest.css @@ -0,0 +1,73 @@ +/* responsive-font-size property with `px` unit */ +.selector-1, +.disable-responsive-font-size .selector-1, +.disable-responsive-font-size.selector-1 { + background-color: red; + width: 300px; + font-size: 2rem; +} +@media (max-width: 1200px) { + .selector-1 { + font-size: calc(1.2rem + 1.066667vw); + } +} + +/* responsive-font-size property with `rem` unit */ +.selector-2, +.disable-responsive-font-size .selector-2, +.disable-responsive-font-size.selector-2 { + font-size: 2rem; +} +@media (max-width: 1200px) { + .selector-2 { + font-size: calc(1.2rem + 1.066667vw); + } +} + +/* responsive-font-size property with !important */ +.selector-3, +.disable-responsive-font-size .selector-3, +.disable-responsive-font-size.selector-3 { + font-size: 2rem !important; +} +@media (max-width: 1200px) { + .selector-3 { + font-size: calc(1.2rem + 1.066667vw) !important; + } +} + +/* rfs shorthand */ +.selector-4, +.disable-responsive-font-size .selector-4, +.disable-responsive-font-size.selector-4 { + font-size: 2rem; +} +@media (max-width: 1200px) { + .selector-4 { + font-size: calc(1.2rem + 1.066667vw); + } +} + +/* not supported unit */ +.selector-5 { + font-size: 2em; +} + +/* special value */ +.selector-6 { + font-size: inherit; +} + +/* responsive-font-size property inside @support-query */ +@supports (display: flex) { + .selector-7, +.disable-responsive-font-size .selector-7, +.disable-responsive-font-size.selector-7 { + font-size: 1.75rem; + } + @media (max-width: 1200px) { + .selector-7 { + font-size: calc(1.15rem + 0.8vw); + } + } +} diff --git a/less/rfs.less b/less/rfs.less new file mode 100644 index 0000000..ee82401 --- /dev/null +++ b/less/rfs.less @@ -0,0 +1,204 @@ +// stylelint-disable declaration-property-value-blacklist + +// RFS mixin. +// +// Automated font-resizing. +// +// See https://github.com/MartijnCuppens/rfs. + +// Configuration. + +// Minimum font size. +@rfs-minimum-font-size: 1rem; +@rfs-font-size-unit: rem; + +// Breakpoint at where font-size starts decreasing if screen width is smaller. +@rfs-breakpoint: 1200px; +@rfs-breakpoint-unit: px; + +// Resize font-size based on screen height and width. +@rfs-two-dimensional: false; + +// Factor of decrease. +@rfs-factor: 5; + +// Generate disable classes +@rfs-generate-disable-classes: true; + +// 1 rem = @rfs-rem-value px. +@rfs-rem-value: 16; + +// Disable RFS by setting @enable-responsive-font-sizes to false. +@enable-responsive-font-sizes: true; + +// Responsive font-size mixin. +.rfs(@fs, @important: false) { + + & when (not(@important)) { + ._rfs-prefix(@fs, e('')); + } + + & when (@important) { + ._rfs-prefix(@fs, e(' !important')); + } +} + +._rfs-prefix(@fs, @suffix) { + + & when ((not(isnumber(@fs)) and not(isunit(@fs, px)) and not(isunit(@fs, rem))) or (@fs = 0)) { + font-size: @fs @suffix; + } + + & when (((isnumber(@fs)) and (get-unit(@fs) = e(''))) or (isunit(@fs, px)) or (isunit(@fs, rem))) { + ._rfs-render-base(@fs, @suffix); + } +} + +._rfs-render-base(@fs, @suffix) { + + & when ((isnumber(@fs)) and (get-unit(@fs) = e(''))) { + ._rfs-render-base-number(@fs, @suffix); + ._rfs-render-media-query(@fs, @suffix); + } + + & when ((isunit(@fs, px))) { + ._rfs-render-base-number(unit(@fs), @suffix); + ._rfs-render-media-query(unit(@fs), @suffix); + } + + & when ((isunit(@fs, rem))) { + ._rfs-render-base-number(unit(@fs/.0625), @suffix); + ._rfs-render-media-query(unit(@fs/.0625), @suffix); + } +} + +._rfs-render-media-query(@fs, @suffix) { + & when ((@fs > @rfs-minimum-font-size) and (@rfs-factor > 1) and (@enable-responsive-font-sizes = true)) { + + & when ((isnumber(@rfs-breakpoint)) and (get-unit(@rfs-breakpoint) = e(''))) { + ._rfs-render-media-query-breakpoint(@fs, @suffix, @rfs-breakpoint); + } + + & when ((isunit(@rfs-breakpoint, px))) { + ._rfs-render-media-query-breakpoint(@fs, @suffix, unit(@rfs-breakpoint)); + } + + & when ((isunit(@rfs-breakpoint, rem))) { + ._rfs-render-media-query-breakpoint(@fs, @suffix, unit(@rfs-breakpoint * @rfs-rem-value)); + } + + & when ((isunit(@rfs-breakpoint, em))) { + ._rfs-render-media-query-breakpoint(@fs, @suffix, unit(@rfs-breakpoint * @rfs-rem-value)); + } + } +} + +._rfs-render-media-query-breakpoint(@fs, @suffix, @breakpoint) { + & when (@rfs-two-dimensional) { + ._rfs-render-media-query-two-dimensional(@fs, @suffix, @breakpoint); + } + & when (not(@rfs-two-dimensional)) { + ._rfs-render-media-query-one-dimension(@fs, @suffix, @breakpoint); + } +} + +._rfs-render-media-query-one-dimension(@fs, @suffix, @breakpoint) { + & when (@rfs-breakpoint-unit = px) { + @media (max-width: unit(@breakpoint, px)) { + ._rfs-render-media-query-content(@fs, @suffix, @breakpoint); + } + } + + & when (@rfs-breakpoint-unit = rem) { + @media (max-width: unit((@breakpoint / @rfs-rem-value), rem)) { + ._rfs-render-media-query-content(@fs, @suffix, @breakpoint); + } + } + + & when (@rfs-breakpoint-unit = em) { + @media (max-width: unit((@breakpoint / @rfs-rem-value), em)) { + ._rfs-render-media-query-content(@fs, @suffix, @breakpoint); + } + } +} + +._rfs-render-media-query-two-dimensional(@fs, @suffix, @breakpoint) { + & when (@rfs-breakpoint-unit = px) { + @media (max-width: unit(@breakpoint, px)), (max-height: unit(@breakpoint, px)) { + ._rfs-render-media-query-content(@fs, @suffix, @breakpoint); + } + } + + & when (@rfs-breakpoint-unit = rem) { + @media (max-width: unit((@breakpoint / @rfs-rem-value), rem)), (max-height: unit((@breakpoint / @rfs-rem-value), rem)) { + ._rfs-render-media-query-content(@fs, @suffix, @breakpoint); + } + } + + & when (@rfs-breakpoint-unit = em) { + @media (max-width: unit((@breakpoint / @rfs-rem-value), em)), (max-height: unit((@breakpoint / @rfs-rem-value), em)) { + ._rfs-render-media-query-content(@fs, @suffix, @breakpoint); + } + } +} + +._rfs-render-media-query-content(@fs, @suffix, @breakpoint) { + & when ((isnumber(@rfs-minimum-font-size)) and (get-unit(@rfs-minimum-font-size) = e(''))) { + ._rfs-render-media-query-content-dimensional(@fs, @suffix, @rfs-minimum-font-size, @breakpoint); + } + + & when ((isunit(@rfs-minimum-font-size, px))) { + ._rfs-render-media-query-content-dimensional(@fs, @suffix, unit(@rfs-minimum-font-size), @breakpoint); + } + + & when ((isunit(@rfs-minimum-font-size, rem))) { + ._rfs-render-media-query-content-dimensional(@fs, @suffix, unit(@rfs-minimum-font-size * @rfs-rem-value), @breakpoint); + } +} + +._rfs-render-media-query-content-dimensional(@fs, @suffix, @rfs-min, @breakpoint) { + & when (@rfs-two-dimensional) { + // Calculate minimum font-size for given font-size. + @fs-min: @rfs-min + (@fs - @rfs-min) / @rfs-factor; + // Calculate difference between given font-size and minimum font-size for given font-size. + @fs-variable-width: unit((@fs - @fs-min) / (@breakpoint / 100), vmin); + + ._rfs-render-fluid(@fs-min, @fs-variable-width, @suffix); + } + + & when (not(@rfs-two-dimensional)) { + // Calculate minimum font-size for given font-size. + @fs-min: @rfs-min + (@fs - @rfs-min) / @rfs-factor; + // Calculate difference between given font-size and minimum font-size for given font-size. + @fs-variable-width: unit((@fs - @fs-min) / (@breakpoint / 100), vw); + + ._rfs-render-fluid(@fs-min, @fs-variable-width, @suffix); + } +} + +._rfs-render-fluid(@fs-min, @fs-variable-width, @suffix) { + + & when (@rfs-font-size-unit = px) { + font-size: calc(unit(@fs-min, px) e('+') @fs-variable-width)@suffix; + } + + & when (@rfs-font-size-unit = rem) { + font-size: calc(unit(@fs-min / @rfs-rem-value, rem) e('+') @fs-variable-width)@suffix; + } +} + +._rfs-render-base-number(@fs, @suffix) { + + & when (@rfs-font-size-unit = px) { + font-size: unit(@fs, px)@suffix; + } + + & when (@rfs-font-size-unit = rem) { + font-size: unit((@fs / @rfs-rem-value), rem)@suffix; + } +} + +// The responsive-font-size mixin uses RFS to rescale font sizes. +.responsive-font-size(@fs, @important: false) { + .rfs(@fs, @important); +} diff --git a/package.json b/package.json index f41f0ae..62e415f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "rfs", "version": "7.0.4", "description": "A scss-mixin for responsive font-sizes.", - "main": "scss/_rfs.scss", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, @@ -11,15 +10,30 @@ "url": "git+https://github.com/MartijnCuppens/rfs.git" }, "keywords": [ - "scss", + "rfs", "responsive", "font-size", - "typography" + "typography", + "scss", + "sass", + "less", + "stylus", + "postcss" ], "author": "Martijn Cuppens <martijn.cuppens@gmail.com>", "license": "MIT", "bugs": { "url": "https://github.com/MartijnCuppens/rfs/issues" }, - "homepage": "https://github.com/MartijnCuppens/rfs#readme" + "homepage": "https://github.com/MartijnCuppens/rfs#readme", + "devDependencies": { + "postcss": "^6.0.14", + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.6.1", + "browserify": "^14.5.0", + "postcss-nested": "^3.0.0", + "uglify-js": "^3.2.2", + "gulp-postcss" : "^7.0.0", + "gulp": "^3.9.1" + } } diff --git a/postcss/rfs.js b/postcss/rfs.js new file mode 100644 index 0000000..abe02a5 --- /dev/null +++ b/postcss/rfs.js @@ -0,0 +1,175 @@ +'use strict'; + +const postcss = require('postcss'); + +module.exports = postcss.plugin('postcss-rfs', function (opts) { + const BREAKPOINT_ERROR = 'breakpoint option is invalid, it must be set in `px`, `rem` or `em`.'; + const BREAKPOINT_UNIT_ERROR = 'breakpointUnit option is invalid, it must be `px`, `rem` or `em`.'; + const MINIMUM_FONT_SIZE_ERROR = 'minimumFontSize option is invalid, it must be set in `px` or `rem`.'; + const DISABLE_RESPONSIVE_FONT_SIZE_SELECTOR = '.disable-responsive-font-size'; + opts = opts || {}; + opts.minimumFontSize = opts.minimumFontSize || 16; + opts.fontSizeUnit = opts.fontSizeUnit || 'rem'; + opts.breakpoint = opts.breakpoint || 1200; + opts.breakpointUnit = opts.breakpointUnit || 'px'; + opts.factor = opts.factor || 5; + opts.twoDimensional = opts.twoDimensional || false; + opts.unitPrecision = opts.unitPrecision || 5; + opts.generateDisableClasses = opts.generateDisableClasses || true; + opts.remValue = opts.remValue || 16; + opts.propList = opts.propList || ['responsive-font-size', 'rfs']; + + if (typeof opts.minimumFontSize !== 'number') { + if (opts.minimumFontSize.endsWith('px')) { + opts.minimumFontSize = parseFloat(opts.minimumFontSize); + } + else if (opts.minimumFontSize.endsWith('rem')) { + opts.minimumFontSize = parseFloat(opts.minimumFontSize) / opts.remValue; + } + else { + console.error(MINIMUM_FONT_SIZE_ERROR); + } + } + + if (typeof opts.breakpoint !== 'number') { + if (opts.breakpoint.endsWith('px')) { + opts.breakpoint = parseFloat(opts.breakpoint); + } + else if (opts.breakpoint.endsWith('em')) { + opts.breakpoint = parseFloat(opts.breakpoint) * opts.remValue; + } + else { + console.error(BREAKPOINT_ERROR); + } + } + + return function (css) { + + css.walkRules(function (rule) { + + if (rule.selector.includes(DISABLE_RESPONSIVE_FONT_SIZE_SELECTOR)){ + return; + } + + rule.walkDecls(function (decl) { + // Skip if property is not in propList. + if (opts.propList.indexOf(decl.prop) === -1) { + return; + } + + // Set property to font-size. + decl.prop = 'font-size'; + + // Skip if value is not in px or rem. + if (!new RegExp(/(\d*\.?\d+)(px|rem)/g).test(decl.value)) { + return; + } + + // Get the float value of the value. + let value = parseFloat(decl.value); + + // Multiply by remValue if value is in rem. + if (decl.value.indexOf('rem') > -1) { + value *= opts.remValue; + } + + // Render value in desired unit. + if (opts.fontSizeUnit === 'px') { + decl.value = toFixed(value, opts.unitPrecision) + 'px'; + } + else if (opts.fontSizeUnit === 'rem') { + decl.value = toFixed(value / opts.remValue, opts.unitPrecision) + 'rem'; + } + else { + console.error('fontSizeUnit option is not valid, it must be `px` or `rem`.'); + } + + // Only add media query if needed. + if (opts.minimumFontSize >= value || opts.factor === 1) { + return; + } + + // Calculate font-size and font-size difference. + let baseFontSize = opts.minimumFontSize + (value - opts.minimumFontSize) / opts.factor; + const fontSizeDiff = value - baseFontSize; + + // Divide by remValue if needed. + if (opts.fontSizeUnit === 'rem') { + baseFontSize /= opts.remValue; + } + + // Save selector for later. + const rule_selector = rule.selector; + + // Disable classes. + if (opts.generateDisableClasses) { + const selectors = rule.selector.split(','); + let ruleSelector = ''; + + for (let selector of selectors) { + ruleSelector += selector + ',\n'; + ruleSelector += DISABLE_RESPONSIVE_FONT_SIZE_SELECTOR + ' ' + selector + ',\n'; + ruleSelector += DISABLE_RESPONSIVE_FONT_SIZE_SELECTOR + selector + ',\n'; + } + + rule.selector = ruleSelector.slice(0, - 2); + } + + const viewportUnit = opts.twoDimensional ? 'vmin' : 'vw'; + + value = 'calc(' + toFixed(baseFontSize, opts.unitPrecision) + opts.fontSizeUnit + ' + ' + toFixed((fontSizeDiff * 100 / opts.breakpoint), opts.unitPrecision) + viewportUnit + ')'; + + const mediaQuery = postcss.atRule(renderMediaQuery(opts)); + const mediaQueryRule = postcss.rule({ + selector: rule_selector, + source: rule.source + }); + mediaQueryRule.append(decl.clone({value: value})); + mediaQuery.append(mediaQueryRule); + rule.parent.insertAfter(rule, mediaQuery.clone()); + }); + }); + + }; + + function renderMediaQuery (opts) { + const mediaQuery = { + name: 'media' + }; + + switch (opts.breakpointUnit) { + case 'em': + case 'rem': + const breakpoint = opts.breakpoint / opts.remValue; + + if (opts.twoDimensional) { + mediaQuery.params = '(max-width: ' + breakpoint + opts.breakpointUnit + '), (max-height: ' + breakpoint + opts.breakpointUnit + ')'; + } + else { + mediaQuery.params = '(max-width: ' + breakpoint + opts.breakpointUnit + ')'; + } + break; + + case 'px': + if (opts.twoDimensional) { + mediaQuery.params = '(max-width: ' + opts.breakpoint + 'px), (max-height: ' + opts.breakpoint + 'px)'; + } + else { + mediaQuery.params = '(max-width: ' + opts.breakpoint + 'px)'; + } + break; + + default: + console.error(BREAKPOINT_UNIT_ERROR); + break; + } + + return mediaQuery; + } + + function toFixed (number, precision) { + const multiplier = Math.pow(10, precision + 1), + wholeNumber = Math.floor(number * multiplier); + return Math.round(wholeNumber / 10) * 10 / multiplier; + } +}); diff --git a/stylus/_rfs.styl b/stylus/_rfs.styl new file mode 100644 index 0000000..330dceb --- /dev/null +++ b/stylus/_rfs.styl @@ -0,0 +1,151 @@ +// stylelint-disable declaration-property-value-blacklist + +// RFS mixin. +// +// Automated font-resizing. +// +// See https://github.com/MartijnCuppens/rfs. + +// Configuration. + +// Minimum fontsize. +$rfs-minimum-font-size = 1rem +$rfs-font-size-unit = rem + +// Breakpoint at where font-size starts decreasing if screen width is smaller. +$rfs-breakpoint = 1200px +$rfs-breakpoint-unit = px + +// Resize font-size based on screen height and width. +$rfs-two-dimensional = false + +// Factor of decrease. +$rfs-factor = 5 + +// Generate disable classes +$rfs-generate-disable-classes = true + +// 1 rem = $rfs-rem-value px. +$rfs-rem-value = 16 + +// Disable RFS by setting $enable-responsive-font-sizes to false. +$enable-responsive-font-sizes = true + +if $enable-responsive-font-sizes == false + // If $rfs-factor is set to 1, fluid font-resizing is disabled. + $rfs-factor = 1 + +// Remove px-unit from $rfs-minimum-font-size for calculations. +if unit($rfs-minimum-font-size) == "px" + $rfs-minimum-font-size = unit($rfs-minimum-font-size, '') +else if unit($rfs-minimum-font-size) == "rem" + $rfs-minimum-font-size = unit($rfs-minimum-font-size * $rfs-rem-value, '') + +// Remove unit from $rfs-breakpoint for calculations. +if unit($rfs-breakpoint) == "px" + $rfs-breakpoint = unit($rfs-breakpoint, '') +else if unit($rfs-breakpoint) == "rem" or unit($rfs-breakpoint) == "em" + $rfs-breakpoint = unit($rfs-breakpoint / $rfs-rem-value, '') + +// Responsive font-size mixin. +rfs($fs, $important = false) + $rfs-suffix = "%s" % () + + // Add !important suffix if needed. + if $important + $rfs-suffix = !important + + // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value. + if type-of($fs) != "unit" or !unitless($fs) and unit($fs) != "px" and unit($fs) != "rem" or $fs == 0 + font-size: "%s%s" % ($fs $rfs-suffix) + else + // Variables for storing static and fluid rescaling. + $rfs-static = null + $rfs-fluid = null + + // Remove px-unit from $fs for calculations. + if unit($fs) == px + $fs = unit($fs, '') + else if unit($fs) == rem + $fs = unit($fs / $rfs-rem-value, '') + + // Set default font-size. + if $rfs-font-size-unit == rem + $rfs-static = "%s%s" % (unit(($fs / $rfs-rem-value), rem) $rfs-suffix) + else if $rfs-font-size-unit == px + $rfs-static = "%s%s" % (unit($fs, px) $rfs-suffix) + else + @error "`$rfs-font-size-unit` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`." + + if type-of($rfs-factor) != "unit" or $rfs-factor < 1 + @error "`$rfs-factor` is not a valid $rfs-factor, it must be greater or equal to 1." + + // Only add media query if font-size is bigger as the minimum font-size. + // If $rfs-factor == 1, no rescaling will take place. + if $fs > $rfs-minimum-font-size and $rfs-factor != 1 + $min-width = null + $variable-unit = null + + // Calculate minimum font-size for given font-size. + $fs-min = $rfs-minimum-font-size + ($fs - $rfs-minimum-font-size) / $rfs-factor + + // Calculate difference between given font-size and minimum font-size for given font-size. + $fs-diff = $fs - $fs-min + + // Minimum font-size formatting. + // No need to check if the unit is valid, because we did that before. + if $rfs-font-size-unit == rem + $min-width = unit($fs-min / $rfs-rem-value, rem) + else + $min-width = unit($fs-min, px) + + // If two-dimensional, use smallest of screen width and height. + if $rfs-two-dimensional + $variable-unit = vmin + else + $variable-unit = vw + + // Calculate the variable width between 0 and $rfs-breakpoint. + $variable-width = "%s%s" % ($fs-diff * 100 / $rfs-breakpoint $variable-unit) + + // Set the calculated font-size. + $rfs-fluid = "calc(%s + %s)%s" % ($min-width $variable-width $rfs-suffix) + + // Rendering. + if $rfs-fluid == null + // Only render static font-size if no fluid font-size is available. + font-size: $rfs-static + else + $mq-value = null + + // RFS breakpoint formatting. + if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem + $mq-value = unit($rfs-breakpoint / $rfs-rem-value, $rfs-breakpoint-unit) + else if $rfs-breakpoint-unit == px + $mq-value = unit($rfs-breakpoint, px) + else + @error "`$rfs-breakpoint-unit` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`." + + if $rfs-generate-disable-classes + // Adding an extra class increases specificity, + // which prevents the media query to override the font size + &, + .disable-responsive-font-size &, + &.disable-responsive-font-size + font-size: $rfs-static + else + font-size: $rfs-static + + if $rfs-two-dimensional + @media (max-width: $mq-value), (max-height: $mq-value) + font-size: $rfs-fluid + else + @media (max-width: $mq-value) + font-size: $rfs-fluid + +// The responsive-font-size mixin uses RFS to rescale font sizes. +responsive-font-size($fs, $important = false) + rfs($fs, $important) + +.title + responsive-font-size(40) |