Smooth out layout jumps at breakpoints

What is responsify?

responsify verb to make an HTML element fluidly adapt to changes in viewport size

At my past job at a digital agency I transformed Photoshop, Sketch, and InVision designs into functioning websites. But the designs gave no instructions on how to handle the in-between resolutions. So, to minimize the abrupt layout jumps I employed a technique I call responsify, which uses CSS calc() function to fluidly change width, margin, left, etc. so they match the value at the neighboring breakpoint.

If you're still unclear what exactly it is and how it works, you're not alone. Many told me it didn't click for them until they saw it in action. So, below's a screen recording of an example.

Read on to learn how to use it in your project.

Today I learned that responsify is a rediscovery of CSS locks. Read the comparison between CSS locks and responsify.

Table of contents

  1. Responsify
    1. What is responsify?
    2. Table of contents
    3. How to responsify
      1. Example 1 featuring two media queries
      2. Example 2 featuring max-width media query
      3. Example 3 featuring max-height
      4. Example 4 featuring ch and min()
      5. Example 5 featuring clamp()
    4. Responsify form
    5. Sass @function
    6. Browser support
    7. Comparison with CSS locks
    8. Related resources
  2. Privacy policy
  3. Accessibility statement

How to responsify


Examples assume smallest viewport width of 320px, a tablet breakpoint at 768px, and a desktop breakpoint at 1024px.

Example 1 featuring two media queries


Suppose a <div> needs to be 90% wide below desktop breakpoint and 40% above that. Because you practice mobile-first approach, you start with:

div {
    width: 90%;

and for desktop you add:

@media (min-width: 1024px) {
    div {
        width: 40%;

You want to gradually transition between these two values so you reserve, let's say, the 900px - 1024px range to smooth this out. You add another media query with the magic ๐Ÿช„ calc() value that you generate using the responsify form below and you're done! ๐ŸŽ‰

@media (min-width: 900px) and (max-width: 1023px) {
    div {
        width: calc(3716.129px - 322.903%); /* - parent lower bound: 900px; parent upper bound: 1024px; element lower bound: 90%; element upper bound: 40%; */

Note the comment that accompanies calc() value. Preserving input values makes it easier to maintain the code.

The comment also includes both as a reference for future maintainers and as a unique string you can match against when tracking down responsified values.

Without responsify:

With responsify:

Example 2 featuring max-width media query


You want the <body>'s padding to increase from 10px to 50px, and have it stay at 50px once it hits the desktop breakpoint. For desktop and above you start off with:

body {
    padding: 50px;

and for below desktop you add:

@media (max-width: 1023px) {
    body {
        padding: calc(-8.182px + 5.682vw); /* - viewport lower bound: 320px; viewport upper bound: 1024px; element lower bound: 10px; element upper bound: 50px; */

I'm not a fan of using a max-width media query because it smells of a desktop-first approach ๐Ÿ‘Ž, but I've included it here for completeness' sake.

Example 3 featuring max-height


You want the <header>'s height to increase from 40px to 90px, and have it stay at 90px once it hits the desktop breakpoint.

header {
    height: calc(17.273px + 7.102vw); /* - viewport lower bound: 320px; viewport upper bound: 1024px; element lower bound: 40px; element upper bound: 90px; */
    max-height: 90px;

Without the max-height the <header> would continue to grow in height with increase in viewport width. This approach removes the need for a media query ๐Ÿ‘, but is limited to width and height as no other property has a corresponding max-width and max-height. ๐Ÿ‘Ž

Example 4 featuring ch and min()


You want the <button>'s border-width to increase from 1ch to 2ch, and have it stay at 2ch once it hits the desktop breakpoint. In this example let's say that the average character width is 13.65px.

button {
    border-width: min(calc(0.545ch + 1.939vw), 2ch); /* - viewport lower bound: 320px; viewport upper bound: 1024px; element lower bound: 1ch; element upper bound: 2ch; "ch" width in pixels: 13.65; */

By using min() you can do away with media query and you're not limited to width and height like in Example 3. ๐Ÿ’ฏ

Example 5 featuring clamp()


You want the <footer>'s margin-top to be 20px below tablet breakpoint, 200px above desktop breakpoint, and increase from 2.6vw at tablet breakpoint (0.026 * 768px โ‰… 20px) to 19.5vw at desktop breakpoint (0.195 * 1024px โ‰… 200px).

footer {
    margin-top: clamp(20px, calc(-515.482px + 69.87vw), 200px); /* - viewport lower bound: 768px; viewport upper bound: 1024px; element lower bound: 2.75vw; element upper bound: 19.53vw; */

Responsify + clamp() is a powerful combination ๐Ÿ’ช that also allows you to do away with media queries and also allows you to mix and match units, something you can't do with responsify alone.

Responsify form


Generate responsified calc() value using the form below.

Bookmark the link next to the form heading above for direct access to this form.

  1. px
  2. px
  3. px

Sass @function


You can use responsify as a Sass @function. Download _responsify.scss, unzip it, and import it to your root Sass file. Usage examples are included in the file.

The advantage of using the Sass @function is that you don't need comments documenting input values. ๐Ÿ™Œ

Note that at the moment, Sass @function doesn't support ch and rem units. ๐Ÿ˜ž

Browser support


Browser support is very good. In spite of IE having known issues with calc() I haven't encountered any. Two of the examples use clamp() and min(), which IE doesn't support. As far as "exotic" ๐Ÿ  CSS values go: vw is supported by all browsers and ch is narrower on IE compared to other browsers, so just look out for that.

Comparison with CSS locks


CSS locks originated as Molten leading. In the article that introduced the concept and in almost every example I came across CSS locks are used for controlling line-height and font-size, even though it works with many CSS properties.

CSS locks and responsify are based on fundamentally the same logic/math and as such share many similarities. They both:

  • work with CSS properties that accept a px value,
  • don't work with properties that accept keyword value like visibility,
  • don't work with properties that accept a unitless value like z-index.

There are also a few differences, most notable are listed in the following table.

CSS locks vs responsify
CriterionCSS locksResponsify
SassCSS locks Sass functionResponsify Sass function
Web interfaceNo Yes

Related resources


There's a similar tool that can generate non-linear calc() value.

For more awesomeness, James Gilyead and Trys Mudford created "Utopia" design system where elements scale proportionally and fluidly. It's an unconventional approach that uses a whole lot of calc(), CSS variables, rem and vw relative units, all tied together with what seems to me as undecipherable math. Fascinating stuff. ๐Ÿง