From: Ardis Lu Date: Wed, 29 Jan 2025 04:19:18 +0000 (-0800) Subject: Replace getLineHeightInPx with pseudo element with 1lh height X-Git-Url: https://git.ardis.lu/?a=commitdiff_plain;h=5cdd5d64e7e5d02425689eee1971fffeeef7a42b;p=css-for-line-clamp-ellipsis Replace getLineHeightInPx with pseudo element with 1lh height --- diff --git a/index.html b/index.html index f7adc0e..c9f11bf 100644 --- a/index.html +++ b/index.html @@ -161,6 +161,10 @@ -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines); overflow: hidden; + + &::after { + height: 1lh; + } } .height-resizable { @@ -234,20 +238,16 @@ -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines); overflow: hidden; + &::after{ + height: 1lh; + } }

And this JavaScript:

-
function getLineHeightInPx(elem) {
-  const temp = document.createElement('div');
-  temp.textContent = '0';
-  elem.insertAdjacentElement('beforeend', temp);
-  const h = temp.scrollHeight;
-  temp.remove();
-  return h;
-}
-
-const elem = document.querySelector('.dynamic-line-clamp');
-new ResizeObserver(_ => {
-  elem.style.setProperty('--lines', Math.floor(elem.clientHeight / getLineHeightInPx(elem)));
+      
const elem = document.querySelector('.dynamic-line-clamp');
+const lh = Number(getComputedStyle(elem, '::after').getPropertyValue('height').slice(0, -2));
+new ResizeObserver(() => {
+  const lines = Math.round(elem.clientHeight / lh);
+  elem.style.setProperty('--lines', lines);
 }).observe(elem);

Try adjusting the height:

@@ -278,11 +278,10 @@ new ResizeObserver(_ => { If your paragraph's height is dynamic, it's useful to add some JavaScript to snap the paragraph's height to a multiple of its line-height whenever the paragraph is resized. To do so, update ResizeObserver:

-
new ResizeObserver(_ => {
-  const lineHeight = getLineHeightInPx(elem);
-  const lines = Math.floor(elem.clientHeight / lineHeight);
+      
new ResizeObserver(() => {
+  const lines = Math.round(elem.clientHeight / lh);
   elem.style.setProperty('--lines', lines);
-  elem.style.setProperty('height', `${lines * lineHeight}px`);
+  elem.style.setProperty('height', `${lines * lh}px`);
 }).observe(elem);

It's also best to debounce the observer for better performance and to prevent the observer from fighting with the user for control over the element's height while the user is resizing it. Using this basic debounce function:

@@ -295,10 +294,9 @@ new ResizeObserver(_ => { }

You can update the observer to cancel if another event is fired within 200 milliseconds:

new ResizeObserver(debounce(() => {
-  const lineHeight = getLineHeightInPx(elem);
-  const lines = Math.floor(elem.clientHeight / lineHeight);
+  const lines = Math.round(elem.clientHeight / lh);
   elem.style.setProperty('--lines', lines);
-  elem.style.setProperty('height', `${lines * lineHeight}px`);
+  elem.style.setProperty('height', `${lines * lh}px`);
 }, 200)).observe(elem);
@@ -310,6 +308,9 @@ new ResizeObserver(_ => { -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines); overflow: hidden; + &::after{ + height: 1lh; + } }

And the final JavaScript:

function debounce(fn, wait) {
@@ -320,21 +321,12 @@ new ResizeObserver(_ => {
   }
 }
 
-function getLineHeightInPx(elem) {
-  const temp = document.createElement('div');
-  temp.textContent = '0';
-  elem.insertAdjacentElement('beforeend', temp);
-  const h = temp.scrollHeight;
-  temp.remove();
-  return h;
-}
-
 const elem = document.querySelector('.dynamic-line-clamp');
+const lh = Number(getComputedStyle(elem, '::after').getPropertyValue('height').slice(0, -2));
 new ResizeObserver(debounce(() => {
-  const lineHeight = getLineHeightInPx(elem);
-  const lines = Math.floor(elem.clientHeight / lineHeight);
+  const lines = Math.round(elem.clientHeight / lh);
   elem.style.setProperty('--lines', lines);
-  elem.style.setProperty('height', `${lines * lineHeight}px`);
+  elem.style.setProperty('height', `${lines * lh}px`);
 }, 200)).observe(elem);

And here it is in action!

@@ -366,26 +358,19 @@ new ResizeObserver(debounce(() => { } } - function getLineHeightInPx(elem) { - const temp = document.createElement('div'); - temp.textContent = '0'; - elem.insertAdjacentElement('beforeend', temp); - const h = temp.scrollHeight; - temp.remove(); - return h; - } - const elem = document.querySelector('#basic-observer'); - new ResizeObserver(_ => { - elem.style.setProperty('--lines', Math.floor(elem.clientHeight / getLineHeightInPx(elem))); + const lh = Number(getComputedStyle(elem, '::after').getPropertyValue('height').slice(0, -2)); + new ResizeObserver(() => { + const lines = Math.round(elem.clientHeight / lh); + elem.style.setProperty('--lines', lines); }).observe(elem); const elem2 = document.querySelector('#full-observer'); + const lh2 = Number(getComputedStyle(elem2, '::after').getPropertyValue('height').slice(0, -2)); new ResizeObserver(debounce(() => { - const lineHeight = getLineHeightInPx(elem2); - const lines = Math.floor(elem2.clientHeight / lineHeight); + const lines = Math.round(elem2.clientHeight / lh2); elem2.style.setProperty('--lines', lines); - elem2.style.setProperty('height', `${lines * lineHeight}px`); + elem2.style.setProperty('height', `${lines * lh2}px`); }, 200)).observe(elem2); // Insert "Copy to clipboard" icon button to all code blocks