<onWebFocus />

Knowledge is only real when shared.

Responsive Websites without Breakpoints

September 6, 2021

Introducing wasser a plugin to create fully responsive websites without breakpoints.

Usually responsive webdesign is done by defining breakpoints. The more breakpoints are defined the better the website will look on different screens.

A New Way to Responsive

After picking up a CSS formula using calc I've created a plugin called wasser to make it easy to create websites with responsive values that scale linearly so they are different for each viewport.

The idea is to define two values: one for desktop and one for mobile. This is especially helpful if you have a desktop design and a mobile design. The plugin will then linearly interpolate all the values between these two points. For the simple case where you only have a desktop design and want a quick responsive version the mobile value can simply be calculated using a configurable parameter by which to divide it.

The plugin has been around for some time and the formula is well known. However, the approach has failed to gain mainstream adoption until now. Personally, I've used it in a couple of websites and haven't experienced any issues and don't miss writing breakpoints at all. It works on all browsers (Version 2 requires CSS Variables which are supported well now) and doesn't lead to any performance issues. For debugging it can be a bit weird as you get formulas instead of simple values like 10px and the computed values can look like 8.34125666px.

How it works

wasser Illustration

The above illustration shows how the values are calculated. The illustration is using default values which can be configured. At the desktop viewport width of 1500 pixels and above the value will be the input value for the first argument to the wasser() method. If no second argument for the mobile viewport is added it's calculated by dividing the desktop value through the scaling ratio.

import { wasser } from 'wasser'

margin-left: wasser(60)
// =>
margin-left: 60px // 1500px desktop viewport
margin-left: 50px // 910px viewport
margin-left: 40px // 320px mobile viewport

Between the fixed values for mobile and desktop the values are linearly scaled, so that there's a different value for each possible breakpoint.

margin-right: ${wasser(60, 40)};
margin-bottom: ${wasser(60, 60 / 1.5)};

Unless the scaling ratio (1.5 by default) is configured otherwise the above usages with a second argument will lead to the same result as not specifying a second argument.

The following shows what will be the result after the mixin (for the SASS version) is compiled or the method (for the CSS-in-JS version) has been called. Additionally, the :root css variables are added once per page.

margin-left: calc((7.5px + 52.5 * var(--factor)) * var(--between) + 7.5px * var(--min) + 60px * var(--max));
// :root values
--factor: (100vw - 320px)/1180;
--max: 0;
--between: 1;
--min: 0;

When debugging the formula itself isn't important and there is no need to understand how exactly it works. The computed tab in the CSS DevTools will reveal the currently displayed value in simple pixels.


It's not necessary and recommended to use the plugin for every pixel value in CSS. It's best suited for spaces, fonts and sizes. What it cannot do is create dynamic grids and wholly different layouts for different viewports. Because the mobile viewport is usually in portrait while desktops more often have a landscape size the information on a page will have to be layed out differently anyways. For this breakpoints are still the way to go.

Also, the plugin isn't built to handle more than two specific breakpoints. The values in between will always be calculated linearly. It can only be used if the design to be implemented either only has a desktop design or a desktop and mobile design. If that's the case the plugin can make the development of pixel perfect designs very easy with the additional benefit that breakpoints in between will also look good.