šŸŒœ
šŸŒž
rfs

rfs

v9.0.6

Powerful & easy-to-use responsive resizing engine.

npm install rfs

README

RFS logo

RFS is a unit resizing engine which was initially developed to resize font sizes (hence its abbreviation for Responsive Font Sizes). Nowadays RFS is capable of rescaling basically every value for any css property with units, like margin, padding, border-radius or even box-shadow.

The mechanism automatically calculates the appropriate values based on the dimensions of the browser viewport. It's available in one of your favourite preprocessors or postprocessor: Sass, Less, Stylus or PostCSS.

RFS

npm licence build devDeps

Demos

Advantages

  • No need to rescale paddings or margins anymore.
  • Text won't be chopped off in smaller viewports when RFS is applied to font sizes.
  • RFS will prevent the font size from rescaling too small, so readability can be assured.
  • The font sizes of all text elements will always remain in relation with each other.

Fluid rescaling in action

The following example shows the effect of RFS on font sizes:

RFS

Installation

RFS can be installed using a package manager (recommended):

  • npm: npm install rfs
  • yarn: yarn add rfs
  • bower (deprecated): bower install rfs --save

Copy/paste (not recommended):

The source files can also be downloaded manually and used in a project. This method is not recommended because you lose the ability to easily and quickly manage and update RFS as a dependency.

Usage

Sass (.scss syntax)

project/
ā”œā”€ā”€ node_modules/
ā”‚   ā””ā”€ā”€ rfs
ā”‚        ā””ā”€ā”€ ...
ā””ā”€ā”€ scss/
    ā””ā”€ā”€ main.scss

Input

// scss/main.scss

@import "../node_modules/rfs/scss";

.title {
  @include font-size(4rem);

  // The font-size mixin is a shorthand which calls
  // @include rfs(4rem, font-size);

  // Other shorthand mixins that are available are:
  // @include padding(4rem);
  // @include padding-top(4rem);
  // @include padding-right(4rem);
  // @include padding-bottom(4rem);
  // @include padding-left(4rem);
  // @include margin(4rem);
  // @include margin-top(4rem);
  // @include margin-right(4rem);
  // @include margin-bottom(4rem);
  // @include margin-left(4rem);

  // For properties which do not have a shorthand, the property can be passed:
  // @include rfs(4rem, border-radius);

  // Whenever a value contains a space, it should be escaped with `#{}`:
  // @include rfs(0 0 4rem red #{","} 0 0 5rem blue, box-shadow);

  // Custom properties (css variables):
  // @include rfs(4rem, --border-radius);
}

If you're using Webpack, you can simplify the @import using the ~ prefix:

@import "~rfs/scss";

Generated css

.title {
  font-size: calc(1.525rem + 3.3vw);
}

@media (min-width: 1200px) {
  .title {
    font-size: 4rem;
  }
}

!important usage

Input
.label {
  @include font-size(2.5rem !important);
}
Output
.label {
  font-size: calc(1.375rem + 1.5vw) !important;
}

@media (min-width: 1200px) {
  .label {
    font-size: 2.5rem !important;
  }
}

Sass (.sass syntax)

project/
ā”œā”€ā”€ node_modules/
ā”‚   ā””ā”€ā”€ rfs
ā”‚        ā””ā”€ā”€ ...
ā””ā”€ā”€ sass/
    ā””ā”€ā”€ main.sass

Input

// scss/main.scss

@import "../node_modules/rfs/sass"

.title
  +font-size(4rem)

  // The font-size mixin is a shorthand which calls
  // +rfs(4rem, font-size)

  // Other shorthand mixins that are available are:
  // +padding(4rem)
  // +padding-top(4rem)
  // +padding-right(4rem)
  // +padding-bottom(4rem)
  // +padding-left(4rem)
  // +margin(4rem)
  // +margin-top(4rem)
  // +margin-right(4rem)
  // +margin-bottom(4rem)
  // +margin-left(4rem)

  // For properties which do not have a shorthand, the property can be passed:
  // +rfs(4rem, border-radius)

  // Whenever a value contains a space, it should be escaped with `#{}`:
  // +rfs(0 0 4rem red #{","} 0 0 5rem blue, box-shadow)

  // Custom properties (css variables):
  // +rfs(4rem, --border-radius)

If you're using Webpack, you can simplify the @import using the ~ prefix:

@import "~rfs/scss"

Generated css

.title {
  font-size: calc(1.525rem + 3.3vw);
}

@media (min-width: 1200px) {
  .title {
    font-size: 4rem;
  }
}

