Created
April 5, 2022 07:29
-
-
Save souporserious/7d0f834ec293482e86dc84eceb119a55 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Step = number | string | |
/** | |
* Create a fluid type scale that can be interpolated between a minimum and maximum screen width. | |
* | |
* Forked from: https://www.aleksandrhovhannisyan.com/blog/fluid-type-scale-with-css-clamp/ | |
*/ | |
export function createTypeScale<Steps extends ReadonlyArray<Step>>({ | |
baseFontSize, | |
ratio, | |
screen, | |
baseStep, | |
steps, | |
}: { | |
baseFontSize: [minFontSize: number, maxFontSize: number] | |
ratio: [minRatio: number, maxRatio: number] | |
screen: [minWidth: number, maxWidth: number] | |
baseStep: Steps[number] | |
steps: Steps | |
}) { | |
const [minFontSize, maxFontSize] = baseFontSize | |
const [minRatio, maxRatio] = ratio | |
const [minWidth, maxWidth] = screen | |
const round = (value: number) => Number(value.toFixed(4)) | |
const remUnit = (value: number) => `${round(value)}rem` | |
const baseStepIndex = steps.indexOf(baseStep) | |
return steps.map((step, index) => { | |
const minSize = minFontSize * Math.pow(minRatio, index - baseStepIndex) | |
const maxSize = maxFontSize * Math.pow(maxRatio, index - baseStepIndex) | |
const slope = (maxSize - minSize) / (maxWidth - minWidth) | |
const intercept = minSize - slope * minWidth | |
const minUnit = remUnit(minSize) | |
const maxUnit = remUnit(maxSize) | |
const slopeUnit = `${round(slope * 100)}vw` | |
const interceptUnit = remUnit(intercept) | |
const css = `clamp(${minUnit}, calc(${slopeUnit} + ${interceptUnit}), ${maxUnit})` | |
function getFontSizeAtScreenWidth(width: number) { | |
let preferredFontSize = slope * width + intercept | |
preferredFontSize = Math.min(maxSize, preferredFontSize) | |
preferredFontSize = Math.max(minSize, preferredFontSize) | |
return round(preferredFontSize) | |
} | |
return { css, step, getFontSizeAtScreenWidth } | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment