Scale Typography from Screen Width. With Easing Functions

by Hugo Vale Pereira

HTML

<!--
From: [https://9to5.hfbk.hamburg/] (7 fev 2024)
-->
<div class="blue"></div>
<div class="red"></div>

<h1 id="t1">Title</h1>
<h1 id="t2">Title</h1>

CSS

.blue {
  width: 200px;
  background: blue;
}
.red {
  width: 400px;
  background: red;
}

div {
  height: 10px;
}

/* 1. Register a property so atan2 works correctly */
@property --100vw {
  syntax: "<length>";
  initial-value: 0px;
  inherits: true;
}

:root {
  --100vw: 100vw;
  --vw-unitless: tan(atan2(var(--100vw), 1px)); /* This gets a unitless value */

  --sm-w: 200;
  --bg-w: 400;
  --min-f: 16;
  --max-f: 64;

  /* Normalize progress to 0-1 */
  --progress: calc((var(--vw-unitless) - var(--sm-w)) / (var(--bg-w) - var(--sm-w)));

  --eased: calc((1 - cos(var(--progress) * 180deg)) / 2);
}


/* ------------------------------------ With Animation approach --- */
/* 4. Define font range */
@keyframes fluid-font {
  0%   { font-size: 16px; }
  100% { font-size: 64px; }
}

#t1 {
  animation-name: fluid-font;
  animation-duration: 1s;
  animation-timing-function: ease-in-out; /* ← your easing here */
  animation-fill-mode: both;
  animation-play-state: paused;
  animation-delay: calc(var(--progress) * -1s);

}

/* ------------------------------------ With Cosine math function approach --- */
/* 
  This approach would need a media query as well or a function that always have a positive or negative slope. Sin and Cos alternates
 */
#t2 {
  /* Apply cosine easing to progress */
  
  font-size: clamp(
    calc(var(--min-f) * 1px),
    calc((var(--min-f) + (var(--max-f) - var(--min-f)) * var(--eased)) * 1px),
    calc(var(--max-f) * 1px)
  );
}

JavaScript

let h = document.querySelectorAll('h1');
h.forEach((h1) => {
  let size = h1.style.fontSize;
  h1.textContent = 'Title ' + window.getComputedStyle(h1).fontSize;

  window.addEventListener('resize', () => {
    h1.textContent = 'Title ' + window.getComputedStyle(h1).fontSize;
  });
});