!important usage

Input
.label
  +font-size(2.5rem !important)

output

.label {
  font-size: calc(1.375rem + 1.5vw) !important;
}

@media (min-width: 1200px) {
  .label {
    font-size: 2.5rem !important;
  }
}

PostCSS

project/
ā”œā”€ā”€ postcss/
ā”‚   ā””ā”€ā”€ main.css
ā””ā”€ā”€ node_modules/
    ā””ā”€ā”€ rfs
         ā””ā”€ā”€ ...

Have a look at the examples folder to find examples on how your PostCSS setup can be configured.

// postcss/main.css

.title {
  font-size: rfs(4rem);

  // Or use it with any other property, for example
  // padding: rfs(4rem);

  // It's also possible to pass multiple values
  // padding: rfs(3rem 4rem);

  // or even
  // box-shadow: rfs(0 3px 4rem red);

  // or even comma seperated values
  // box-shadow: rfs(0 3px 4rem red, 3px 0 4rem blue);

  // To combine it with !important, use
  // box-shadow: rfs(0 3px 4rem red) !important;

  // Custom properties (css variables):
  // --border-radius: rfs(4rem);
}

Generated css

.title {
  font-size: calc(1.525rem + 3.3vw);
}

@media (min-width: 1200px) {
  .title {
    font-size: 4rem;
  }
}

Less

project/
ā”œā”€ā”€ less/
ā”‚   ā””ā”€ā”€ main.less
ā””ā”€ā”€ node_modules/
    ā””ā”€ā”€ rfs
         ā””ā”€ā”€ ...
// less/main.less

@import "../node_modules/rfs/less";

.title {
  .font-size(4rem);

  // The font-size mixin is a shorthand which calls
  // .rfs(4rem, font-size);

  // Other shorthand mixins that are available are:
  // .padding(4rem);
  // .padding-top(4rem);
  // .padding-right(4rem);
  // 'padding-bottom(4rem);
  // .padding-left(4rem);
  // .margin(4rem);
  // .margin-top(4rem);
  // .margin-right(4rem);
  // .margin-bottom(4rem);
  // .margin-left(4rem);

  // For properties which do not have a shorthand, the property can be passed as:
  // .rfs(4rem, border-radius);

  // Whenever a value contains a space, it should be escaped with a tilde(~):
  // .rfs(0 0 4rem red ~"," 0 0 5rem blue, box-shadow)

  // Custom properties (css variables):
  // .rfs(4rem, --border-radius)
}

If you're using Webpack, you can simplify the @import using the ~ prefix:

@import "~rfs/less"

Generated css

.title {
  font-size: calc(1.525rem + 3.3vw);
}

@media (min-width: 1200px) {
  .title {
    font-size: 4rem;
  }
}

!important usage

Less still has a bug for native !important support, and !important can not be accepted as a parameter, so you 'll need to pass important as a flag:

Input
.label {
  .font-size(2.5rem important);
}

output

.label {
  font-size: calc(1.375rem + 1.5vw) !important;
}

@media (min-width: 1200px) {
  .label {
    font-size: 2.5rem !important;
  }
}

Stylus

project/
ā”œā”€ā”€ node_modules/
ā”‚   ā””ā”€ā”€ rfs
ā”‚        ā””ā”€ā”€ ...
ā””ā”€ā”€ stylus/
    ā””ā”€ā”€ main.styl
// stylus/main.styl

@import "../node_modules/rfs/stylus";

.title
  rfs-font-size(64px)

  // The font-size mixin is a shorthand which calls
  // rfs(4rem, font-size)

  // Other shorthand mixins that are available are:
  // rfs-padding(4rem)
  // rfs-padding-top(4rem)
  // rfs-padding-right(4rem)
  // rfs-padding-bottom(4rem)
  // rfs-padding-left(4rem)
  // rfs-margin(4rem)
  // rfs-margin-top(4rem)
  // rfs-margin-right(4rem)
  // rfs-margin-bottom(4rem)
  // rfs-margin-left(4rem)

  // For properties which do not have a shorthand, the property can be passed as:
  // rfs(4rem, border-radius)

  // Whenever a value contains a space, it should be escaped with a backslash:
  // rfs(0 0 4rem red \, 0 0 5rem blue, box-shadow)

  // Custom properties (css variables):
  // rfs(4rem, --border-radius)

Note the font-size mixin can not be used to set the font size. That is because a font-size() mixin would override the font-size property. See 129#issuecomment-477926416 for more info.

If you're using Webpack, you can simplify the @import using the ~ prefix:

