What if I told you that you can build a web page without device-based breakpoints?

Julián Ricardo Mahecha D'Maria
UX Collective
Published in
9 min readMay 28, 2020

--

TThe first time I heard those words I thought “That’s crazy! The designs don’t reflect that! How would we match a design that way? How can we achieve pixel-perfect?!”. This was one of the guidelines followed in the latest project I worked on. Now that the project is finished, I can say that the team (designers, devs, and QAs) learned a lot from the experience.

Most of the members of the team were used to working with a predefined grid system where every element has its position and width based on columns. A grid usually has 4 to 12 columns that change depending on breakpoints. These breakpoints are usually designed with 3 or 4 screen sizes in mind (often we build pages thinking in mobile, tablet, desktop, and extra-large desktop sizes).

Computer screen showing a page layout using a grid system
Source: AlleyWatch

Additional information about grid systems can be found in this article about designing with grid systems.

So when we (dev team) learned about the “no device breakpoint” approach we decided to give it a go. Then we proceeded to schedule a meeting with the design team to understand if this could be implemented in our project. At the meeting, we explained that we wouldn’t be using the traditional grid system but a flexible one.

So, what is a flexible grid system?

In short, creating a unique grid per page or group of pages that follows a similar design pattern. Also, the columns can have a variable width depending on the content in them.

Naturally, this was the reaction of our design team.

A person moving his hands away of his forehead, represents an explosion

What at first was a design meant to be pixel perfect on all devices, now needs to be a fully flexible device-agnostic solution. We needed to figure out the right tooling and practices to approach the creation of the page in a way that would meet the design requirements. Here is when fluid layouts come in.

What is a fluid layout? And how can we build it?

Animation showing a page layout using fluid design
Source: UX Alpaca

To create a fluid layout you should specify sizes using CSS relative units, e.g. ‘ems’, ‘rems’, ‘vw’, ‘vh’, percentages, or ‘ch’. Using these units you can size elements on the page based on its width, height, or typography.

We used most of the related units in different parts of the site. For most of the devs, it was the first time we heard and used ch units. As defined on MDN web docs: “The ch unit is relative to the advance measure (width) of the glyph “0” of the element’s font”. Most of the measurements done using ch were done in live sessions between devs and design to define the best estimate that reflects the intent.

Define breakpoints based on content not devices

You may ask: So, your page doesn’t have any breakpoints?

It does, but they are defined per page, section, or component used on the page. Also, they are based on how the content looks best in each scenario. This means we define breakpoints as we develop a new component/page, and we may reuse some breakpoints depending on the case.

Use grid and flex to its full potential

If you are a frontend developer you should be familiar with flexbox and if you follow the latest practices/trends you should be familiar with CSS grid. Have you mastered them?

I have noticed we usually use flex and grid for the same things and following the same patterns. Usually, we use flexbox to center items, to change layouts from rows to columns using breakpoints. And, we use CSS grid to build the page grid system and to position elements in columns to match a design.

So what if we tried to build elements without the classic grid system and minimize the use of breakpoints in components/pages?. The dev team worked with this new mindset tackling problems in different ways as they were used to. We explore different approaches using flexbox and grid in ways we never had before to fulfill fluid design intent.

Some code examples

The following examples are abstractions of the actual code we used on the project. They represent a self-contained idea that can be applied to any project. They don’t represent the final work of the project.

Base page layout

Here is an example of the base layout for some of the pages. In the code, we use a single centered column as the base of the page. Within it, we can place components one below the other.

Flex container

Here we can see an example of a simple component that holds a container with a text on one side and an image on the other. We use the property ‘flex-wrap: wrap;’ to avoid adding a breakpoint to change from column to row design. Also, we are using the `flex` along with ‘min-width’ property on the text and image to do the transition from column to row when the content fits best. For this component, we got inspiration from several articles on the web including but not limited to home using flexbox without media queries and the difference between width and flex-basis.

Grid using auto fit

Here we create a grid that will place elements based on the available space. The grid creates rows as needed given item size and available space, the best part, we don’t use breakpoints!. We have two variations of the grid, in the first one, the items fill all the available space, in the second one they have a max-width defined.

