twbs/rfs: resizing CSS values against the viewport
✩ Automates responsive resizing ✩
At a glance
- What is it?
- RFS is a unit resizing engine that turns a single value such as 4rem into a calc() expression plus a min-width media query. It ships as Sass, Less, Stylus and PostCSS entry points, and the trade-offs are in the generated CSS.
- Who is it for?
- Adopt twbs/rfs if your project already runs Sass, Less, Stylus or PostCSS and you want font sizes, margins and paddings to scale with the viewport from a single declared value. Do not adopt it if you need fluid type without media queries, if you want the browser to interpolate the value itself, or if you cannot add a build step.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 20 days ago.
- What is it written in?
- Mainly CSS, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What problem RFS solves, and who it is for
The README describes RFS as a unit resizing engine that was initially developed to resize font sizes, hence the abbreviation Responsive Font Sizes. Today it rescales values for any CSS property with units: margin, padding, border-radius, box-shadow. The mechanism automatically calculates values from the dimensions of the browser viewport.
The target user is not someone writing plain CSS by hand. RFS is distributed as entry points for preprocessors and postprocessors, and the repository ships scss.scss, sass.sass, less.less, stylus.styl and postcss.js at the top level, with a lib/ directory behind them. If your build does not run one of those four tools, there is nothing here for you to import.
The stated advantages are concrete: no need to rescale paddings or margins separately, text is not chopped off in smaller viewports when RFS is applied to font sizes, the font size will not rescale too small so readability can be assured, and font sizes of all text elements stay in relation with each other. That last point is the real argument. Declaring a single value and letting one engine derive every step keeps a type scale coherent, which hand-written media query ladders tend to lose over time.
How the resizing actually works
RFS does not use clamp() or any CSS-native fluid function. The README shows the generated output for a 4rem font size:
.title {
font-size: calc(1.525rem + 3.3vw);
}
@media (min-width: 1200px) {
.title {
font-size: 4rem;
}
}The mixin splits the value into a fixed rem part and a viewport-relative vw part, then caps the result at the original value once the viewport reaches the configured maximum breakpoint. So the behaviour is piecewise: below the max breakpoint the size tracks the viewport continuously, above it the size stops changing. The same shape appears in the Sass, Less, Stylus and PostCSS examples in the README, which all generate that identical pair of rules.
Because the fluid part is a vw unit, the interpolation is done by the browser at layout time, not at build time. The build only produces the arithmetic. That is why the output is two rules rather than one, and why every RFS declaration costs you a media query block in the compiled stylesheet.
Installing twbs/rfs and a first real use
The README recommends a package manager. npm and yarn are both listed, and bower is marked deprecated. The package requires Node 12 or later according to the engines field in package.json.
npm install rfsFor a Sass project the README lays out the directory as node_modules/rfs alongside scss/main.scss, then imports the entry point and calls the mixin:
// scss/main.scss
@import "../node_modules/rfs/scss";
.title {
@include font-size(4rem);
}If Webpack is in the build, the README says the import can be shortened to @import "~rfs/scss". The font-size mixin is a shorthand that calls @include rfs(4rem, font-size). Shorthands exist for padding, padding-top, padding-right, padding-bottom, padding-left, margin, margin-top, margin-right, margin-bottom and margin-left. For any property without a shorthand, the property is passed as the second argument, as in @include rfs(4rem, border-radius).
After compiling, the reader should see the calc() rule plus the min-width media query shown in the previous section. Two details from the README are easy to miss. A value containing a comma must be escaped with #{}, for example @include rfs(0 0 4rem red #{","} 0 0 5rem blue, box-shadow). And custom properties work too: @include rfs(4rem, --border-radius).
For a PostCSS pipeline the entry point is the postcss.js file listed in package.json as main, and the README points to the examples/postcss folder in the repository for how the setup should be configured. The syntax there is a function call inside the declaration:
.title {
font-size: rfs(4rem);
padding: rfs(3rem 4rem);
}The README also shows multiple and comma-separated values, box-shadow: rfs(0 3px 4rem red, 3px 0 4rem blue), and notes that !important is combined by writing box-shadow: rfs(0 3px 4rem red) !important. Less and Stylus follow the same pattern with their own call syntax, and the examples directory has a folder for each.
Where the generated CSS gets in the way
The output shape is the main limitation. Every RFS declaration becomes a calc() plus a media query, so a stylesheet with many RFS values accumulates many media query blocks, and the min-width breakpoint is fixed by configuration rather than by the value. If your project already uses a different breakpoint set, you now have two systems describing the same viewport ranges.
The README does not document what happens at the lower end of the viewport range, and it does not describe a minimum breakpoint in the generated output. The stated advantage is that RFS prevents the font size from rescaling too small, so readability can be assured, but the mechanism behind that floor is not spelled out in the README. Anyone who needs a hard lower bound should read lib/ before shipping.
It is also the wrong tool when the answer is a CSS-native one. If you only need a single fluid font size and your browser targets support clamp(), writing clamp() directly gives you one declaration with no media query and no build step. RFS is the better fit when the same scaling rule has to be applied across many properties and many components, because that is where a shared engine beats repeated hand-written arithmetic.
RFS compared with Bootstrap's own responsive typography
The closest alternative is Bootstrap itself. The README links to a demo titled RFS in Bootstrap, and the project lives under the twbs organization, so the relationship is not incidental: RFS is the engine behind Bootstrap's responsive font sizing. The difference in approach is scope. Bootstrap's responsive typography is delivered as compiled CSS custom properties and classes that you consume as-is, and it covers the heading scale Bootstrap defines. RFS is the generator, not the output. It gives you mixins and a PostCSS function so you can apply the same scaling to values Bootstrap never touches, such as a border-radius or a padding on your own component.
Choosing between them comes down to whether you want to consume a finished scale or generate your own. If Bootstrap's heading sizes are what you want, importing Bootstrap gets you there without adding RFS as a separate dependency. If you need the same fluid behaviour on properties outside that scale, RFS is the layer that produces it.
Maintenance, version and licence
The repository is not archived, and the last push was on 2026-09-10. The most recent release listed is v10.0.0 from 2023-03-23, with v9.0.6 and v8.1.0 both from 2021-09-07. So the release cadence is slow: the current major version is over three years old while commits continue. That pattern is normal for a small, single-purpose engine, but it means a fix you need may sit on main without a tagged release, and pinning to a version is the safer default. The package.json version field matches the v10.0.0 tag.
The licence is MIT, declared in package.json and shipped as a LICENSE file at the repository root. MIT is permissive and places essentially no condition on how you use the compiled CSS beyond keeping the licence notice with the source distribution. That matters less here than for a runtime library, because RFS runs at build time and what ships to users is the generated CSS. If you redistribute the RFS source files themselves, the notice applies to those files. This is a description of the licence text, not legal advice; your own counsel should confirm obligations for your distribution model.
Upgrade cost is tied to the preprocessor entry points. The files listed in package.json are lib/, less.less, postcss.js, sass.sass, scss.scss and stylus.styl, so a major version can change mixin signatures or generated output across all four at once. Compiling the test suite's expected CSS before and after an upgrade is the cheapest way to see what moved.
Editorial conclusion
Adopt twbs/rfs if your project already runs Sass, Less, Stylus or PostCSS and you want font sizes, margins and paddings to scale with the viewport from a single declared value. Do not adopt it if you need fluid type without media queries, if you want the browser to interpolate the value itself, or if you cannot add a build step. Before committing, compile one real component and read the output: check that the generated calc() and the min-width media query match the breakpoints your project already uses, and confirm the postcss.js plugin is wired into the same pipeline that processes the rest of your CSS.
Frequently asked questions
What is twbs/rfs in Sass?
It is a unit resizing engine imported into a Sass file, which provides mixins such as font-size, padding and margin that compile a single value into a calc() expression plus a min-width media query. The README shows the import as @import "../node_modules/rfs/scss" for .scss files and @import "../node_modules/rfs/sass" for .sass files.
How do I install twbs/rfs?
The README recommends a package manager and lists npm install rfs, yarn add rfs, and bower install rfs --save, which it marks as deprecated. Downloading the source files manually is possible but the README does not recommend it because you lose the ability to manage and update RFS as a dependency.
Can twbs/rfs resize properties other than font-size?
Yes. The README states RFS can rescale basically every value for any CSS property with units, and lists margin, padding, border-radius and box-shadow as examples. Shorthand mixins exist for padding and margin, and any other property is passed as the second argument, as in @include rfs(4rem, border-radius).
Does twbs/rfs work with PostCSS?
Yes. postcss.js is listed as the package main file, and the README shows the syntax as font-size: rfs(4rem) inside a declaration. It points to the examples/postcss folder in the repository for how a PostCSS setup should be configured.
What CSS does twbs/rfs generate for a 4rem font size?
The README shows a calc() rule of font-size: calc(1.525rem + 3.3vw) plus a media query at min-width: 1200px that sets font-size: 4rem. The same output is shown for the Sass, Less, Stylus and PostCSS examples.
What licence does twbs/rfs use?
MIT. The licence field in package.json is MIT and a LICENSE file sits at the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/twbs-rfs)