Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Last active July 18, 2019 03:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomhodgins/ff86575ac86e1d1991e7ee2caa8efec3 to your computer and use it in GitHub Desktop.
Save tomhodgins/ff86575ac86e1d1991e7ee2caa8efec3 to your computer and use it in GitHub Desktop.
<!doctype html>
<h1 style='--clamped-font-size: 30:5:50;'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as colon-separated list: 0:1:2
const [min, mid, max] = gcs
.getPropertyValue('--clamped-font-size-params')
.split(/\s*:\s*/)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: 30, 5, 50;'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as comma-separated list: 0, 1, 2
const [min, mid, max] = gcs
.getPropertyValue('--clamped-font-size-params')
.split(/,\s*/)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: 30 < 5 > 50;'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as clamped number: 0 < 1 > 2
const [min, mid, max] = gcs
.getPropertyValue('--clamped-font-size-params')
.match(/(.+)[<∧](.+)[>∨](.+)/)
.slice(1)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: [30, 5, 50];'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params array as JSON: [0, 1, 2]
const [min, mid, max] = JSON.parse(
gcs.getPropertyValue('--clamped-font-size-params')
)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='
--clamped-font-size: {
"min": 30,
"mid": 5,
"max": 50
};
font-size: var(--clamped-font-size);
'>Clamped Headline</h1>
<script type=module>
function clampedFontSize(event) {
Array.from(
document.querySelectorAll('[style*="--clamped-font-size"]')
).map(tag => {
const gcs = window.getComputedStyle(tag)
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
const {min, mid, max} = JSON.parse(
gcs.getPropertyValue('--clamped-font-size-params')
)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: --breakpoints(30 min 5 mid 50 max);'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as named breakpoints: --breakpoints(0 min 1 mid 2 max)
const {min, mid, max} = parseABreakpointFunction(
gcs.getPropertyValue('--clamped-font-size-params')
)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
/* Named breakpoints are just a handy made-up syntax for describing breakpoints */
/*
<breakpoint-list> := <custom-ident> <breakpoint-func> [ ',' <custom-ident> <breakpoint-func> ]*
*/
function parseABreakpointList(string) {
return string.split(/,\s+/).reduce(
(acc, part) => {
const [full, condition, breakpoints] = part.trim().match(
/^([a-zA-Z-]+)\s*(--breakpoints\(.*\))$/
)
acc[condition] = parseABreakpointFunction(breakpoints)
return acc
},
{}
)
}
/*
<breakpoint-func> := '--breakpoints(' <breakpoint-string> ')'
*/
function parseABreakpointFunction(string) {
return parseABreakpointString(
/^--breakpoints\(.*\)$/.test(string.trim())
&& string.trim().match(/^--breakpoints\((.*)\)$/)[1] || ''
)
}
/*
<breakpoint-string> := <breakpoint>* <custom-ident> [ <breakpoint> <custom-ident> ]*
*/
function parseABreakpointString(string) {
let list = string.trim().split(/\s+/)
let breakpoints = {}
if (list.length % 2 !== 0) {
list = ['0', ...list]
}
for (let i=0; i < list.length; i = i + 2) {
breakpoints[list[i + 1]] = list[i]
}
return breakpoints
}
</script>
<!doctype html>
<h1 style='
--clamped-font-size:
Never smaller than 30px,
try to be 5% of the element’s own rendered width,
but never go larger than 50px.
;
'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as prose: <number> and <number> and <number>
const [min, mid, max] = gcs
.getPropertyValue('--clamped-font-size-params')
.match(/(\d+\/*\.*\d*)/g)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: ((min 30) (mid 5) (max 50));'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
import symbolix from 'https://unpkg.com/symbolix'
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as symbolic expression: ((min 30) (mid 5) (max 50))
const [[,min], [,mid], [,max]] = symbolix(
gcs.getPropertyValue('--clamped-font-size-params')
)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: 30 5 50;'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as space-separated list: 0 1 2
const [min, mid, max] = gcs
.getPropertyValue('--clamped-font-size-params')
.trim()
.split(/\s+/)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
<!doctype html>
<h1 style='--clamped-font-size: <num min="30" mid="5" max="50" />;'>Clamped Font Size</h1>
<style>
h1 {
font-size: var(--clamped-font-size);
}
</style>
<script type=module>
function clampedFontSize(event) {
[...document.querySelectorAll('[style*="--clamped-font-size"]')].map(tag => {
const gcs = window.getComputedStyle(tag)
// Set original value to *-params as backup
if (!gcs.getPropertyValue('--clamped-font-size-params')) {
tag.style.setProperty(
'--clamped-font-size-params',
gcs.getPropertyValue('--clamped-font-size')
)
}
// Parse params as XML element: <num min="" mid="" max="" />
const {min, mid, max} = Object.fromEntries(
[
...new DOMParser().parseFromString(
gcs.getPropertyValue('--clamped-font-size-params'),
'application/xml'
).documentElement.attributes
].map(({name, value}) => [name, value])
)
tag.style.setProperty(
'--clamped-font-size',
Math.min(
Math.max(
min,
(tag.offsetWidth / 100) * mid
),
max
) + 'px'
)
}).join('')
}
[
'load',
'resize'
].forEach(event => window.addEventListener(event, clampedFontSize))
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment