From f6fc8c4671f94312127b90ee428078de75d4e8df Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Wed, 12 Apr 2023 21:49:05 -0700 Subject: [PATCH] Add full observer demo --- index.html | 105 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index e9791ea..9682be6 100644 --- a/index.html +++ b/index.html @@ -111,8 +111,17 @@ min-block-size: 417px; } + .both-resizable { + resize: both; + min-block-size: 21px; + max-block-size: 294px; + min-inline-size: 50px; + max-inline-size: min(1080px, 100%); + } + .width-resizable, - .height-resizable { + .height-resizable, + .both-resizable { border: 1px dashed hsl(216deg 50% 75%); border-radius: 4px; } @@ -198,7 +207,7 @@ const elem = document.querySelector('.dynamic-line-clamp'); new ResizeObserver(_ => elem.style.setProperty('--lines', Math.floor(elem.clientHeight / getLineHeightInPx(elem)))).observe(elem);

Try adjusting the height:

-

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin. Suscipit adipiscing bibendum est ultricies integer quis auctor. Odio facilisis mauris sit amet massa vitae tortor condimentum lacinia. Nam @@ -212,14 +221,24 @@ new ResizeObserver(_ => elem.style.setProperty('--lines', Math.floor(elem.client quis varius quam quisque id. Adipiscing tristique risus nec feugiat in fermentum posuere urna nec. Elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus.

-

Note that overflow: hidden will only hide lines that are completely cut off from - the container element. So if you resize the paragraph to cut through the middle of a line, the ellipsis will - appear in the line above it but the cut off line will still be visible. When resizing the element, you'll need to - be careful to only resize it to mulitples of its line-height. This behavior appears to be a hard - limitation of line-clamp. +

Note that overflow: hidden will only hide text that is outside the + container element. So if you resize the paragraph to cut through the middle of a line, the ellipsis will appear in + the line above it but the cut-off text will still be visible.

-

It's helpful to debounce ResizeObserver's event listener for better performance. Using this basic debounce function:

+

+ 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 the event listener like so: +

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

Lastly, it's best to debounce the event listener for better performance and to prevent the event listener from fighting with + the user for control over the element's height while the user is resizing it. Using this basic debounce function:

 function debounce(fn, wait) {
   let timeoutId;
@@ -230,7 +249,63 @@ function debounce(fn, wait) {
 }

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

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

The final combined JavaScript looks like this:

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

Here's the final combined JavaScript with all the bells and whistles:

+
+function debounce(fn, wait) {
+  let timeoutId;
+  return () => {
+    clearTimeout(timeoutId);
+    timeoutId = setTimeout(fn, wait);
+  }
+}
+
+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(debounce(() => {
+  const lineHeight = getLineHeightInPx(elem);
+  const lines = Math.floor(elem.clientHeight / lineHeight);
+  elem.style.setProperty('--lines', lines);
+  elem.style.setProperty('height', `${lines * lineHeight}px`);
+}, 200)).observe(elem);
+

And here it is in action!

+
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin. Suscipit adipiscing bibendum + est ultricies integer quis auctor. Odio facilisis mauris sit amet massa vitae tortor condimentum lacinia. Nam + libero justo laoreet sit amet cursus sit amet. Nisl vel pretium lectus quam id. Proin nibh nisl condimentum id. + Sagittis vitae et leo duis ut diam quam nulla. Sed cras ornare arcu dui vivamus arcu felis. Vulputate ut pharetra + sit amet aliquam id diam. Id neque aliquam vestibulum morbi. Tellus at urna condimentum mattis. Non enim praesent + elementum facilisis leo vel. Turpis massa tincidunt dui ut. Risus quis varius quam quisque id. Amet purus gravida + quis blandit. Felis eget velit aliquet sagittis id consectetur purus ut. Quis commodo odio aenean sed adipiscing. + Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Facilisis leo vel fringilla est ullamcorper + eget nulla. Montes nascetur ridiculus mus mauris. Nunc sed augue lacus viverra vitae congue. Morbi non arcu risus + quis varius quam quisque id. Adipiscing tristique risus nec feugiat in fermentum posuere urna nec. Elit + ullamcorper dignissim cras tincidunt lobortis feugiat vivamus. +

+
-- 2.47.3