@import "~rfs/stylus"

Generated css

.title {
  font-size: calc(1.525rem + 3.3vw);
}

@media (min-width: 1200px) {
  .title {
    font-size: 4rem;
  }
}

!important usage

Input
.label
  rfs-font-size(2.5rem important)

output

.label {
  font-size: calc(1.375rem + 1.5vw) !important;
}

@media (min-width: 1200px) {
  .label {
    font-size: 2.5rem !important;
  }
}

Visualisation

If you wonder how the values are rescaled, wonder no more and stare at this graph which might clarify things a bit:

RFS visualisation

Each color represents another value being rescaled. For example:

.title {
  @include font-size(40px);
}

This is the green line. A font size of 40px stays 40px in viewports with a size larger than 1200px. Below 1200px, the font size is rescaled and at viewport of 360px, the font size is about 27px. Note that every font size is generated in a combination of rem and vw units, but they are mapped to px in the graph to make it easier to understand.

Configuration

RFS works out of the box without any configuration tweaks, but if you feel the urge to go loco and fine tune the way values are rescaled, you can:

Base value (unit in px or rem)

  • SCSS, Sass & Stylus: $rfs-base-value
  • Less: @rfs-base-value
  • PostCSS: baseValue

The option will prevent the value from becoming too small on smaller screens. If the font size which is passed to RFS is smaller than this value, no fluid rescaling will take place.

Default value: 1.25rem

Unit (px or rem)

  • SCSS, Sass & Stylus: $rfs-unit
  • Less: @rfs-unit
  • PostCSS: unit

The output value will be rendered in this unit. Keep in mind configuring this value to px will disable the ability for users to change the the font size in their browser.

Default value: rem

Breakpoint (in px, em or rem)

  • SCSS, Sass & Stylus: $rfs-breakpoint
  • Less: @rfs-breakpoint
  • PostCSS: breakpoint

Above this breakpoint, the value will be equal to the value you passed to RFS; below the breakpoint, the value will dynamically scale.

Default value: 1200px

Breakpoint unit (px, em or rem)

  • SCSS, Sass & Stylus: $rfs-breakpoint-unit
  • Less: @rfs-breakpoint-unit
  • PostCSS: breakpointUnit

The width of the max width in the media query will be rendered in this unit.

Default value: px

Factor (number)

  • SCSS, Sass & Stylus: $rfs-factor
  • Less: @rfs-factor
  • PostCSS: factor

This value determines the strength of font size resizing. The higher the factor, the less difference there is between values on small screens. The lower the factor, the less influence RFS has, which results in bigger values for small screens. The factor must be greater than 1.

Default value: 10

Rem value (number)

  • SCSS, Sass & Stylus: $rfs-rem-value
  • Less: @rfs-rem-value
  • PostCSS: remValue

The value of 1rem in px. The value of 1rem is typically 16px but if the font size is changed for html the value of 1rem changes. This variable can be used to change the default value but be careful with it because changing it could lead to unexpected behaviour, for example if additional CSS is loaded which expects 1rem to be 16px.

Default value: 16

Two dimensional (boolean)

  • SCSS, Sass & Stylus: $rfs-two-dimensional
  • Less: @rfs-two-dimensional
  • PostCSS: twoDimensional

Enabling the two dimensional media queries will determine the value based on the smallest side of the screen with vmin. This prevents values from changing if the device toggles between portrait and landscape mode.

Default value: false

Class (boolean)

  • SCSS, Sass & Stylus: $rfs-class
  • Less: @rfs-class
  • PostCSS: class

RFS can be enabled or disabled with a class. There are 3 options:

  • false No extra classes are generated.
  • disable When the the disable classes are generated you can add the .disable-rfs class to an element to disable responsive value rescaling for the element and its child elements.
  • enable RFS is disabled by default in this case. The .enable-rfs class can be added to an element to enable responsive value rescaling for the element and its child elements.

Default value: false

Safari iframe resize bug fix (boolean)

  • SCSS, Sass & Stylus: $rfs-safari-iframe-resize-bug-fix
  • Less: @rfs-safari-iframe-resize-bug-fix
  • PostCSS: safariIframeResizeBugFix

Safari doesn't resize its values in an iframe if the iframe is resized. To fix this min-width: 0vw can be added and that's what happens if this option is enabled. See #14.

Default value: false

Best practices

  • Don't set RFS on the html element, because this influences the value of rem and could lead to unexpected results.
  • Always set your line-heights relative (in em or unitless) to prevent interline issues with font sizes.

Browser support

RFS is supported by all browsers that support media queries and viewport units.

