Вопрос или проблема
Показать/скрыть некоторый текст в большом тексте
Я пытаюсь показать/скрыть некоторый текст (выделение) в середине абзаца. Эти критерии являются основными:
- Метод должен быть гибким, чтобы работать как в однострочном, так и в многострочном режиме.
- И я не хочу, чтобы он мешал остальному тексту абзаца
line-height
.
Ниже приведены то, что у меня есть на данный момент, но ни одно из них не совсем правильно. Версия 1 имеет переход, который я предпочитаю, т.е. ширина тега <mark>
сокращается до нуля, и используется overflow: hidden
, чтобы скрыть текст по мере уменьшения его размера. Проблема в том, что это не может быть многострочным. Версия 2 – это компромисс, который уменьшает font-size: 0px;
, но может быть многострочным.
Есть ли решение, чтобы это работало (выглядело как версия 1, но функционировало как версия 2)? Или есть ли другое решение для этого? (Я также пробовал transform: scaleX(0);
, и это не работает).
body
{
font-size: 15px;
line-height: 21px;
font-family: 'Open Sans';
}
.section
{
position: relative;
margin: 0px 0px 50px 0px;
width: 500px;
height: 210px;
background: #eeeeee;
border: 1px solid #666666;
}
.paragraph
{
position: relative;
width: 100%;
height: 100%;
display: inline;
vertical-align: middle;
}
.paragraph1
{
background: #00ffff;
}
.paragraph2
{
background: #00ffff;
}
/* версия 1 */
.mark1
{
position: relative;
top: 2px;
width: 150px;
height: 21px;
transition: all 1.0s;
vertical-align: bottom;
display: inline-block;
overflow: hidden;
white-space: pre;
}
.mark1 span
{
position: relative;
top: -2px;
height: 23px;
display: inline-block;
background: #cccccc;
}
.mark1.hidden
{
width: 0px;
transition: all 1.0s;
}
/* версия 2 */
.mark2
{
position: relative;
transition: all 1.0s;
vertical-align: bottom;
background: #00ff00;
}
.mark2 span
{
position: relative;
padding: 0px 0px 0px 0px;
background: #cccccc;
}
.mark2.hidden
{
font-size: 0px;
transition: all 1.0s;
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>пример</title>
<link href="https://fonts.googleapis.com/css?family=Open Sans" rel="stylesheet">
</head>
<body>
<button onclick="
const collection = document.getElementsByClassName('mark1');
for (let i = 0; i < collection.length; i++) {
collection[i].classList.toggle('hidden');
}
">переключить версию 1</button>
<div class="section">
<div class="paragraph paragraph1">
Lorem Ipsum is<mark class="mark1"> <span>просто тестовый текст</span></mark> в печати и наборе текста. <mark class="mark1"><span>Lorem Ipsum</span> </mark>является стандартным тестовым текстом этой отрасли с 1500-х годов, когда неизвестный печатник взял галерею шрифтов и перемешал их, чтобы сделать образец шрифта. Он выстоял не только пять столетий, но и переход в электронную типографию, оставаясь по сути неизменным. Он стал популярным в 1960-х годах с выпуском таблиц Letraset, содержащих отрывки Lorem Ipsum, а позже с программным обеспечением для настольной публикации, таким как Aldus PageMaker, включая версии Lorem Ipsum.
</div>
</div>
<button onclick="
const collection = document.getElementsByClassName('mark2');
for (let i = 0; i < collection.length; i++) {
collection[i].classList.toggle('hidden');
}
">переключить версию 2</button>
<div class="section">
<div class="paragraph paragraph2">
Lorem Ipsum is просто тестовый текст печати и набором. Lorem Ipsum был<mark class="mark2"> <span>стандартный тестовый текст этой отрасли с 1500-х годов</span></mark>, когда неизвестный печатник взял галерею шрифтов и перемешал их, чтобы сделать образец шрифта. Он выстоял не только пять столетий, но и переход в электронную типографию, оставаясь по сути неизменным. Он стал популярным в 1960-х с выходом листов Letraset, содержащих отрывки Lorem Ipsum, а более поздно с программным обеспечением для настольной публикации, таким как Aldus PageMaker, включая версии Lorem Ipsum.
</div>
</div>
</body>
</html>
</div><div class="s-prose js-post-body" itemprop="text">
Чтобы достичь этого, вам нужно как минимум 2 элемента
<mark class="mark1">
<span class="mark-placeholder">просто тестовый текст</span>
<span class="mark-highlight">просто тестовый текст</span>
</mark>
На этом этапе вы можете анимировать ширину у mark-placeholder и изменять mark-hightlight как угодно, не нарушая макет, так как он абсолютный.
body
{
font-size: 15px;
line-height: 21px;
font-family: 'Open Sans';
}
.section
{
position: relative;
margin: 0px 0px 50px 0px;
width: 500px;
height: 210px;
background: #eeeeee;
border: 1px solid #666666;
}
.paragraph
{
position: relative;
width: 100%;
height: 100%;
display: inline;
vertical-align: middle;
}
.paragraph1
{
background: #00ffff;
}
.paragraph2
{
background: #00ffff;
}
/* версия 1 */
.mark1
{
position: relative;
width: 150px;
height: 21px;
transition: all 1.0s;
vertical-align: bottom;
display: inline-block;
overflow: hidden;
white-space: pre;
}
.mark1.hidden
{
width: 0px;
transition: all 1.0s;
}
.mark-placeholder
{
position: relative;
opacity: 0;
display: inline-block;
}
.mark-hightlight
{
box-sizing: border-box;
display: block;
color: red;
background-color: #cccccc;
z-index: 1;
position: absolute;
bottom: 0%;
top: -0;
left: 0%;
right: 0%;
transform: translateY(-10%);
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>пример</title>
<link href="https://fonts.googleapis.com/css?family=Open Sans" rel="stylesheet">
</head>
<body>
<button onclick="
const collection = document.getElementsByClassName('mark1');
for (let i = 0; i < collection.length; i++) {
collection[i].classList.toggle('hidden');
}
">переключить версию 1</button>
<div class="section">
<div class="paragraph paragraph1">
Lorem Ipsum is<mark class="mark1"> <span class="mark-placeholder">просто тестовый текст</span><span class="mark-hightlight">просто тестовый текст</span></mark> в печати и наборе текста. был стандартным тестовым текстом этой отрасли с 1500-х годов, когда неизвестный печатник взял галерею шрифтов и перемешал их, чтобы сделать образец шрифта. Он выстоял не только пять столетий, но и переход в электронную типографию, оставаясь по сути неизменным. Он стал популярным в 1960-х годах с выпуском листов Letraset, содержащих отрывки Lorem Ipsum, а более поздно с программным обеспечением для настольной публикации, таким как Aldus PageMaker, включая версии Lorem Ipsum.
</div>
</div>
<button onclick="
const collection = document.getElementsByClassName('mark2');
for (let i = 0; i < collection.length; i++) {
collection[i].classList.toggle('hidden');
}
">переключить версию 2</button>
<div class="section">
<div class="paragraph paragraph2">
Lorem Ipsum is просто тестовый текст печати и набором. Lorem Ipsum был<mark class="mark2"> <span>стандартный тестовый текст этой отрасли с 1500-х годов</span></mark>, когда неизвестный печатник взял галерею шрифтов и перемешал их, чтобы сделать образец шрифта. Он выстоял не только пять столетий, но и переход в электронную типографию, оставаясь по сути неизменным. Он стал популярным в 1960-х с выходом листов Letraset, содержащих отрывки Lorem Ipsum, а более поздно с программным обеспечением для настольной публикации, таким как Aldus PageMaker, включая версии Lorem Ipsum.
</div>
</div>
</body>
</html>
Ответ или решение
Для решения задачи отображения и скрытия текста в середине абзаца с учетом заданных условий (гибкость для однострочных и многострочных текстов, а также без изменения высоты строк в остальной части абзаца) можно использовать комбинацию CSS и JavaScript с двумя элементами внутри одного тега <mark>
.
Решение
HTML-код:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример отображения/скрытия текста</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
</head>
<body>
<button onclick="
const collection = document.getElementsByClassName('mark1');
for (let i = 0; i < collection.length; i++) {
collection[i].classList.toggle('hidden');
}
">Переключить выделение</button>
<div class="section">
<div class="paragraph">
Lorem Ipsum это<mark class="mark1">
<span class="mark-placeholder">стандартный текст</span>
<span class="mark-highlight">стандартный текст</span>
</mark> печатной и наборной промышленности.
</div>
</div>
</body>
</html>
CSS-код:
body {
font-size: 15px;
line-height: 21px;
font-family: 'Open Sans', sans-serif;
}
.section {
position: relative;
margin: 0 0 50px;
width: 500px;
background: #eeeeee;
border: 1px solid #666666;
}
.paragraph {
position: relative;
width: 100%;
}
.mark1 {
position: relative;
display: inline-block;
overflow: hidden;
transition: width 1s;
}
.mark1.hidden {
width: 0;
}
.mark-placeholder {
opacity: 0;
display: inline-block;
}
.mark-highlight {
display: block;
background-color: #cccccc;
position: absolute;
inset: 0; /* Занимает всю площадь контейнера */
color: red; /* Цвет текста выделения */
}
Объяснение работы
-
Структура HTML: Мы используем тег
<mark>
, чтобы обернуть текст, который мы хотим скрывать или отображать. Внутри него находятся два<span>
элемента: один (с классомmark-placeholder
) служит для поддержания необходимости в пространстве, когда выделенный текст скрыт, а другой (с классомmark-highlight
) — это текст, который должен отображаться и скрываться. -
Стили CSS:
.mark1
имеет свойстваoverflow: hidden
иtransition: width 1s
, что позволяет анимировать изменение ширины, когда текст скрывается.- Класс
.hidden
сжимает ширину элемента<mark>
до нуля, эффективно скрывая текст. .mark-placeholder
имеетopacity: 0
, поэтому его фактически не видно, но он занимает пространство в документе, чтобы высота строки остального текста оставалась неизменной..mark-highlight
позиционируется абсолютно, занимая все пространство, что обеспечивает корректное отображение текста выделения.
- JavaScript для переключения: Кнопка вызывает функцию, которая переключает класс
.hidden
у всех элементов с классомmark1
, скрывая или отображая текст при нажатии.
Заключение
С данным подходом вы сможете гибко управлять отображением текста в средине абзаца, сохраняя при этом целостность верстки и высоту строк. Этот метод обеспечивает анимацию и универсальность для однострочных и многострочных текстов.