Три способа, как обрезать текст в CSS: с многоточием и без него

В этой статье мы разберем три способа, как обрезать текст в CSS. Вы узнаете, как добавить многоточие к однострочному тексту, а также как реализовать обрезку многострочного текста — как с многоточием, так и с оригинальным дизайнерским эффектом.

Для чего нужна обрезка текста в CSS

Довольно типичной ситуацией на веб-странице является расположение определенного текста слишком большой длины в контейнере с ограниченным размером. В таких случаях текст необходимо обрезать так, чтобы пользователь понимал, что перед ним лишь часть содержания, и мог предпринять действия для его полного просмотра: прокрутить, раскрыть текст либо перейти на другую страницу. При этом обрезка должна не только решать функциональную задачу, но и гармонично вписываться в общий дизайн страницы.

Примеры реализации обрезания текста можно встретить на множестве сайтов разных типов:

  • Превью статей или постов в блогах, где отображается только часть текста, чтобы привлечь внимание пользователя.
  • Заголовки и элементы меню, которые должны вписываться в дизайн без переполнения.
  • Карточки товаров в интернет-магазинах, где длинные названия продуктов обрезаются до одной строки с добавлением многоточия.

Как создавать такие элементы с помощью CSS, мы подробно рассмотрим далее в статье.

Обрезка текста с добавлением многоточия

Чтобы появление многоточия стало возможным, элементу, содержащему текст, необходимо задать ряд CSS-свойств, которые не позволят всему тексту вместиться в этот блок.

Однако сперва стоит отметить, что тип отображения элемента должен быть блочным (block) или строчно-блочным (inline-block), так как строчным элементам (inline) нельзя задать размеры (свойства width, height, max-width, max-height). Это ограничение не позволяет использовать свойства для обрезки текста на строчных элементах. Если элемент не соответствует этим условиям, следует изменить его тип отображения на block, inline-block или flex в зависимости от требований контекста разработки.

В качестве примера возьмем текст в строчном элементе span:

<span class="some-text">
    Это строчный элемент, содержащий длинный текст. Для создания многоточия, этому элементу нужно задать блочный тип отображения и дополнительные стили.
</span>

Чтобы иметь возможность обрезать текст с CSS в этом элементе, сделаем его блочным:

.some-text {
    display: block;
}

Таким образом, имея в распоряжении элемент блочного отображения с текстом, мы можем работать с обрезкой. Сперва зададим строгое ограничение по ширине, чтобы элемент не занимал больше положенного пространства:

.some-text {
    display: block;
    width: 200px;
}

Добавим некоторые стили для лучшего визуального восприятия:

.some-text {
    display: block;
    width: 200px;
    font-size: 16px;
    padding: 8px 12px;
    background: #fff;
    color: #333;
}

При ограничении ширины элемента с классом .some-text текст не выйдет за его пределы по горизонтали. Однако текст будет искать свободное пространство снизу и переходить на новые строки, так как это поведение по умолчанию:

При таком поведении обрезка текста не будет возможной. Поэтому запретим этот перенос, добавив свойство white-space: nowrap;:

.some-text {
    display: block;
    width: 200px;
    font-size: 16px;
    padding: 8px 12px;
    background: #fff;
    color: #333;
    white-space: nowrap;
}

Теперь наш текст всегда будет в одну строку:

Так как тексту запрещено переходить на новую строку и ему не хватает места, он выходит за пределы элемента. Нам необходимо, чтобы часть текста за пределами скрывалась. Сделаем это возможным с помощью свойства overflow: hidden;:

.some-text {
    display: block;
    width: 200px;
    font-size: 16px;
    padding: 8px 12px;
    background: #fff;
    color: #333;
    white-space: nowrap;
    overflow: hidden;
}

После этого мы будем видеть только часть текста в одной строке в пределах ширины элемента:

Последним шагом остается добавить многоточие. Это делается очень просто, благодаря свойству text-overflow: ellipsis;:

.some-text {
    display: block;
    width: 200px;
    font-size: 16px;
    padding: 8px 12px;
    background: #fff;
    color: #333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

Таким образом, мы получаем текст с многоточием:

Обрезать однострочный текст с многоточием

Далее рассмотрим более сложные варианты — обрезка текста с несколькими строками.

Обрезка текста с несколькими строками без многоточия

На момент написания статьи не существует кросс-браузерных CSS-свойств для создания эффекта обрезки многострочного текста с многоточием в конце. Но добиться красивого эффекта обрезки такого текста можно с помощью определенных дизайнерских подходов.

Приведем пример одного из таких подходов. Первым делом, создадим блок с текстом:

<div class="demo-card">
    Это блок с ограниченной шириной и высотой, в котором находится текст, выходящий за пределы блока. При наведении курсора текст раскрывается.
</div>

Теперь добавим CSS-стили. Предположим, этот блок будет представлять собой какую-то карточку с ограниченными размерами. Поэтому зададим ему строгую ширину и высоту (width, height). Чтобы не вмещающийся в пределах блока текст не выходил за границы блока, спрячем эту часть текста с помощью свойства overflow: hidden;. Также зададим относительное позиционирование элементу (position: relative;), чтобы в него можно было поместить элемент с абсолютным позиционированием (об этом чуть позже). Добавим немного декоративных стилей, чтобы наш блок выглядел презентабельно. Таким образом, стили сейчас будут такими:

.demo-card {
    position: relative;
    width: 260px;
    height: 100px;
    overflow: hidden;
    font-size: 16px;
    background-color: #fff;
    color: #333;
    border: 1px solid #ddd;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
    padding: 8px 12px;
}

Блок будет выглядеть следующим образом:

Так как мы не можем добавить многоточие исключительно с помощью CSS, создадим эффект затухания текста внизу блока. Для этого элементу добавим градиент с фиксированной высотой на псевдоэлементе :after. Создадим этому псевдоэлементу абсолютное позиционирование, закрепив его у нижнего края блока:

.demo-card:after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 30px;
    background: linear-gradient(to bottom, transparent, lightskyblue 70%);
}

