npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

fluid-px

v3.1.0

Published

Fluid responsive CSS values using linear interpolation — scale any CSS property smoothly between two screen sizes with calc(). Zero-config Tailwind v3 and v4 support. Works with inline styles and Tailwind arbitrary values. No media queries, no clamp, no l

Readme

fluid-px

Fluid responsive values for any CSS property — no media queries, no breakpoints, no clamp.

Scales smoothly between two screen sizes using a single CSS max() expression. Define a value at mobile and desktop, it interpolates in between — and keeps growing proportionally on screens larger than your max so the design stays consistent on ultrawide displays.

import { fluid, tw, cls } from 'fluid-px'
import cls from 'fluid-px/cls'

// inline style
<h1 style={{ fontSize: fluid(24, 56) }}>

// tailwind arbitrary value
<h1 className={`text-[${tw(24, 56)}]`}>

// tailwind class builder (cleanest)
<h1 className={cls.text(24, 56)}>

Works with React, Next.js, Vue, Angular, Svelte, Payload CMS — any framework, JavaScript or TypeScript.


What's included

| | | |---|---| | fluid() | Inline style value — grows proportionally above max screen | | tw() | Tailwind arbitrary value — no spaces, same behavior | | fluid-px/cls | Tailwind class builders — cls.text(24, 56) instead of `text-[${tw(24, 56)}]` | | at() | Real px number at any screen width, including overflow | | configure() | Set global screen defaults at runtime | | npx fluid-px scan | Tailwind v4 — generate fluid-classes.css from your source files | | npx fluid-px generate | Generate CSS vars + Tailwind tokens from a config file | | npx fluid-px preview | Print a value table including overflow widths | | npx fluid-px audit | Scan your codebase for breakpoint-heavy classNames | | fluid-px/image | Generate sizes strings for Next.js <Image> |


How it works

You pass a pixel value for mobile and a pixel value for desktop. The package computes a max() expression that:

  • Scales linearly between your two screen sizes
  • Keeps growing proportionally above your max screen — so the design looks the same on ultrawide monitors
fluid(24, 56)  with screens 375px → 1440px

At  375px → 24px    (your mobile baseline)
At  768px → 35.8px  (smooth interpolation)
At 1440px → 56px    (your desktop baseline)
At 1920px → 74.7px  (proportional — keeps growing)
At 2560px → 99.6px  (proportional — keeps growing)
At 3840px → 149px   (proportional — keeps growing)

The CSS value looks like this:

max(calc(4.7324px + 3.0047vw), calc(2.5vw))
  • Below max screen: the calc(intercept + slope*vw) linear term wins
  • Above max screen: the calc(proportionalVw) term wins — seamless transition, no jump
  • No JavaScript runs in the browser
  • No media queries
  • No layout shifts

Installation

npm install fluid-px

That's it. The postinstall script detects your Tailwind version and wires everything up automatically.

What happens on install

Tailwind v3

Your tailwind.config.js is patched automatically:

// Added automatically — no manual step needed
const { withFluidPx } = require('fluid-px/extractor')
// ...your existing config...
module.exports = withFluidPx(module.exports)

Every build re-evaluates your cls.*() and tw() calls and generates the matching CSS. Zero ongoing maintenance.

Tailwind v4

Three things happen automatically:

  1. Your source files (./src, ./app, etc.) are scanned for cls.*() and tw() calls
  2. fluid-classes.css is written alongside your CSS entry with @source inline(...) directives
  3. @import "./fluid-classes.css" is injected into your globals.css
/* globals.css — @import injected automatically */
@import "tailwindcss";
@import "./fluid-classes.css";

One additional step for v4: add fluid-px scan to your prebuild script so the CSS file stays up to date when you add new fluid-px calls:

{
  "scripts": {
    "prebuild": "fluid-px scan",
    "build": "next build"
  }
}

No Tailwind

If you're not using Tailwind, use fluid() for inline styles — no configuration needed.


Optional: set your screen sizes

npx fluid-px setup
📐  fluid-px — set your default screen sizes
    Press Enter to keep the shown default.

  Min screen width in px [430]: 375
  Max screen width in px [1920]: 1440

