Search code examples
cssfluid-layouttypographyclamp

Calculating css clamp() preferred values for fluid typography with varying :root font sizes


As an example, for the h1 styles:

I have the following varying :root font-sizes:

  • 700px - 1599px, font-size: 15px (1rem = 15px)
  • 1600px - 1920px, font-size: 17px (1rem = 17px)

For the h1, I want the minimum font-size to be 50px, and the maximum font-size to be 280px, and I want these to reach their points at 700px viewport width, and 1920px viewport width respectively, so I believe I know what the minimum and maximum values for the clamp() should be: clamp(3.333rem, *looking for this value*, 16.47rem), 3.333rem from 50px (min font size) / 15px (:root font size at 700px viewport width), and 16.47rem from 280px (max font size) / 17px (:root font size at 1920px viewport width) Wrong. See Edit below.

The problem I am having is that I do not know how to calculate the preferred value in the middle. I know there are calculators for things like this, and I am able to get sort of close, but I am just guessing and checking, and it only accounts for a single :root font-size across the viewport widths.

Is there a way to find a general solution for calculating this preferred value with the varying :root sizes I've described?

EDIT: I have made some progress on the problem and have found the correct values for this example, but I am still not sure how to generate them for other font sizes.

The correct clamp() for achieving what I have described for the above values is clamp(3.241rem, 18.857vw - 5.32rem, 18.15rem);. I arrived here by the following steps:

  1. Calculating a weighted average of the :root font-sizes. The actual :root font size I need to be using is 15.427px (15px covers approx. 73.68% of the viewport range I am trying to map the preferred values over, so I calculated a weighted average based on that). $weighted-average=(0.73688525 * 15)+(0.26311475 * 17)
  2. Calculating the fluid viewport size (18.857) by multiplying the base font size (15.427) by some rem value (arrived at by guess and check), adding the max font size (280), dividing that by the max viewport width, and multiplying by 100 to get it into vw units. 18.857 = (((15.427 * 5.32) + 280) / 1920) * 100
  3. The min and max values are just the min and max font sizes divided by the :root font-size

I still don't understand the significance of the 5.32rem value here though, and I don't know how to generate the correct value for other font sizes with different min and max values so that those map over the same viewport width range.

If it helps, I have found another clamp value that works for max font size 100px and min font size 40px, mapped over the same viewport range: clamp(2.593rem, 4.92vw + 0.36rem, 6.482rem)

I am having trouble seeing the pattern.


Solution

  • I believe I have figured this out for anyone coming in after. I think discrepancies between results here and the guess and check values I posted can be ascribed to rounding. If your $relative-size value is positive, you should subtract it from the $fluid-size in the preferred value in the clamp, if it's negative, add them.

    $fluid-size = (($max-font-size - $min-font-size) / ($max-viewport-width - $min-viewport-width)) * 100;
    $relative-size = ((max-viewport-width * ($fluid-size / 100)) - $max-font-size) / $weighted-base-font-size;
    

    Using an example I know works, $fluid-size I am expecting: ~18.85. $relative-size I am expecting: 5.32:

    $weighted-base-font-size: 15.427;
    $max-viewport-width: 1920;
    $min-viewport-width: 700;
    $max-font-size: 280;
    $min-font-size: 50;
    
    ((280 - 50) / (1920 - 700)) * 100 = 18.85
    ((1920 * (18.85 / 100)) - 280) / 15.427 = 5.31
    

    Plugging these values into this calculator, I receive these results: Min value (50px) ends at 700 px. Max value (280px) starts at 1920 px.

    Another, $fluid-size I am expecting: ~4.92. $relative-size I am expecting: 0.36:

    $weighted-base-font-size: 15.427;
    $max-viewport-width: 1920;
    $min-viewport-width: 700;
    $max-font-size: 100;
    $min-font-size: 40;
    
    ((100 - 40) / (1920 - 700)) * 100 = 4.91
    ((1920 * (4.91 / 100)) - 100) / 15.427 = -0.37;
    

    Plugging these values into the same calculator, I receive these results: Min value (40px) ends at 698 px. Max value (100px) starts at 1920 px.