9th April, 2022

LESS: high resolution fluidity

In the previous blog posts I have explained how I tackle responsiveness and fluidity of the font-size property in less. In those explanations I rely on the default breakpoints provided by Butter Cake which allow the development of responsive interfaces for screens of resolutions of FHD (1920x1080) and below.

While most people would probably be satisfied, I own and work on 3 beautiful Terra LED 2766W PV display monitors, which run at QHD resolution (2560 × 1440). Anybody who owns a screen with this resolution or larger know that way too many websites look ridiculous on these screens. Therefore, I am going to address this issue on my interfaces.

Instead of changing every absolute size to relative, a process that might cause issues and uncaught mistakes, I will just be modifying the behavior of the interface when it is being viewed on screens with resolution higher than FHD. To do so, a new breakpoint will be necessary.

/*
 * Breakpoints to match Butter Cake
 */
@bp-sm: 590px;
@bp-md: 790px;
@bp-lg: 1160px;
@bp-xl: 1260px;
@screen-sm: ~"(min-width: @{bp-sm})";
@screen-md: ~"(min-width: @{bp-md})";
@screen-lg: ~"(min-width: @{bp-lg})";
@screen-xl: ~"(min-width: @{bp-xl})";
/*
 * Breakpoint for high resolution screens
 */
@bp-hr: 2000px;
@screen-hr: ~"(min-width: @{bp-hr})";

Here I show how to apply the new behavior to the .fluid-font mixin explained previously.

/*
 * Mixin for fluid scaling of fonts
 * Updated with fluid scaling above 2000px viewport width
 */
.fluid-font (@min-size, @max-size) {
    @screen-sm-pxless: unit(@bp-sm);
    @screen-xl-pxless: unit(@bp-xl);
    @screen-hr-pxless: unit(@bp-hr);
    @min-size-px: unit(@min-size, px);
    @max-size-px: unit(@max-size, px);
    /* Find ratio between text size and viewport width when viewport is exactly @bp-hr wide */
    @hr-size: (@max-size / (@screen-hr-pxless/100));
    @hr-size-vw: unit(@hr-size, vw);

    font-size: @min-size-px;

    @media @screen-sm {
        font-size: calc(@min-size-px + (((100vw - @bp-sm) / (@screen-xl-pxless - @screen-sm-pxless)) * (@max-size - @min-size)));
    }

    @media @screen-xl {
        font-size: @max-size-px;
    }

    /* Keep the ratio constant when viewport width is above 2000px */
    @media @screen-hr {
        font-size: @hr-size-vw;
    }
}

I can then apply this mixin to my .display-1 class

.display-1 {
    .fluid-font(58, 82);
}

And it will compile to this

.display-1 {
    font-size: 58px;
}

@media (min-width: 590px) {
    .display-1 {
        font-size: calc(58px + (((100vw - 590px) / (1260 - 590)) * (82 - 58)));
    }
}

@media (min-width: 1260px) {
    .display-1 {
        font-size: 82px;
    }
}

@media (min-width: 2000px) {
    .display-1 {
        font-size: 4.1vw;
    }
}

Now all that is left to do is to make containers also become larger to fit the larger text size. In Butter Cake 4.0.2 the .container class becomes 1150px wide at the largest breakpoint 1160px. I am not sure whether this behavior is intended or not: I expected the largest breakpoint used by it would be the 1260px one instead.

.container {
    @media @screen-hr {
        max-width: unit(((unit(@bp-lg)-10)/(unit(@bp-hr)/100)), vw);
    }
}

Alright, this looks complex, though it isn’t. The @bp-lg breakpoint is 10px bigger than the max-width, instead of explicitly defining a new variable for the width of the container, I opted to just subtract 10 from the breakpoint. However, the breakpoint is defined with the unit px, to subtract 10 I first have to remove the unit with the unit() function.

Once I have the width of the container, I need to divide it by the minimum width of the high resolution breakpoint, which again is defined with the unit which as to be stripped first. Once I have the result of the calculation, I add the vw unit to it.