✅  fluid-px defaults saved: 375px → 1440px

Re-run at any time to change your defaults. Default until you run setup: 430px → 1920px.


API

fluid(min, max, options?)

Returns a max() CSS value with spaces — use as an inline style value.

Scales linearly from min at minScreen to max at maxScreen, then continues growing proportionally above maxScreen.

import { fluid } from 'fluid-px'

// font size that scales from 16px to 48px, keeps growing beyond max screen
<h1 style={{ fontSize: fluid(16, 48) }}>

// padding that scales from 16px to 80px on both sides
<nav style={{ paddingLeft: fluid(16, 80), paddingRight: fluid(16, 80) }}>

// gap that scales from 8px to 24px
<div style={{ gap: fluid(8, 24) }}>

// border radius that scales from 4px to 16px
<div style={{ borderRadius: fluid(4, 16) }}>

// any CSS property — you control the property name
<div style={{ marginTop: fluid(24, 64), letterSpacing: fluid(-0.5, -1) }}>

Output:

fluid(16, 48)  →  "max(calc(4.7324px + 3.0047vw), calc(3.3333vw))"

tw(min, max, options?)

Returns the same max() value without spaces — use inside Tailwind arbitrary value brackets [...].

Tailwind breaks on spaces inside arbitrary values, so use tw() instead of fluid() for classNames.

import { tw } from 'fluid-px'

// font size
<h1 className={`text-[${tw(16, 48)}]`}>

// padding
<nav className={`px-[${tw(16, 80)}]`}>

// multiple fluid values in one className
<div className={`gap-[${tw(8, 24)}] rounded-[${tw(4, 16)}] h-[${tw(60, 100)}]`}>

// combine with regular tailwind classes
<section className={`flex flex-col items-center py-[${tw(32, 96)}]`}>

Output:

tw(16, 48)  →  "max(calc(4.7324px+3.0047vw),calc(3.3333vw))"

fluid-px/cls — Tailwind class builders

A set of helpers that return complete, ready-to-use Tailwind class strings so you don't have to wrap tw() in template literal brackets yourself.

// Before (tw() — still valid)
<h1 className={`text-[${tw(24, 56)}]`}>

// After (cls — cleaner)
<h1 className={cls.text(24, 56)}>

Import

// default import — cls object
import cls from 'fluid-px/cls'

// named imports — individual helpers
import { text, px, gap } from 'fluid-px/cls'

Usage

import cls from 'fluid-px/cls'

// typography
<h1 className={cls.text(24, 56)}>
<p  className={cls.text(14, 16)}>
<p  className={`${cls.text(14, 16)} ${cls.leading(20, 28)}`}>

// padding
<nav className={cls.px(16, 80)}>
<section className={cls.py(32, 96)}>

// gap
<div className={`flex flex-col ${cls.gap(12, 32)}`}>

// sizing
<img className={`${cls.w(79, 170)} ${cls.h(32, 62)}`}>

// border radius
<div className={cls.rounded(8, 20)}>

// combine with regular Tailwind classes
<section className={`flex flex-col items-center ${cls.py(32, 96)} ${cls.gap(16, 40)}`}>

All helpers pass options through to tw():

cls.text(24, 56, { minScreen: 375, maxScreen: 1440 })
cls.px(16, 80, { unit: 'rem' })
cls.gap(8, 24, { minScreen: 320, maxScreen: 768 })

Available helpers