Responsive card

We create several models for cards that can be placed on the grid. Here is an example of a simplified version of them. It is a simple example with an image with variable width and a section with some text. Creating this component we need to have in mind that by itself it may look weird, but it will be placed inside the grid. We have to think that the card width will be constrained by the grid.

Combination of card and grid

Here is the combination of the grid using the card component. You can see that the card flows in the grid available space. The grid can host different card designs and have variations. When creating and integrating cards on the grid you probably need to do a couple of updates to the card of the grid itself to reflect the design as intended.

The magic of clamp

Another interesting technique was pointed out by our technical stakeholder. He showed us how to do fluent layouts even better using the clamp function.

As defined on MDN web docs: “the clamp() function clamps a value between an upper and lower bound. clamp() enables selecting a middle value within a range of values between a defined minimum and maximum. It takes three parameters: a minimum value, a preferred value, and a maximum allowed value.

Why is clamp really cool?

I think the clamp function is really cool because we can transform static properties to be flexible. Mostly we use clamp function on margins, padding, width, and height but it can be used even in the configuration of grid columns.

Let’s check some code:

margin-right: clamp(0.25rem, 1vw, 1rem);

This code can be interpreted as: the margin-right will have a minimum value of 0.25rem and a maximum of 1rem. The middle value is a little tricky to understand. It is defined as the “preferred value” which may not mean much. We considered that value as some sort of “speed”. So, is how fast the margin will change from 0.25rem to 1rem.

To select that middle value we use viewport width units in most of the cases. Then we check in the browser the transition of the margin-right value. It was a trial and error process but it worked.

So, what can I do with the clamp function?

We use the clamp function when we want to have one value for small screens and a different one for large screens. Imagine you want a margin between two elements to be 1rem on small screens and 3rem for large screens, that’s when the clamp function comes in. Below there are some cool examples of the clamp function magic.

Fluid typography

Here is an example of how to build fluid typography using the clamp function. This particular example uses material design font sizes as a reference for the maximum value. The minimum value is an opinionated value selected by me for testing. And the middle value was selected with a trial and error process in the browser.

In a real project, we can do several improvements to the example above. For instance, add some sort of math to have a more constant pace for font scaling. Also, we can create a mixin to handle all that logic.

Grid using clamp for column width

Here is a cool/crazy idea that ends up working. Can we use the clamp function in the definition of a grid and it’s gap? Yes, we can! But why you may ask.

In this particular case, we want to have the column to flow from a minimum value to 1fr. That can be achieved easily just using a min-max function. So let’s imagine using a min-max function the change from row to column happens at 900px. But, we want that change to happen around 600 or 700 pixels.

How can we achieve this without a breakpoint? So here comes the crazy idea, what if we use the clamp to define the minimum value on the min-max function?. It will work as needed because we can define min and max values for the clamp function as well, and define how fast it will change between those two. It took some trial and error to get the values right but it worked.

What is the downside?

Sadly not all are good news. The clamp function is a new feature on CSS which means it is not fully supported on all browsers. You can verify its current support on Can I use or MDN web docs.

At the time we started the project around January 2020, the clamp function was only supported in Chrome, now by the time I’m writing, April 2020, it is also supported in Firefox, Edge, and Opera. Maybe in the future, it will be available in Safari.

So before using clamp on your projects, make sure you check its support and make sure you, your team, and client are okay with the browser that supports it. You can consider clamp function as a part of the progressive enhancement process of web pages. This means we offer a baseline experience for users, in this case, Safari users base and an enhanced experience to users on browsers that support clamp.

It’s possible to build a good looking website without device-based breakpoints. As a developer, the challenge to avoid using a predefined breakpoint value has made me and the team think in different and more creative ways of using flexbox and CSS grid. Thinking about how the content will look better and defining different breakpoints is not an easy task but the result was awesome.

As a team, design, devs, and QA learn a lot about fluid design and understand that we can create great websites that aren’t pixel perfect.

I think the clamp function is awesome and if we use it having in mind the progressive enhancement pattern we could improve the experience for our users. Looking forward to being able to use it across browsers freely.

If you like this article you may be interesting in reading:

Resources

--

--