Walrus
Walrus

Reputation: 20444

Pure CSS Line-Height reduction as Font-Size Increases with example but only works in one direction

I found a dynamic way in pure css to reduce the line-height as the font size increases by using a series of nested clamps.

Essentially we ascertain the font size using the em unit and then add the number of additional pixels we want to add to the line-height until the range is exceeded.

.dynamic-line-height {
  line-height: clamp(
    clamp(
      clamp(
        clamp(
          clamp(
            clamp(
              clamp(25px, 1em + 8px, 28px),
              1em + 7px, 32px
            ),
            1em + 6px, 34px
          ),
          1em + 5px, 40px
        ),
        1em + 4px, 76px
      ),
      1em + 3px, 92px
    ),
    1em + 2px, 9999px
  );
}

You get the idea.

Now while this works with decreasing the line-height as the font-size increases I want to also initially increase the line height before decreasing it like this, however there is a *troublemaker.

The issue is that the largest conceivable <preferred size> is taking precedence over the values that precede it. So in the example below anything with a line-height of less than 25px receives the formula of 1em + 8px instead of that assigned to it.

CSS

p {
  line-height: clamp(
    clamp(
      clamp(
        clamp(
          clamp(
            clamp(
              clamp(
                clamp(
                  clamp(
                    clamp(1px, 1em + 4px, 12px), 
                    1em + 6px, 18px
                  ),
                  1em + 7px, 25px
                ),
                1em + 8px, 28px
              ),
              1em + 7px, 32px
            ),
            1em + 6px, 34px
          ),
          1em + 5px, 40px
        ),
        1em + 4px, 76px
      ),
      1em + 3px, 92px
    ),
    1em + 2px, 9999px
  );
}

HTML

<p style="font-size: 12px;">
  Hello there<br>hello there
</p>

<p style="font-size: 17px;">
  Hello there<br>hello there
</p>

<p style="font-size: 20px;">
  Hello there<br>hello there
</p>

<p style="font-size: 24px;">
  Hello there<br>hello there
</p>


<p style="font-size: 28px;">
  Hello there<br>hello there
</p>


<p style="font-size: 40px;">
  Hello there<br>hello there
</p>


<p style="font-size: 60px;">
  Hello there<br>hello there
</p>

<p style="font-size: 80px;">
  Hello there<br>hello there
</p>

Testing area https://jsfiddle.net/x08cpjug/3/

So looking at the first paragraph with font-size set to 12 px you can see that it is providing a line-height of 1em + 8px (ie. 20px) when it should in fact be using 1em + 4px (ie. 16px).

A very rough graph showing the additional number of px above 1em to be added to line-height (vertical axis) against the font-size (horizontal axis).

Upvotes: -1

Views: 599

Answers (1)

Walrus
Walrus

Reputation: 20444

An answer of sorts.

Clamp cannot overcome the limitation stated in the question but the problem can be reduced. In the question the minimum line-height is 1em + 8px until the line-height reaches 28px, thus a font-size of 12px will provide a line-height of 20px instead of the intended 16px.

While this cannot be completely solved with clamp we can use an em value that is closer to achieving what was desired. Instead of 1em + 8px being the effective minimum preferred size value we can say 1.48em is the minimum preferred size value.

This would make a font-size of 12px have a line-height of 17.76px. Not quite 16px but certainly smaller than 20px.

Therefore using the em value without adding pixels is the closest approximation to achieving the a solution with clamp.

--line-height--dynamic: clamp(
    clamp(
      clamp(
        clamp(
          clamp(
            clamp(
              clamp(
                clamp(
                  clamp(
                    clamp(clamp(1em, 1.48em, 25px), 1.4em, 28px),
                    1.28em,
                    32px
                  ),
                  1.16em,
                  36px
                ),
                1.12em,
                40px
              ),
              1.1em,
              44px
            ),
            1.08em,
            54px
          ),
          1.06em,
          68px
        ),
        1.04em,
        80px
      ),
      1.02em,
      96px
    ),
    1em,
    128px
  );
}

Here it is https://jsfiddle.net/zc608kg5/1/

This question really suffered from an overabundance of support and experimentation. I don't know everyone managed to contain their enthusiasm.

Upvotes: 0

Related Questions