| Import | Returns | CSS property | |--------|---------|--------------| | cls.text | text-[...] | font-size | | cls.leading | leading-[...] | line-height | | cls.tracking | tracking-[...] | letter-spacing | | cls.p | p-[...] | padding | | cls.px | px-[...] | padding-left + right | | cls.py | py-[...] | padding-top + bottom | | cls.pt | pt-[...] | padding-top | | cls.pb | pb-[...] | padding-bottom | | cls.pl | pl-[...] | padding-left | | cls.pr | pr-[...] | padding-right | | cls.ps | ps-[...] | padding-inline-start | | cls.pe | pe-[...] | padding-inline-end | | cls.m | m-[...] | margin | | cls.mx | mx-[...] | margin-left + right | | cls.my | my-[...] | margin-top + bottom | | cls.mt | mt-[...] | margin-top | | cls.mb | mb-[...] | margin-bottom | | cls.ml | ml-[...] | margin-left | | cls.mr | mr-[...] | margin-right | | cls.ms | ms-[...] | margin-inline-start | | cls.me | me-[...] | margin-inline-end | | cls.gap | gap-[...] | gap | | cls.gapX | gap-x-[...] | column-gap | | cls.gapY | gap-y-[...] | row-gap | | cls.w | w-[...] | width | | cls.h | h-[...] | height | | cls.size | size-[...] | width + height | | cls.minW | min-w-[...] | min-width | | cls.maxW | max-w-[...] | max-width | | cls.minH | min-h-[...] | min-height | | cls.maxH | max-h-[...] | max-height | | cls.rounded | rounded-[...] | border-radius | | cls.border | border-[...] | border-width | | cls.top | top-[...] | top | | cls.right | right-[...] | right | | cls.bottom | bottom-[...] | bottom | | cls.left | left-[...] | left | | cls.inset | inset-[...] | inset |


Options

Both fluid() and tw() accept an optional third argument:

fluid(min, max, { minScreen?, maxScreen?, unit? })
tw(min, max,    { minScreen?, maxScreen?, unit? })

Per-call screen override

Override the screen range for a single value without changing global defaults:

// this value only scales between 320px and 768px
fluid(14, 18, { minScreen: 320, maxScreen: 768 })

// useful for components that only appear on mobile
tw(12, 16, { minScreen: 320, maxScreen: 600 })

unit: 'rem'

Output rem units instead of px. Pass px values as always — division by 16 is handled automatically.

fluid(16, 48, { unit: 'rem' })
// → "max(calc(0.2958rem + 0.1878vw), calc(0.2083vw))"

tw(16, 48, { unit: 'rem' })
// → "max(calc(0.2958rem+0.1878vw),calc(0.2083vw))"

Useful when your design system or browser accessibility settings depend on rem for font sizes.

unit: 'cqi'

Output cqi units — scales relative to the parent container's width instead of the viewport. Use this for components inside sidebars, grids, cards, or modals where viewport width doesn't reflect the component's actual space.

fluid(14, 24, { unit: 'cqi' })
// → "calc(4.7324px + 3.0047cqi)"

Note: cqi uses plain calc() — container sizes are bounded by their parent so proportional overflow does not apply.

Requires container-type: inline-size on the parent:

.sidebar {
  container-type: inline-size;
}
<aside className="sidebar">
  <h2 style={{ fontSize: fluid(14, 24, { unit: 'cqi' }) }}>
    Scales with sidebar width, not viewport
  </h2>
</aside>

at(min, max, screenWidth, options?)

Returns the actual rendered pixel value at a given screen width. Matches exactly what the browser computes from fluid() — including proportional overflow above maxScreen.

import { at } from 'fluid-px'

at(16, 48, 375)   // → 16      (mobile baseline)
at(16, 48, 768)   // → 27.81
at(16, 48, 1440)  // → 48      (desktop baseline)
at(16, 48, 1920)  // → 64      (proportional overflow)
at(16, 48, 2560)  // → 85.33   (proportional overflow)
at(16, 48, 3840)  // → 128     (proportional overflow)

// with screen override
at(16, 48, 768, { minScreen: 375, maxScreen: 1440 })  // → 27.81

configure(options)

Override global screen defaults at runtime. Call once at your app's entry point before any fluid() or tw() calls.

import { configure } from 'fluid-px'
configure({ minScreen: 375, maxScreen: 1440 })

Where to call it:

// Next.js App Router — app/layout.tsx
import { configure } from 'fluid-px'
configure({ minScreen: 375, maxScreen: 1440 })

// Next.js Pages Router — pages/_app.tsx
import { configure } from 'fluid-px'
configure({ minScreen: 375, maxScreen: 1440 })

