Skip to content

Instantly share code, notes, and snippets.

@Niedzwiedzw
Created March 14, 2022 08:39
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 Niedzwiedzw/fccf710476a1b84eae5bef4e5246424d to your computer and use it in GitHub Desktop.
Save Niedzwiedzw/fccf710476a1b84eae5bef4e5246424d to your computer and use it in GitHub Desktop.
detects element's text overflow and fixes it
<script lang="ts">
import { LANGUAGE_CHANGED_EVENT } from '@/user-settings-store';
import { takeWhile, last } from 'lodash-es';
import { onMount } from 'svelte';
export let maxWidthPx = 99999;
export let marginPx = 8;
function textWidth(element: HTMLElement) {
const tag = element.cloneNode(true) as unknown as HTMLElement;
tag.style.position = 'absolute';
tag.style.left = '-99in';
tag.style.whiteSpace = 'nowrap';
document.body.appendChild(tag);
var result = tag.clientWidth;
document.body.removeChild(tag);
return result;
}
let child: HTMLElement | undefined;
let original: string | undefined = undefined;
const lastNumericIdx = (text: string): number =>
last(
takeWhile(
[...text].map((c, i) => [c, i]),
([c, i]: [string, number]) => !isNaN(parseInt(c)) || c === '.'
).map(([child, i]) => (i as number) + 1)
) ?? 99999;
const scaleFontSize = (original: string, scale: number): string => {
const [numeric, unit] = [
original.slice(0, lastNumericIdx(original)),
original.slice(lastNumericIdx(original))
];
console.log({ numeric, unit, original });
return `${parseFloat(numeric) * scale}${unit}`;
};
const validate = async () => {
if (child == null) return;
const parent = child.parentElement;
parent.style.fontSize = original;
const container = parent.parentElement;
const siblings = [...(parent.children as unknown as HTMLElement[])];
const parentWidth = textWidth(parent);
const containerWidth = Math.min(container.clientWidth, maxWidthPx);
if (parentWidth >= containerWidth) {
original = parent.style.fontSize;
parent.style.fontSize = scaleFontSize(
window.getComputedStyle(parent, null).getPropertyValue('font-size'),
(containerWidth - marginPx) / parentWidth
);
}
};
onMount(async () => {
window.addEventListener(LANGUAGE_CHANGED_EVENT, validate);
await validate();
});
</script>
{#if $$slots.default}
<div class="overflow-watcher-marker" bind:this={child} />
<slot />
{/if}
<style lang="scss">
.overflow-watcher-marker {
position: absolute;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment