✩ Automates responsive resizing ✩

  • By Bootstrap
  • Last update: Dec 28, 2022
  • Comments: 16

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

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 comma, 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

// sass/main.sass

@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 comma, 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 comma, 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 comma, 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

Copyright and license

Code released under the MIT license.

Github

https://github.com/twbs/rfs

Comments(16)

  • 1

    Version 7.1.8 Post-Install Issue

    I've been using the rfs v 7.1.4 since the last 2 months without a problem. I recently started a new Project and did a npm install followed by the project execution.

    I noticed the below error: ERROR in ./src/styles.scss (./node_modules/raw-loader!./node_modules/postcss-loader/lib??embedded!./node_modules/sass-loader/lib/loader.js??ref--14-3!./src/styles.scss) Module build failed: @error "#{$rfs-breakpoint-unit}is not a valid unit for $rfs-breakpoint-unit. Usepx,emorrem."; ^ `` is not a valid unit for $rfs-breakpoint-unit. Usepx,emorrem.

    I reviewed the documentation to check for any breaking changes or whether I had to explicitly specify the rfs-breakpoint-unit (and I tried doing that) but it didn't work.

    On a bit of investigation, I could see that there has been a new version upgrade to v7.1.8.

    I then reverted to the previous version with npm install [email protected] --save and things worked as expected -- no error. (I do see a difference in the packages between 7.1.4 and 7.1.8)

    Am I missing something in the new release ? Please advise.

  • 2

    RFS doesn't work

    Hi,

    I've installed your library and tried to refactor one of my projects to see how it performs. What I've found really strange is that font-size jumps from 48px(viewport wider than 1200px) to 24px (viewport on 1199px and below).

    Shouldn't it fluidly resize?

    Thanks.

  • 3

    Any way to use css variables?

    On my current project i am forced to use css variables instead of scss variables. But i was not a ble to make it in this way work: @include font-size(var(--h6-font-size)); Someone think it will be possible to use css vars any time?

  • 4

    Add function that just returns the calc() value for a specific property

    When using a separate file for variables in a project it would be very useful to have a function in rfs, that only returns the calc() value for a specific property.

    E.g. instead of using the mixin @include font-size(30px) I would like to do the following:

    vars.scss:

    $font-size-1: new-rfs-font-size-function(30px);
    

    file1.scss

    @import './vars.scss'
    
    .someClass {
       font-size: $font-size-1;
    }
    

    That would really help sometimes, when it comes to elements with position: fixed and margins set with rfs.

  • 5

    Not mobile-first

    What are your thoughts on changing the algorithm to be mobile-first (i.e. take font size on mobile as the argument and use min-width in the output)? Ultimately the effect could be the same, but readability could be better for those accustomed to writing for mobile-first (of which there are many).

    Or another option might be to just add a mixin for mobile-first sizing.

    See: Precise control over responsive typography

  • 6

    $rfs-two-dimensional: true wrong media queries?

    at the moment the media queries for two dimensional mode are generated to look like this:

    @media (min-width: 1200px), (min-height: 1200px) {

    I think this leads to undesired behavior for screens with very high or very low aspect ratio.

    better would be to change this to:

    @media (min-width: 1200px) and (min-height: 1200px) {

  • 7

    fallback values for missing calc() browser support

    I would like to suggest adding fallback values in case the browser doesnt support calc().

    This could be easily done by adding the fallback value at the beginning of the generated css file.

  • 8

    Bump stylelint from 12.0.1 to 13.0.0

    Bumps stylelint from 12.0.1 to 13.0.0.

    Release notes

    Sourced from stylelint's releases.

    13.0.0

    • Removed: Node.js 8.x support. Node.js 10 is now required. We can guarantee stylelint works on the latest Node.js 10 release. (#4500).
    • Removed: types declarations for Flow (#4451).
    • Changed: globby was updated to v10. Now only forward-slashes (/) should be used as directory separator in globs. Refer to glob pattern syntax. Most of the users wouldn't need to change anything, but Windows users might need to update their globs. (#4254).
    • Added: unit-no-unknown support for x unit (#4427).
    • Fixed: --report-invalid-scope-disables crash when no rules specified (#4498).
    • Fixed: media-feature-parentheses-space-inside false negatives for multiple spaces (#4513).
    • Fixed: selector-type-no-unknown false positives for SVG tags (#4495).
    • Fixed: unit-no-unknown false positives for Sass map keys (#4450).
    • Fixed: value-list-comma-newline-after false positives for shared-line comments (#4482).
    • Fixed: consistently check that selectors are standard before passing to the parser (#4483).
    • Fixed: overlapping disabled ranges edge case (#4497).
    Changelog

    Sourced from stylelint's changelog.

    13.0.0

    • Removed: Node.js 8.x support. Node.js 10 is now required. We can guarantee stylelint works on the latest Node.js 10 release. (#4500).
    • Removed: types declarations for Flow (#4451).
    • Changed: globby was updated to v10. Now only forward-slashes (/) should be used as directory separator in globs. Refer to glob pattern syntax. Most of the users wouldn't need to change anything, but Windows users might need to update their globs. (#4254).
    • Added: unit-no-unknown support for x unit (#4427).
    • Fixed: --report-invalid-scope-disables crash when no rules specified (#4498).
    • Fixed: media-feature-parentheses-space-inside false negatives for multiple spaces (#4513).
    • Fixed: selector-type-no-unknown false positives for SVG tags (#4495).
    • Fixed: unit-no-unknown false positives for Sass map keys (#4450).
    • Fixed: value-list-comma-newline-after false positives for shared-line comments (#4482).
    • Fixed: consistently check that selectors are standard before passing to the parser (#4483).
    • Fixed: overlapping disabled ranges edge case (#4497).
    Commits

    Dependabot compatibility score

    You can trigger a rebase of this PR by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)
  • 9

    padding-bottom mixin is using font-size property?

    I got a strange issue. Here is the SCSS I'm using:

    
    .custom {
        &.jumbotron {
            h2 {
                @include font-size(4.8rem);
                color:$primary;
                font-weight:700;
                div+div {
                    font-weight:500;
                }
                @include padding-bottom(5.1rem);
            }
        }
    }
    
    

    The result CSS checked in Browser Inspector is as follows:

    .custom.jumbotron h2 {
        font-size: 4.8rem;
        color: 
        #2e3192;
        font-weight: 700;
        font-size: 5.1rem !important;
    }
    

    Whats going on. Am I missing something? Same happens when I'm using rfs() mixin. The rfs version is 9.0.0

  • 10

    Switch to lefthook

    Ditch Husky in favor of https://github.com/Arkweid/lefthook. In the future we can split the tests more, eg. only run xo when something is changed in js files or prevent the tests from running when .md files are changed.

    Fixes https://github.com/twbs/rfs/issues/149

  • 11

    It's not you, it's me: Bootstrap 4.3.1/RFS not generating media query at sub 1200px threshold

    I've recently updated our project's Bootstrap version to the latest (4.3.1). I'm importing all of Bootstrap via node_modules. I haven't modified the RFS mixin in any way. I'm using the version that ships with Bootstrap 4.3.1 as configured by default. Bootstrap is compiling just fine with the exception of this particular RFS issue.


    The media query is not being generated in my current environment. It is a large project with many dependencies and I'm pretty much shooting the dark trying to come up with a reduced test case. I realize that that makes helping me with this issue very difficult if not impossible. But I'm desperate at this point.

    Also, I'm reasonably sure (say, 99%) this is a me problem, not an RFS problem, but I haven't been able to sort the issue.

    I'm invoking the mixin as follows:

    .my-test {
       @include rfs(3rem);
    }
    

    Note that this font size is greater than the minimum font size of 1.25rem at or below which no scaling will take place. So, that's not the issue.

    I've also tried invoking the aliased versions of the mixin:

    .my-test {
       @include responsive-font-size(3rem);
    }
    

    and

    .my-test {
       @include font-size(3rem);
    }
    

    I've tried it with rem, px, and unitless values.

    The mixin is definitely being recognized and is halfway working. I.e., it compiles out to regular CSS without a hitch.

    So, the code above does indeed generate the following CSS:

    .my-test {
      font-size: 3rem;
    }
    

    But, again, no media query (at 1200px) is being generated by the mixin in my current environment and, thus, no downward scaling is taking place below the 1200px threshold.

    At screen widths below 1200px, I would expect to see something similar to the following:

    @media (max-width: 1200px) {
      .my-test {
        font-size: calc(1.525rem + 3.3vw);
      }
    }
    

    But, no dice.

    Again, I haven't modified the default configuration of the RFS mixin in any way, and it does appear to be halfway working, as it's compiling out to CSS.

    Tried in my coworker's environment and he gets the same results. But, that's expected, as we have pretty similar local environments, I suppose.

    I hate to clutter up your issues with something that's in all likelihood not an issue with RFS (which is awesome -- using it on other projects), but SO hasn't turned up any leads so far.

    Any suggestions for how to debug?

    Thanks.

  • 12

    Build(deps): Bump decode-uri-component from 0.2.0 to 0.2.2

    Bumps decode-uri-component from 0.2.0 to 0.2.2.

    Release notes

    Sourced from decode-uri-component's releases.

    v0.2.2

    • Prevent overwriting previously decoded tokens 980e0bf

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.1...v0.2.2

    v0.2.1

    • Switch to GitHub workflows 76abc93
    • Fix issue where decode throws - fixes #6 746ca5d
    • Update license (#1) 486d7e2
    • Tidelift tasks a650457
    • Meta tweaks 66e1c28

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.1

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the Security Alerts page.
  • 13

    rem and px have incompatible units in rfs-breakpoint

    Hey, i'm trying to configure the RFS values in a scss stylesheet and get the following error: 7065rem and 1440px have incompatible units.

    image

    I previously used the same settings but in a stylus stylesheet and had no problems. Is this a bug or a feature? 😁

    @import "node_modules/rfs/scss";
    $rfs-base-value: 1.5rem;
    $rfs-breakpoint: 1440px; // this causes the error
    //$rfs-breakpoint: 90rem; // this works
    $rfs-two-dimensional: true;
    
  • 14

    Build(deps): Bump terser from 5.12.1 to 5.14.2

    Bumps terser from 5.12.1 to 5.14.2.

    Changelog

    Sourced from terser's changelog.

    v5.14.2

    • Security fix for RegExps that should not be evaluated (regexp DDOS)
    • Source maps improvements (#1211)
    • Performance improvements in long property access evaluation (#1213)

    v5.14.1

    • keep_numbers option added to TypeScript defs (#1208)
    • Fixed parsing of nested template strings (#1204)

    v5.14.0

    • Switched to @​jridgewell/source-map for sourcemap generation (#1190, #1181)
    • Fixed source maps with non-terminated segments (#1106)
    • Enabled typescript types to be imported from the package (#1194)
    • Extra DOM props have been added (#1191)
    • Delete the AST while generating code, as a means to save RAM

    v5.13.1

    • Removed self-assignments (varname=varname) (closes #1081)
    • Separated inlining code (for inlining things into references, or removing IIFEs)
    • Allow multiple identifiers with the same name in var destructuring (eg var { a, a } = x) (#1176)

    v5.13.0

    • All calls to eval() were removed (#1171, #1184)
    • source-map was updated to 0.8.0-beta.0 (#1164)
    • NavigatorUAData was added to domprops to avoid property mangling (#1166)
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the Security Alerts page.
  • 15

    Use Sass Modules (dart-sass)

    Some functions in the scss files are deprecated and will be removed next Year. So dont use lib-sass anymore and change to dart-sass. https://sass-lang.com/blog/libsass-is-deprecated

    Usefull Link: https://sass-lang.com/documentation/at-rules

    @use "sass:math";
    @use "sass:meta";
    @use "sass:string";
    
    
    // stylelint-disable property-blacklist, scss/dollar-variable-default
    
    // SCSS RFS mixin
    //
    // Automated responsive values for font sizes, paddings, margins and much more
    //
    // Licensed under MIT (https://github.com/twbs/rfs/blob/main/LICENSE)
    
    // Configuration
    
    // Base value
    $rfs-base-value: 1.25rem !default;
    $rfs-unit: rem !default;
    
    @if $rfs-unit != rem and $rfs-unit != px {
      @error "`#{$rfs-unit}` is not a valid unit for $rfs-unit. Use `px` or `rem`.";
    }
    
    // Breakpoint at where values start decreasing if screen width is smaller
    $rfs-breakpoint: 1200px !default;
    $rfs-breakpoint-unit: px !default;
    
    @if $rfs-breakpoint-unit != px and $rfs-breakpoint-unit != em and $rfs-breakpoint-unit != rem {
      @error "`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.";
    }
    
    // Resize values based on screen height and width
    $rfs-two-dimensional: false !default;
    
    // Factor of decrease
    $rfs-factor: 10 !default;
    
    @if meta.type-of($rfs-factor) != number or $rfs-factor <= 1 {
      @error "`#{$rfs-factor}` is not a valid  $rfs-factor, it must be greater than 1.";
    }
    
    // Mode. Possibilities: "min-media-query", "max-media-query"
    $rfs-mode: min-media-query !default;
    
    // Generate enable or disable classes. Possibilities: false, "enable" or "disable"
    $rfs-class: false !default;
    
    // 1 rem = $rfs-rem-value px
    $rfs-rem-value: 16 !default;
    
    // Safari iframe resize bug: https://github.com/twbs/rfs/issues/14
    $rfs-safari-iframe-resize-bug-fix: false !default;
    
    // Disable RFS by setting $enable-rfs to false
    $enable-rfs: true !default;
    
    // Cache $rfs-base-value unit
    $rfs-base-value-unit: math.unit($rfs-base-value);
    
    // Remove px-unit from $rfs-base-value for calculations
    @if $rfs-base-value-unit == px {
      $rfs-base-value: $rfs-base-value / ($rfs-base-value * 0 + 1);
    }
    @else if $rfs-base-value-unit == rem {
      $rfs-base-value: $rfs-base-value / ($rfs-base-value * 0 + 1 / $rfs-rem-value);
    }
    
    // Cache $rfs-breakpoint unit to prevent multiple calls
    $rfs-breakpoint-unit-cache: math.unit($rfs-breakpoint);
    
    // Remove unit from $rfs-breakpoint for calculations
    @if $rfs-breakpoint-unit-cache == px {
      $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);
    }
    @else if $rfs-breakpoint-unit-cache == rem or $rfs-breakpoint-unit-cache == "em" {
      $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);
    }
    
    // Calculate the media query value
    $rfs-mq-value: if($rfs-breakpoint-unit == px, #{$rfs-breakpoint}px, #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit});
    $rfs-mq-property-width: if($rfs-mode == max-media-query, max-width, min-width);
    $rfs-mq-property-height: if($rfs-mode == max-media-query, max-height, min-height);
    
    // Internal mixin used to determine which media query needs to be used
    @mixin _rfs-media-query {
      @if $rfs-two-dimensional {
        @if $rfs-mode == max-media-query {
          @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}), (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {
            @content;
          }
        }
        @else {
          @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) and (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {
            @content;
          }
        }
      }
      @else {
        @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) {
          @content;
        }
      }
    }
    
    // Internal mixin that adds disable classes to the selector if needed.
    @mixin _rfs-rule {
      @if $rfs-class == disable and $rfs-mode == max-media-query {
        // Adding an extra class increases specificity, which prevents the media query to override the property
        &,
        .disable-rfs &,
        &.disable-rfs {
          @content;
        }
      }
      @else if $rfs-class == enable and $rfs-mode == min-media-query {
        .enable-rfs &,
        &.enable-rfs {
          @content;
        }
      }
      @else {
        @content;
      }
    }
    
    // Internal mixin that adds enable classes to the selector if needed.
    @mixin _rfs-media-query-rule {
    
      @if $rfs-class == enable {
        @if $rfs-mode == min-media-query {
          @content;
        }
    
        @include _rfs-media-query {
          .enable-rfs &,
          &.enable-rfs {
            @content;
          }
        }
      }
      @else {
        @if $rfs-class == disable and $rfs-mode == min-media-query {
          .disable-rfs &,
          &.disable-rfs {
            @content;
          }
        }
        @include _rfs-media-query {
          @content;
        }
      }
    }
    
    // Helper function to get the formatted non-responsive value
    @function rfs-value($values) {
      // Convert to list
      $values: if(meta.type-of($values) != list, ($values,), $values);
    
      $val: '';
    
      // Loop over each value and calculate value
      @each $value in $values {
        @if $value == 0 {
          $val: $val + ' 0';
        }
        @else {
          // Cache $value unit
          $unit: if(meta.type-of($value) == "number", math.unit($value), false);
    
          @if $unit == px {
            // Convert to rem if needed
            $val: $val + ' ' + if($rfs-unit == rem, #{$value / ($value * 0 + $rfs-rem-value)}rem, $value);
          }
          @else if $unit == rem {
            // Convert to px if needed
            $val: $val + ' ' + if($rfs-unit == px, #{$value / ($value * 0 + 1) * $rfs-rem-value}px, $value);
          }
          @else {
            // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value
            $val: $val + ' ' + $value;
          }
        }
      }
    
      // Remove first space
      @return string.unquote(string.slice($val, 2));
    }
    
    // Helper function to get the responsive value calculated by RFS
    @function rfs-fluid-value($values) {
      // Convert to list
      $values: if(meta.type-of($values) != list, ($values,), $values);
    
      $val: '';
    
      // Loop over each value and calculate value
      @each $value in $values {
        @if $value == 0 {
          $val: $val + ' 0';
        }
    
        @else {
          // Cache $value unit
          $unit: if(meta.type-of($value) == "number", math.unit($value), false);
    
          // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value
          @if not $unit or $unit != px and $unit != rem {
            $val: $val + ' ' + $value;
          }
    
          @else {
            // Remove unit from $value for calculations
            $value: $value / ($value * 0 + if($unit == px, 1, 1 / $rfs-rem-value));
    
            // Only add the media query if the value is greater than the minimum value
            @if math.abs($value) <= $rfs-base-value or not $enable-rfs {
              $val: $val + ' ' +  if($rfs-unit == rem, #{$value / $rfs-rem-value}rem, #{$value}px);
            }
            @else {
              // Calculate the minimum value
              $value-min: $rfs-base-value + (math.abs($value) - $rfs-base-value) / $rfs-factor;
    
              // Calculate difference between $value and the minimum value
              $value-diff: math.abs($value) - $value-min;
    
              // Base value formatting
              $min-width: if($rfs-unit == rem, #{$value-min / $rfs-rem-value}rem, #{$value-min}px);
    
              // Use negative value if needed
              $min-width: if($value < 0, -$min-width, $min-width);
    
              // Use `vmin` if two-dimensional is enabled
              $variable-unit: if($rfs-two-dimensional, vmin, vw);
    
              // Calculate the variable width between 0 and $rfs-breakpoint
              $variable-width: #{$value-diff * 100 / $rfs-breakpoint}#{$variable-unit};
    
              // Return the calculated value
              $val: $val + ' calc(' + $min-width + if($value < 0, ' - ', ' + ') + $variable-width + ')';
            }
          }
        }
      }
    
      // Remove first space
      @return string.unquote(string.slice($val, 2));
    }
    
    // RFS mixin
    @mixin rfs($values, $property: font-size) {
      @if $values != null {
        $val: rfs-value($values);
        $fluidVal: rfs-fluid-value($values);
    
        // Do not print the media query if responsive & non-responsive values are the same
        @if $val == $fluidVal {
          #{$property}: $val;
        }
        @else {
          @include _rfs-rule {
            #{$property}: if($rfs-mode == max-media-query, $val, $fluidVal);
    
            // Include safari iframe resize fix if needed
            min-width: if($rfs-safari-iframe-resize-bug-fix, (0 * 1vw), null);
          }
    
          @include _rfs-media-query-rule {
            #{$property}: if($rfs-mode == max-media-query, $fluidVal, $val);
          }
        }
      }
    }
    
    // Shorthand helper mixins
    @mixin font-size($value) {
      @include rfs($value);
    }
    
    @mixin padding($value) {
      @include rfs($value, padding);
    }
    
    @mixin padding-top($value) {
      @include rfs($value, padding-top);
    }
    
    @mixin padding-right($value) {
      @include rfs($value, padding-right);
    }
    
    @mixin padding-bottom($value) {
      @include rfs($value, padding-bottom);
    }
    
    @mixin padding-left($value) {
      @include rfs($value, padding-left);
    }
    
    @mixin margin($value) {
      @include rfs($value, margin);
    }
    
    @mixin margin-top($value) {
      @include rfs($value, margin-top);
    }
    
    @mixin margin-right($value) {
      @include rfs($value, margin-right);
    }
    
    @mixin margin-bottom($value) {
      @include rfs($value, margin-bottom);
    }
    
    @mixin margin-left($value) {
      @include rfs($value, margin-left);
    }
    
  • 16

    rfs() doens't work inside calc()

    I'm using RFS v9.0.3 with PostCSS. The rfs() function doesn't work when wrapped in a calc() function.

    Input:

    margin-right: calc(rfs(2rem) * 2);
    

    Output:

    margin-right: rfs(2rem) * 2;
    

    Expected Output:

    margin-right: calc(calc(1.325rem + 0.9vw) * 2);