7th April, 2022

LESS: responsive text mixin

First I declare the breakpoints. Because I rely on Butter Cake, I want the breakpoints in my LESS code to match the breakpoints in the Butter Cake compiled CSS.

The reason I do not edit the source Butter Cake SCSS is for upgradeability: I want to be able to upgrade to newer Butter Cake versions without having to pull upstream changes into my repository and compile the SCSS source with my changes by myself every time.

/*
 * 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})";

Then I prepare the mixin. Every time the mixin is called, I want to pass the size in pixels to it but I do not want to type px 5 times at every declaration, so I add the unit inside the mixin.

/*
 * Mixin for responsive scaling of fonts
 */
.responsive-font(@xs, @sm, @md, @lg, @xl) {

    font-size: ~"@{xs}px";

    @media @screen-sm {
        font-size: ~"@{sm}px";
    }

    @media @screen-md {
        font-size: ~"@{md}px";
    }

    @media @screen-lg {
        font-size: ~"@{lg}px";
    }

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

In this mixin I add the unit by escaping the variable call and appending px. Another way of achieving the same result would be to use the LESS unit() function like this:

/*
 * Mixin for responsive scaling of fonts
 * utilizing unit() to add the px unit to the parameters
 */
.responsive-font(@xs, @sm, @md, @lg, @xl) {

    @xs-px: unit(@xs, px);
    @sm-px: unit(@sm, px);
    @md-px: unit(@md, px);
    @lg-px: unit(@lg, px);
    @xl-px: unit(@xl, px);

    font-size: @xs-px;

    @media @screen-sm {
        font-size: @sm-px;
    }

    @media @screen-md {
        font-size: @md-px;
    }

    @media @screen-lg {
        font-size: @lg-px;
    }

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

And then I use the mixin

/*
 * 58px when min-width < 590px
 * 64px when min-width ≥ 590px
 * 70px when min-width ≥ 790px
 * 76px when min-width ≥ 1160px
 * 82px when min-width ≥ 1260px
 */
.display-1 {
    .responsive-font(58, 64, 70, 76, 82);
}

Which compiles to

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

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

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

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

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