// React / Vite — main.tsx
import { configure } from 'fluid-px'
configure({ minScreen: 375, maxScreen: 1440 })

If you already ran npx fluid-px setup, you don't need configure() — your screen sizes are already saved.


Defaults priority

Screen sizes are resolved in this order (highest to lowest priority):

| Source | How | |--------|-----| | configure() | Runtime JS call | | Env vars | FLUID_MIN_SCREEN / FLUID_MAX_SCREEN | | npx fluid-px setup | Interactive prompt | | Built-in fallback | 430px → 1920px |


Container / CI / Cloud Run environments

Set environment variables — no interactive prompt needed.

FLUID_MIN_SCREEN=375
FLUID_MAX_SCREEN=1440

Set them in:

  • Google Cloud Run → Edit Service → Variables & Secrets
  • DockerENV FLUID_MIN_SCREEN=375 in Dockerfile
  • GitHub Actions / CI → repository secrets or env block

Runtime env vars are read when your app starts, so no rebuild is required when you change them.


Validation warnings

In development (NODE_ENV !== 'production'), the package warns you in the console when something looks wrong:

fluid(16, 16)
// ⚠ [fluid-px] min and max are equal (16) — no fluid scaling will occur

fluid(undefined, 48)
// ⚠ [fluid-px] min or max is not a number

fluid(16, 48, { minScreen: 1920, maxScreen: 375 })
// ⚠ [fluid-px] minScreen (1920) must be less than maxScreen (375) — scaling will be broken

Warnings are silenced in production automatically.


TypeScript

Types are included — no @types package needed.

import { fluid, tw, at, configure } from 'fluid-px'

const fontSize: string = fluid(16, 48)
const twClass: string  = tw(16, 48)
const value: number    = at(16, 48, 2560)  // 85.33 — accounts for overflow

CLI

npx fluid-px setup

Set or update your default screen sizes interactively.

npx fluid-px setup

npx fluid-px scan [dir]

Tailwind v4 only. Scans your source files for cls.*() and tw() calls, evaluates each one, and writes fluid-classes.css with @source inline(...) directives so Tailwind v4 generates the correct CSS.

npx fluid-px scan                    # scan ./src ./app ./pages ./components
npx fluid-px scan ./src              # scan a specific directory
npx fluid-px scan --output ./app/globals/fluid-classes.css
npx fluid-px scan --watch            # re-scan on file changes (dev mode)

| Flag | Default | Description | |------|---------|-------------| | [dir] | ./src ./app ./pages ./components | Directory (or directories) to scan | | --output <path> | ./fluid-classes.css | Output CSS file path | | --watch | — | Re-scan automatically when source files change |

Generated output:

/* AUTO-GENERATED by fluid-px — do not edit manually */
/* Re-run: npx fluid-px scan                          */

@source inline("text-[max(calc(...))] px-[max(...)] gap-[max(...)]");

Add to your prebuild script to keep it current:

{
  "scripts": {
    "prebuild": "fluid-px scan",
    "dev": "fluid-px scan --watch & next dev"
  }
}

npx fluid-px preview <min> <max>

Print a table of actual pixel values at common screen widths, including overflow widths above your max screen. Useful for verifying a value before using it.

npx fluid-px preview 16 48
npx fluid-px preview 16 48 --minScreen 375 --maxScreen 1440

Output:

📐  fluid(16, 48)  [screens: 375px → 1440px]

  320px   →  14.35px
  375px   →  16px    ← min
  430px   →  17.65px
  768px   →  27.81px
  1024px  →  35.5px
  1280px  →  43.19px
  1440px  →  48px    ← max
  1920px  →  64px

  Overflow (proportional beyond 1440px):
  2560px  →  85.33px  ← grows with screen
  3840px  →  128px    ← grows with screen

npx fluid-px generate

Generate CSS custom properties and Tailwind tokens from a config file. See the Config-file workflow section below.

npx fluid-px generate
npx fluid-px generate --config ./path/to/fluid.config.js

npx fluid-px audit [dir]

Scan your codebase for elements that use 3 or more Tailwind breakpoint variants on the same CSS property — exactly the cases that fluid-px can replace with a single smooth value.