Creator

Martijn Cuppens

Code released under the MIT license.

Release Notes

10.0.0-alpha.0
By Martijn Cuppens ā€¢ Published on June 22, 2020

See https://github.com/twbs/rfs/issues/110

Released as alpha version since browser support ain't that great at this moment. Branch is not merged in main yet, docs are available here: https://github.com/twbs/rfs/tree/min-function

9.0.6
Published on September 7, 2021
  • Use the exponentiation operator
  • Update devDependencies

https://github.com/twbs/rfs/compare/v9.0.5...v9.0.6

9.0.5
Published on July 26, 2021
  • Support less v4
  • Run examples on CI too
9.0.4
Published on June 22, 2021
  • Multiplication fix (#371)
  • New divide() function to prevent Sass deprecation warnings (#398)
9.0.3
Published on April 14, 2020
9.0.2
By Martijn Cuppens ā€¢ Published on October 23, 2019

https://github.com/twbs/rfs/commit/d073bc94689a46031a38840d099b9dde2f072c15#diff-ab9ae3f4626ffc1851a825ba738ae7ba broke Dart Sass compatibility. The bug is patched & a test is written to prevent issues in the future.

Thanks @seth100 for reporting this issue in https://github.com/twbs/rfs/issues/176.

9.0.1
By Martijn Cuppens ā€¢ Published on October 21, 2019
  • Copy fixes in the readme, .sass and .js files.
  • Dev dependency updates
  • Dependabot configuration
  • Github action tweaks.
9.0.0
By Martijn Cuppens ā€¢ Published on August 28, 2019

Features

  • Support for all properties
  • Shorthand mixins for margins and paddings
  • Support for custom properties

Changes

  • Clearer way to declare !important rules: @include rfs(1rem !important) instead of @include rfs(1rem, true)
  • Switched to mobile first approach, still possible to switch to the max-width media queries if needed
  • px-values should always have a unit now. In v8, RFS assumed every unitless value was set in px (eg. @include rfs(32)), but since we can now pass numbers too (eg. @include rfs(1 1 30rem, flex), this behaviour is changed.
  • Configuration variables are changed:
    • Base font size ā†’ Base value
    • Font size unit ā†’ unit

PostCSS implementation change

Drops

  • Dropped responsive-font-size mixins
  • Dropped Less 2 support since we had to work with lists
  • Dropped node 6 support

Meta

  • Prevent generation of /test/expected/main.css
  • Additional tests for new implementations
  • Cleanup npm scripts examples
  • postcss-value-parser dependency added to parse values in PostCSS plugin.
  • Ditch Husky since we already run the tests in each PR
  • Switch from CircleCI to Github actions
  • Add Node 12 tests
  • dev-dependency updates

Demos

8.1.0
Published on September 7, 2021
  • Backport #398 (#421): New divide() function to prevent Sass deprecation warnings
  • Add Dart Sass tests
  • Update devDependencies
  • Switch to GitHub Actions CI

https://github.com/twbs/rfs/compare/v8.0.4...v8.1.0

8.0.4
Published on April 8, 2019
  • Remove unused composer.json (#123)
  • Documentation on browser support (#124)
  • Switch from Travis CI to CircleCI (#125)
  • Update dependencies (#126)
  • Add font-size mixin to less & additional tests (#129)
  • Remove font-size mixin from stylus, it was not possible to use this mixin because it would override the font-size property (#132)

General

License
MIT
Typescript Types
None found
Tree-shakeable
No

Popularity

GitHub Stargazers
3,049
Community Interest
2,953
Number of Forks
204

Maintenance

Commits
11/2110/22020
Last Commit
Open Issues
5
Closed Issues
83
Open Pull Requests
1
Closed Pull Requests
24

Versions

Versions Released
11/2110/2201
Latest Version Released
Sep 7, 2021
Current Tags
latest9.0.6
next10.0.0-alpha.0
previous8.1.0

Contributors

MartijnCuppens
MartijnCuppens
Commits: 193
XhmikosR
XhmikosR
Commits: 98
coliff
coliff
Commits: 2
mdo
mdo
Commits: 1
neelansh15
neelansh15
Commits: 1
akshayknz
akshayknz
Commits: 1
tsilvap
tsilvap
Commits: 1
voltaek
voltaek
Commits: 1
bflatmajor
bflatmajor
Commits: 1
andresgalante
andresgalante
Commits: 1
yursha
yursha
Commits: 1
Johann-S
Johann-S
Commits: 1
ivanjonas
ivanjonas
Commits: 1