Теперь нижняя часть текста как бы плавно исчезает:

Чтобы прочитать весь текст, можно создать эффект разворачивания блока при наведении на него курсора. Для полного раскрытия текста заменим фиксированную высоту блока на автоматическую (height: auto;). Когда текст будет полностью виден, затухание градиента можно убрать, визуально скрыв псевдоэлемент :after (opacity: 0;):

.demo-card:hover {
    height: auto;
}

.demo-card:hover:after {
    opacity: 0;
}

Итоговый CSS-код:

.demo-card {
    position: relative;
    width: 260px;
    height: 100px;
    overflow: hidden;
    font-size: 16px;
    background-color: #fff;
    border: 1px solid #ddd;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
    padding: 8px 12px;
}

.demo-card:after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 30px;
    background: linear-gradient(to bottom, transparent, lightskyblue 70%);
}

.demo-card:hover {
    height: auto;
}

.demo-card:hover:after {
    opacity: 0;
}

Живая демонстрация результата (наведите курсор):

Это блок с ограниченной шириной и высотой, в котором находится текст, выходящий за пределы блока. При наведении курсора текст раскрывается.

Мы реализовали один из вариантов блока с обрезанием многострочного текста без многоточия. Но что делать, если многоточие все-таки необходимо в конце последней строки? В этом случае без JavaScript не обойтись. Давайте рассмотрим, как это можно реализовать.

Обрезка текста с несколькими строками с многоточием

Не имея возможности добавить многоточие к многострочному тексту, используя лишь CSS, обработаем наш блок с помощью JavaScript. Как и в прошлом разделе, работать будем с обычным блоком, содержащим длинный текст:

<div class="multiline-ellipsis">
    Это блок с ограниченной шириной и высотой, в котором находится текст, выходящий за пределы блока. Если высота текста превышает высоту блока, текст обрезается с добавлением многоточия.
</div>

Добавим стили, установив фиксированные размеры блока:

.multiline-ellipsis {
    width: 300px;
    height: 100px;
    overflow: hidden;
    font-size: 16px;
    line-height: 21px;
    padding: 8px 12px;
    background-color: #fff;
    color: #333;
    border: 1px solid #ddd;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
}

Текст, не входящий в блок, будет скрыт средствами CSS:

Теперь добавим логику на JavaScript. Мы создадим функцию, которая с помощью бинарного поиска определит, сколько текста помещается в видимой области, и добавит многоточие, если текст превышает допустимый размер:

function addEllipsisToFixedHeight(selector) {
  // Находим все элементы по указанному селектору
  const elements = document.querySelectorAll(selector);

  elements.forEach((el) => {
    // Проверяем, есть ли текст внутри элемента
    if (!el.textContent.trim()) return;

    // Получаем высоту блока
    const maxHeight = parseFloat(getComputedStyle(el).height);

    // Проверяем, превышает ли высота содержимого высоту блока
    if (el.scrollHeight > maxHeight) {
      let trimmedText = el.textContent; // Рабочая копия текста для обрезки
      let start = 0;
      let end = trimmedText.length;
      let mid;
      let lastValidText = trimmedText; // Сохраняем последний текст, который помещался

      // Используем бинарный поиск для оптимального обрезания текста
      while (start <= end) {
        mid = Math.floor((start + end) / 2); // Находим середину текущего диапазона
        el.textContent = trimmedText.slice(0, mid).trim() + '...'; // Пробуем обрезать текст до середины

        if (el.scrollHeight > maxHeight) {
          end = mid - 1; // Если текст всё ещё выходит за пределы, сокращаем его
        } else {
          start = mid + 1; // Если текст помещается, пробуем добавить больше символов
          lastValidText = el.textContent; // Сохраняем текущий валидный текст
        }
      }

      // Устанавливаем окончательный текст с многоточием
      el.textContent = lastValidText;
    }
  });
}

// Вызываем функцию для целевого блока
addEllipsisToFixedHeight('.multiline-ellipsis');

В итоге получим такой результат:

Заключение

Таким образом, мы рассмотрели три кросс-браузерных способа, как обрезать текст: с использованием только CSS и с добавлением JavaScript. Отметим, что мы сознательно не включили популярный способ с использованием CSS-свойств -webkit-box-orient и -webkit-line-clamp, так как они поддерживаются только WebKit-браузерами, являются устаревшими и могут быть удалены в будущем.

Существуют также готовые решения, такие как библиотека Clamp.js, но они часто зависят от тех же устаревших CSS-свойств, что может привести к проблемам с кросс-браузерностью. Тем не менее в специфических ситуациях их можно рассмотреть как временное решение.

Оцените статью
DevReflex
Добавить комментарий