npx fluid-px audit ./src
npx fluid-px audit ./src --min-breakpoints 4
npx fluid-px audit ./src --json

Options:

| Flag | Default | Description | |------|---------|-------------| | [dir] | . | Directory to scan (recursive) | | --min-breakpoints <n> | 3 | Minimum number of responsive breakpoints to flag | | --json | — | Output machine-readable JSON instead of the human report |

Example output:

  Scanning 87 files in src...

  components/HeroText.js:5
    text-*  →  5 breakpoints
    xs:text-4xl  min-[800px]:text-[40px]  min-[1023px]:text-3xl  min-[1270px]:text-5xl  2xl:text-[2.7rem]
    Suggestion (30px → 48px):
      inline style:   style={{ fontSize: fluid(30, 48) }}
      tailwind arb:   className={`text-[${tw(30, 48)}]`}
      config token:   fontSize: { 'name': [30, 48] }

  Found 14 elements with 3+ breakpoints across 8 files.

What it skips: node_modules/, .next/, .git/, dist/, build/.


Manual Tailwind setup

The postinstall script handles this automatically. If you need to configure manually (e.g. monorepo, custom setup):

Tailwind v3

// tailwind.config.js
const { withFluidPx } = require('fluid-px/extractor')

module.exports = withFluidPx({
  content: ['./src/**/*.{js,ts,jsx,tsx}'],
  theme: { extend: {} },
  plugins: [],
})
// tailwind.config.ts (ESM)
import { withFluidPx } from 'fluid-px/extractor'

const config = {
  content: ['./src/**/*.{js,ts,jsx,tsx}'],
  theme: { extend: {} },
  plugins: [],
}

export default withFluidPx(config)

Tailwind v4

Run the scan manually, then import the output in your CSS entry:

npx fluid-px scan
/* globals.css */
@import "tailwindcss";
@import "./fluid-classes.css";

fluid-px/image — Next.js image sizes

import { imageSizes, configureImage } from 'fluid-px/image'

Generates the sizes attribute string for Next.js <Image> (or any <img> with srcSet). The sizes attribute tells the browser how wide the image will be at each viewport width, so it downloads the correctly-sized source.

imageSizes uses the same max() formula as fluid() — including proportional overflow above maxScreen — so the browser always downloads the right image size even on ultrawide screens.

Setup (optional)

If you use named tokens from fluid.config.js, call configureImage once at your app entry point:

// Next.js App Router — app/layout.js
import { configureImage } from 'fluid-px/image'
import fluidConfig from './fluid.config.js'

configureImage({ config: fluidConfig })

After that, token names resolve automatically everywhere.

imageSizes(minPx, maxPx, options?)

Generate from explicit pixel values — mirrors the fluid(min, max) signature.

import { imageSizes } from 'fluid-px/image'

// Image that scales from 79px on mobile to 170px on desktop, keeps growing on ultrawide
<Image
  src={logo}
  sizes={imageSizes(79, 170)}
/>
// → "(max-width: 375px) 79px, max(calc(46.9577px + 8.5446vw), calc(11.8056vw))"

imageSizes('token-name', options?)

Generate from a named token in your fluid.config.js. Keeps image sizes automatically in sync with your layout tokens — change the token, the sizes string updates on next build.

// fluid.config.js
export default {
  width: {
    'navbar-logo-w': [79, 170],
    'hero-image-w':  [320, 900],
  }
}

// Component
import { imageSizes } from 'fluid-px/image'

<Image src={logo}      sizes={imageSizes('navbar-logo-w')} />
<Image src={heroImage} sizes={imageSizes('hero-image-w')}  />

// Per-call config (if configureImage was not called)
import fluidConfig from './fluid.config.js'
<Image src={logo} sizes={imageSizes('navbar-logo-w', { config: fluidConfig })} />

imageSizes({ mobile, desktop }, options?)

Generate from viewport fractions — for images that span a fraction of the viewport.

// Full-width on mobile, half-width on desktop
<Image sizes={imageSizes({ mobile: '100vw', desktop: '50vw' })} />
// → "(max-width: 768px) 100vw, 50vw"

