Open-source project
twbs/rfs avatar
twbs/rfs

RFS emits one calc expression and one breakpoint, and its indented-syntax section tells you to import the brace-syntax file

✩ Automates responsive resizing ✩

3,370 stars211 forksCSSMIT

At a glance

What is it?
RFS is an MIT-licensed unit resizing engine for Sass, Less, Stylus and PostCSS that started out scaling font sizes and now scales any valued property. Its four syntaxes each have their own entry file, example and build, the stylesheet linter covers two of them, and the expected-output generator still calls a compiler that has been deprecated.
Who is it for?
Use RFS if you want responsive type and spacing to move together from a single authored value, and if your project already has one of the four supported preprocessors. The output is deliberately simple, one calc expression below a threshold and a media query that restores the authored value above it, which means you can read the result and reason about it without a build step in your head.
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 65 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 November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • twbs/rfs3,370 ★ · +1
Star history
Repository2026-09-242026-11-14
twbs/rfs3.4k3.4k

1 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The entire output is one calc expression and one breakpoint

Read the generated CSS for the worked example and the mechanism is fully visible.

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

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

Three declarations. Below the breakpoint, a fixed rem term plus a viewport term. Above it, the value the developer actually typed.

That is worth sitting with, because it means the library does not rescale forever. It scales up to a point and then stops, and the point is the minimum viewport width at which the authored value looks right. Everything about the sizing strategy is in those two coefficients and that one number.

The important-flag example repeats the shape with different coefficients and a smaller authored value, and the important flag is carried into both declarations, so the override survives both branches.

That last detail is the reason to prefer this approach to a hand-written fluid type scale: the media query is not a second rule that has to be kept in sync, it is the same rule with a floor.

The indented-syntax section points at the brace-syntax file

The README documents four syntaxes, and each gets its own section with its own import line.

The brace-syntax Sass section tells you to import a path from the package's scss entry file. The Less section points at the less entry file. The PostCSS section needs no import at all, because the function is used inline.

The indented-syntax Sass section points at the package's sass entry file. Then, three lines later, under a note about simplifying the import for a specific bundler, it tells you to import the scss entry file.

scss
@import "~rfs/scss";

That is a copy from the section above. The note itself is correct for the indented syntax, since a bundler resolves the same package path either way, but the path written is the other entry point, and a reader copying the line gets a file written in the other syntax.

The two files are genuinely different, which is why the package ships both: one uses braces and semicolons and the other uses indentation. So this is not a harmless alias. It is the same class of copy-paste error as the stray quote in the Less example, one section apart.

The Less example has a single quote where a dot belongs

The Less section lists the shorthand mixins in a comment block, one per line, and one of the lines does not match its siblings.

Nine of them begin with a dot, which is how a Less mixin is called. One begins with a single quote character instead, so it is commented out as prose rather than usable as a call.

The list covers the four sides of padding and the four sides of margin plus a general form for each, which is eleven entries in all, and exactly one of them is wrong.

Two more things about that section. The list is cut off mid-comment rather than at the end of a line, and the section that would follow it, covering how to pass a property that has no shorthand, is incomplete for the same reason.

None of this changes what the library does. It does mean the comment block a reader is meant to copy from is not trustworthy as a reference, and that the same truncation appears in three of the four syntax sections, which points at how the README was produced rather than at four independent mistakes.

Four examples built through a task runner, four more built directly

The manifest's scripts describe the same four example projects being built two different ways.

There is one example script that runs two groups in parallel. The first group fans out to four more scripts, one per preprocessor, and each of those invokes a task runner against a task file inside that preprocessor's own example directory.

The second group fans out to four scripts as well, named for the same four preprocessors, and these appear to run the examples directly.

So a single example directory exists in two forms, one wired for a task runner and one wired for a plain script invocation, and the repository ships eight build targets where four would do.

The tree backs this up. There are five example directories plus a README, one per preprocessor.

It also explains why the tree has four entry files at the root, one per preprocessor syntax, each named after its extension. They are not imports of a shared core; they are the four faces of the same package, and each example directory exercises one of them.

The stylesheet linter is pointed at two of the four syntaxes

There are two linters in the manifest, and the stylesheet one has a narrow glob.

It runs against files with two extensions, and a configuration file for it sits at the repository root. Those two extensions are the brace-syntax Sass one and the Less one.

That leaves the indented-syntax Sass file, the Stylus file, and the PostCSS JavaScript plugin outside the stylesheet linter entirely, three of the four entry points at the root.

The JavaScript linter covers the rest of the repository, and the test script runs both linters before running the tests, so the omission is not that anything is unchecked, only that three of the four syntaxes get no style checking.

For a project whose entire surface is those four files, the asymmetry is odd. It is the shape you get when a configuration is written for the two syntaxes that existed first and the later two are added without extending the glob.

The expected-output generator calls a compiler that has been retired

One script regenerates the expected stylesheet output, and it names a specific compiler.

It invokes a Node binding for the Sass compiler to compile the test stylesheets into an expected directory, then runs a formatter over the generated files.

