Responsive design is a pillar of the modern web. Websites and apps are expected to adjust to screen sizes effortlessly, without loosing functionality. Practically, this means using breakpoints to target viewport widths, and adjust things once a devices' viewport width is above what was specified as the breakpoint.
This makes a lot of sense for layout shifts, for example when switching a component from a vertically stacked column on a mobile screen to a horizontal row on a desktop screen, or switching to a two-column layout on desktop since more space is available.
However, it makes way less sense for scaling typography, paddings, margins and layout grids. They are often tediously scaled in pixel increments along the same breakpoints as the layout shifts. But they do not need to - they could also scale fluidly from a minimum to a maximum value.
Based on this idea, James Gilyead and Trys Mudford built utopia.fyi, an open source fluid responsive design toolset for web.
After looking into utopia.fyi in detail, we decided that we would try and skip the breakpoint-based approach entirely when building out the role token tier of Mosaik. Typo size, space and layout grid should all scale fluidly and not need to be adjusted manually at breakpoints. The setup of utopia.fyi is surprisingly simple and consists of setting a bunch of numbers as parameters:
From these parameters, all typo sizes, spaces, and grid values are calculated for viewport width using only CSS.
This worked nicely in code, and after experimenting with the parameters we had promising results, but an important question remained: how does a designer work with this, given that everything has a fixed pixel size in Figma? On a small scale, a designer and developer can work together closely without an exact design and still produce a great outcome. And there are even design/dev hybrids who can do both. But neither would work for an organisation as big as ORF with separate design and development teams. Some way to display fluid design in Figma was needed.
We resolved this via the Figma API, pushing the calculated fluid values from code into a variable collection in Figma. Within this collection called “Viewport”, we set up modes with common viewport widths (such as 320, 393, 834, 1280, etc.), and in each of these modes the calculated values at the respective viewports are inserted. Effectively, this approach takes snapshots of the fluid values at common viewport widths that designers are used to, and then stores them in Figma ready for use.
When working in Figma, designers can now chose a role token such as space-lg or step-0, select a screen size from the layout collection via the mode selector, and the values will show at exactly the size they will have when implemented.
This approach has the neat side effect that designs in Figma become maintainable from code. Are the margins too small or the typography should scale differently? Change the fluid parameters in code, push it to Figma, and re-publish the library. Once a design file updates, the changes will apply. Even such things as standard screen sizes can be adjusted this way. Assuming the standard for mobile grows further, simply change 393 to 402 in code, and in Figma all screens designed for 393 can update to 402px in width.
Just because everything could scale fluidly does not mean it should. A label in a button or the button padding scaling fluidly across viewports made no sense for us. Therefore, many atom-level components with small typography, still use fixed pixel values, whereas fluid values are used for organisms and large typography, such as heroes, cards and lanes or grids. To achieve this, some typography role tokens exist both in a fluid and fixed version, and fixed space role tokens are available too.
Utopia.fyi is a web based solution using CSS, which does not work for native iOS or Android. Since we did not want to design our products for two different approaches to responsiveness, we needed a way translate the fluid design approach to iOS and Android. The solution was rather simple: the viewport table generated for Figma, as shown above, contains all fluid values at snapshot viewport widths, so we just used this table in the traditional breakpoint approach. This resulted in iOS and Android being “pseudo-fluid”, meaning in Figma, the designs for App and Web behave exactly the same, with typography, space etc. all scaling identically. However, in their implementations, the web version scales fluidly between values, whereas the apps jump from breakpoint to breakpoint.
While perhaps not elegant, it proved itself to be a practical and efficient solution. Firstly, apps for iOS and Android need to serve a much more narrow viewport range, mostly limited to smartphones and tablets, so a truly fluid implementation is not as relevant as it is for web. Secondly, the breakpoint approach is not inherently bad, it is just cumbersome having to manually maintain typography, paddings, etc. across viewports – but since our values are automatically generated, this effort is not needed. Lastly, using this approach leaves the door open to easily implement the calculation from utopia.fyi on iOS and Android to make them truly fluid. This is because it would just mean switching the token values from fixed to fluid instead of having to switch from a manually built responsive system with its own tokens, meaning no designs or code would need to be changed.