// Custom breakpoint
<Image sizes={imageSizes({ mobile: '100vw', desktop: '33vw' }, { breakpoint: 1024 })} />
// → "(max-width: 1024px) 100vw, 33vw"

Options

All forms accept an options object:

| Option | Type | Description | |--------|------|-------------| | minScreen | number | Override min screen for this call | | maxScreen | number | Override max screen for this call | | config | FluidConfig | Pass config inline (token form only) | | breakpoint | number | Viewport fraction switch point (fraction form only, default 768) |


Config-file workflow (optional)

The config-file workflow lets you define all fluid values in one place as named tokens, then use them as Tailwind utility classes throughout the codebase.

Instead of writing fluid(24, 56) in every component, you define heading once and use text-heading everywhere.

1. Create fluid.config.js

export default {
  screens: { min: 375, max: 1440 },
  output: {
    css:    './src/styles/fluid.css',
    tokens: './src/utils/fluid.tokens.js',
  },
  units: {
    fontSize: 'rem',  // optional — output rem instead of px for this category
  },
  fontSize: {
    heading: [24, 56],
    body:    [14, 16],
    // per-token screen override:
    caption: { min: 10, max: 13, minScreen: 320, maxScreen: 768 },
  },
  spacing: {
    'page-px': [16, 80],
    sm:        [8,  16],
  },
  borderRadius: {
    card: [8, 20],
  },
  height: {
    navbar: [60, 100],
  },
  // size generates .fluid-size-* CSS classes (square or rectangle)
  size: {
    icon:   [24, 40],              // square — width + height
    avatar: [40, 80, 40, 80],      // rectangle — [minW, maxW, minH, maxH]
  },
}

Supported token categories: fontSize, lineHeight, letterSpacing, spacing, borderRadius, width, height, size

2. Generate

npx fluid-px generate

This writes two files:

  • fluid.css — CSS custom properties on :root using max() — proportional overflow above max screen is baked into each value, no extra media query needed
  • fluid.tokens.js — token map for Tailwind (var(--fluid-...) strings)

3. Import CSS

/* globals.css */
@import './fluid.css';

4. Wire up Tailwind

// tailwind.config.js
import { generateTailwindTokens } from 'fluid-px/tailwind'
import fluidConfig from './fluid.config.js'

const fluid = generateTailwindTokens(fluidConfig)

export default {
  theme: {
    extend: {
      fontSize:     fluid.fontSize,
      spacing:      fluid.spacing,
      borderRadius: fluid.borderRadius,
      height:       fluid.height,
    },
  },
}

5. Use in components

// named tailwind classes — values come from fluid.css via CSS vars
<nav className="h-navbar px-page-px">
  <h1 className="text-heading">My App</h1>
  <p  className="text-body">Subtitle</p>
</nav>

// fluid-size-* utility class
<img className="fluid-size-avatar" />

The math

For fluid(24, 56) with screens 375px → 1440px:

slope       = (56 - 24) / (1440 - 375)  = 0.03005
intercept   = 24 - 0.03005 × 375        = 12.7
slopeVw     = 0.03005 × 100             = 3.005vw

linear:     calc(12.7px + 3.005vw)

  At  375px → 12.7 + 3.005 × 3.75  =  24px  ✓
  At  768px → 12.7 + 3.005 × 7.68  =  35.8px
  At 1440px → 12.7 + 3.005 × 14.4  =  56px  ✓

overflowVw  = 56 / 1440 × 100           = 3.889vw

overflow:   calc(3.889vw)

  At 1440px → 3.889 × 14.4  =  56px    (equal — seamless handoff)
  At 1920px → 3.889 × 19.2  =  74.7px  (keeps growing)
  At 2560px → 3.889 × 25.6  =  99.6px  (keeps growing)

result:     max(calc(12.7px + 3.005vw), calc(3.889vw))

  Below 1440px: linear wins  (linear > proportional in the interpolation range)
  Above 1440px: overflow wins (proportional grows faster beyond max screen)

License

MIT