I think it's not possible to achieve it with CSS only, but even with JavaScript it's quite a straightforward solution. Please let me know if I misunderstood something from the requirements.
Solution
I'm resetting the --fluid-size
CSS variable at load
& resize
events by running the resetFluidSize
function (notice this process will hurt the performance as it triggers reflows every time it runs, I'm not doing any optimization here in order to keep it simple).
Then I used the outerWidth
to prevent the zoom level (which affects the innerWidth
) from messing up the proper scale so no matter the page zoom, the computed style will be the desired one.
After doing the math, I update the CSS variable with document.body.style.setProperty
.
Note
In order to see the right values, run the code snippet Full page.
window.addEventListener('load', () => {
resetFluidSize();
window.addEventListener('resize', resetFluidSize);
});
const
a = 14,
b = 22;
function resetFluidSize() {
const
factor = (window.outerWidth - 1280) / 640,
lerp = a + (b - a) * factor,
clamp = Math.max(a, Math.min(b, lerp)),
fluidSize = `${clamp}px`;
document.body.style.setProperty('--fluid-size', fluidSize);
/* Just to update the feedback. */
document.getElementById('fluid-text').setAttribute('currentSize', fluidSize);
}
:root {
--fluid-size: 16px;
}
#fluid-text {
font-size: var(--fluid-size);
}
/* Ignore the style below, its just for the feedback. */
p {
border-right: 1px solid black;
margin: 0;
width: fit-content;
position: relative;
}
p::after {
content: attr(currentSize);
position: absolute;
left: 100%;
}
<body>
<p style="font-size: 14px;" currentSize="14px">
Lorem ipsum
</p>
<p id="fluid-text">
Lorem ipsum
</p>
<p style="font-size: 22px;" currentSize="22px">
Lorem ipsum
</p>
</body>
Edit
If you want to run it locally, you can use this index.html (a GitHub Gist).