That Node binding is the retired one. The Sass project renamed it, and the recommended implementation is the Dart-based compiler, which is what every other tool in this repository has moved to.

So the script that produces the fixtures the tests compare against depends on a package that is no longer the way to compile Sass, while the four example builds and the README's own instructions all assume the current one.

That is the kind of dependency that keeps working long after it is announced as finished, on the assumption that nobody reinstalls from scratch. It also means a contributor who follows the new documentation will produce different expected output than the fixtures in the repository, and the failure will look like a library regression rather than a tooling mismatch.

A bower manifest is still shipped and a bower install is still listed

The installation section lists three package managers, and marks one of them deprecated in the same line.

The recommended route is the standard Node package manager, with the alternative being a different Node package manager. The third line is for a package manager that no longer has an active user base, and the README says so in the parenthetical after the command.

Meanwhile the repository root still contains that package manager's manifest file, and the package manifest's published-files list does not mention it, which means it is in the repository but not necessarily in the published artefact.

The copy-paste installation route is also documented, with a warning: downloading the source files manually works but is not recommended because you lose the ability to manage and update the dependency easily.

So the installation section is honest about all three, including the one it would rather you not use. What it does not do is explain what happens to the four separate entry files if you take the manual route, which is the case where you would need all of them.

The advantage list is about text, and the library now scales anything

Read the four advantages and you are reading a 2017 product description.

Three of the four are about type. Text will not be chopped off at small viewports. Font size will not rescale so small that readability is lost. And the font sizes of all text elements will always stay in relation to one another.

The fourth says you no longer need to rescale padding and margin by hand, which is the feature that arrived when the library stopped being about fonts.

The opening paragraph explains why. It says the engine was initially developed to resize font sizes, hence the abbreviation, and that nowadays it is capable of rescaling basically every value for any property with units, naming margin, padding, border radius and box shadow among them.

So the name is a historical artefact and the advantage list has not caught up. The PostCSS section demonstrates the breadth directly: the same function applied to font size, to padding, to a multi-value padding shorthand, to a four-value box shadow with a colour, to a comma-separated pair of shadows, and to a custom property.

A library named for font sizes that scales box shadows is a documentation problem, not a design one.

Editorial conclusion

Use RFS if you want responsive type and spacing to move together from a single authored value, and if your project already has one of the four supported preprocessors. The output is deliberately simple, one calc expression below a threshold and a media query that restores the authored value above it, which means you can read the result and reason about it without a build step in your head. Three things to check before you adopt it. Which of the four syntaxes you use, because each has its own entry file at the repository root and its own example, and the indented-syntax section of the README points at the brace-syntax path. What your tooling will and will not check, since the stylesheet linter is pointed at only two of the four syntaxes, and the Less path has a known upstream defect around the important flag that the README links rather than works around. And how current it is, since the newest release is from March 2023 while the branch has been pushed to within the last month.

Frequently asked questions

What is RFS and what does it do?

It is an MIT-licensed unit resizing engine for CSS, originally built to resize font sizes, which is where its abbreviation comes from, and now able to rescale almost any value with units for any property, including margin, padding, border radius and box shadow. It is available as Sass, Less, Stylus and PostCSS, calculates values from the browser viewport dimensions, and is installed with npm install rfs or yarn add rfs.

How does RFS generate its CSS?

It emits two rules per value: a calc expression combining a fixed term with a viewport term for viewports below the threshold, and a media query at the minimum viewport width that restores the value you authored. The worked example for four rem produces calc(1.525rem + 3.3vw) and, from 1200 pixels, 4rem. An important flag passed to the mixin is carried into both declarations.

Which preprocessors does RFS support?

Four: Sass in both indented and brace syntax, Less, Stylus and PostCSS. Each has its own entry file at the repository root, its own example directory and its own build script. The PostCSS file is also the package's declared main entry, so a plain require of the package resolves to it. The Less entry point has a known upstream defect around the important flag, which the README links to rather than works around.

How do I install RFS?

The recommended route is a Node package manager, with a different Node package manager as the alternative. A third package manager's install line is still listed but marked deprecated in place, and that package manager's manifest is still in the repository root. Downloading the source files and placing them in the project is documented but explicitly not recommended, because you then have no way to manage and update the dependency.

Is RFS still being worked on?

The repository is not archived and the last push to the default branch main is dated 2026-09-10. The newest release is v10.0.0 from 2023-03-23, which matches the version in the package manifest, while the two releases before it were both published on 2021-09-07 twenty minutes apart. So the manifest version and the newest tag agree, and both sit more than three years behind the branch.

What does RFS do about linting and test fixtures?

The manifest defines two linters: one for JavaScript and one for stylesheets, and the test script runs both before the tests. The stylesheet linter's file pattern covers only the brace-syntax Sass and Less files, so the indented-syntax Sass, Stylus and PostCSS entry points get no style checking. A separate script regenerates the expected stylesheet fixtures by compiling the test stylesheets and formatting the output.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. twbs/rfs on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/twbs-rfs.svg)](https://hysenlabs.com/projects/twbs-rfs)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/twbs-rfs.svg)](https://hysenlabs.com/projects/twbs-rfs)

Was this useful?