Как проверить, включён ли line-clamp?
У меня есть динамический текст в элементе span
. Я хотел бы использовать line-clamp: 2
.
В этом случае текст ограничивается максимум 2 строками, а остальная часть обрезается и заменяется на …
.
Это работает с:
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
Моя проблема заключается в том, что если контент обрезан, нужно отобразить подсказку (tooltip). Как я могу определить, обрезан ли текст?
Высота элемента остается прежней, innerHTML
также остается прежним... У меня больше нет идей...
3 ответ(ов)
Вы можете проверить, превышает ли scrollHeight
элемента его clientHeight
, чтобы определить, происходит ли переполнение по вертикали:
function multiLineOverflows() {
const el = this._element.nativeElement;
return el.scrollHeight > el.clientHeight;
}
Этот код создает функцию multiLineOverflows
, которая возвращает true
, если высота содержимого элемента (включая скрытое содержание) больше высоты видимой области элемента. Это полезно, если вам нужно понять, есть ли дополнительный текст, который не отображается из-за ограничения по высоте.
Вот решение для NextJS, React, TypeScript и Tailwind, которое включает кнопку "Прочитать далее...", которая появляется, когда текст ограничен.
Описание перед кодом:
Это компонент React, который принимает post
в качестве пропса (может быть и что-то другое). Пост содержит контент, который мы должны отобразить, ограничивая его до 4 строк, пока пользователь не нажмет кнопку "Прочитать далее...".
contentRef
(хука useRef
) содержит ссылку на div с контентом, который должен отображаться. Первый хук useState
хранит состояние isClamped
: true
, если контент ограничен, и false
в противном случае. Второй хук useState
хранит состояние isExpanded
: true
, если пользователь нажал на "Прочитать далее...", и false
в противном случае.
Затем, хук useEffect
, который вызывается только при монтировании из-за пустого массива, добавляет обработчик событий для изменения размера окна (это может повлиять на количество строк в контенте). Когда окно изменяет размер, contentRef
(div с контентом) сравнивает scrollHeight
с clientHeight
, как это описано в других ответах выше. Если scrollHeight
больше, isClamped
будет установлен в true
, и false
в противном случае.
Теперь в div, который содержит контент, если isExpanded
равно false
(пользователь не кликнул на "Прочитать далее..."), то className
будет установлен в "line-clamp-4"
(что ограничит контент до 4 строк), в противном случае className
будет установлен в "line-clamp-none"
(без ограничения).
Наконец, div, содержащий "Прочитать далее...", будет показан, если isClamped
равно true
(т.е. текст ограничен).
Код:
import { useState, useRef, useEffect } from 'react';
interface PostItemProps {
post: Post;
}
export default function PostItem({ post }: PostItemProps) {
const contentRef = useRef<HTMLDivElement>(null);
const [isClamped, setClamped] = useState(false);
const [isExpanded, setExpanded] = useState(false);
useEffect(() => {
// Функция, которая будет вызываться при изменении размера окна
function handleResize() {
if (contentRef.current) {
setClamped(
contentRef.current.scrollHeight > contentRef.current.clientHeight
);
}
}
// Добавляем обработчик события на изменение размера окна
window.addEventListener('resize', handleResize);
// Удаляем обработчик события при размонтировании
return () => window.removeEventListener('resize', handleResize);
}, []); // Пустой массив гарантирует, что он будет выполняться только при монтировании
return (
<div>
<div ref={contentRef} className={`${!isExpanded ? 'line-clamp-4' : 'line-clamp-none'}`}>
{post.content}
</div>
{isClamped && (
<div className="flex justify-end">
<button
className="font-bold text-title"
onClick={() => setExpanded(true)}
>
Прочитать далее...
</button>
</div>
)}
</div>
);
}
Это решение должно помочь вам реализовать функциональность ограничения текста с кнопкой "Прочитать далее..." в вашем проекте NextJS с использованием React, TypeScript и Tailwind.
Для решения задачи с ограничением количества отображаемых строк в элементе, можно использовать метод getClientRects().length
. Вот простой пример, который отлично работает для меня:
$('.text-inline').each(function() {
var textLineCount = $(this)[0].getClientRects().length; // Получаем количество видимых строк
var lineClampValue = $(this).parent().css('-webkit-line-clamp'); // Получаем значение '-webkit-line-clamp'
if (textLineCount > lineClampValue) { // Если количество строк превышает лимит
$(this).parent().addClass('cut'); // Добавляем класс 'cut' родительскому элементу
}
});
Стиль для блока текста и кнопки "Показать больше":
.text-block {
overflow: hidden; /* Скрываем переполнение */
display: -webkit-box; /* Используем flexbox для отображения блоков текста */
-webkit-box-orient: vertical; /* Вертикальная ориентация */
-webkit-line-clamp: 2; /* Лимитируем количество строк до 2 */
}
.text-block.expand {
-webkit-line-clamp: initial; /* Убираем лимит при расширении */
}
.show-text {
display: none; /* Скрываем кнопку по умолчанию */
}
.cut + .show-text {
display: initial; /* Показываем кнопку, если текст был обрезан */
}
.expand + .show-text {
display: none; /* Скрываем кнопку, если текст развернут */
}
Пример HTML-кода, в котором используется этот скрипт:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
<div class="text-block">
<span class="text-inline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</span>
</div>
<button class="show-text" onclick="$(this).prev().addClass('expand')">Read more</button>
Эта реализация добавляет класс cut
к родительскому элементу, если количество строк текста превышает заданное значение -webkit-line-clamp
. Кнопка "Read more" становится видимой только в этом случае, что позволяет пользователю развернуть скрытый текст.
Получить координаты (X,Y) HTML-элемента
Проверка наличия класса у элемента в JavaScript
Высота, равная динамической ширине (флюидная верстка на CSS)
Несколько файлов JavaScript/CSS: лучшие практики?
Как получить границы элемента div в jQuery