Не секрет, что MDN выпустили новый дизайн еще в марте. Это великолепно! И в нем есть несколько приятных CSS-жемчужин, на которые интересно смотреть. Одной из таких жемчужин является то, как компоненты карточек обрабатывают усеченный текст.
Довольно круто, да? Я хочу немного разобрать это, но несколько вещей действительно привлекают меня к этому подходу:
- Это пример преднамеренного отключения контента. Мы назвали это как Потеря данных CSS в других местах. И хотя потеря данных, как правило, плохая вещь, мне нравится, как это используется здесь, поскольку выдержки предназначены для тизера для полного контента.
- Это отличается от усечения текста с помощью
text-overflow: ellipsis
, тема, которая возникла относительно недавно, когда Эрик Эггерт общие его опасения по этому поводу. Главный аргумент против — нет возможности восстановить обрезанный при усечении текст — вспомогательные технологии объявят об этом, но у зрячих пользователей нет возможности его восстановить. Подход MDN обеспечивает немного больше контроля в этом отделе, поскольку усечение является просто визуальным.
Итак, как MDN сделал это? Что касается HTML, здесь нет ничего особенного, просто контейнер с абзацем.
<div class="card">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore consectetur temporibus quae aliquam nobis nam accusantium, minima quam iste magnam autem neque laborum nulla esse cupiditate modi impedit sapiente vero?</p>
</div>
Мы можем добавить несколько базовых стилей, чтобы укрепить ситуацию.
Опять же, ничего особенного. Наша цель — обрезать контент, скажем, после третьей строки. Мы можем установить max-height
в абзаце и скройте для этого переполнение:
.card p {
max-height: calc(4rem * var(--base)); /* Set a cut-off point for the content */
overflow: hidden; /* Cut off the content */
}
Воу воу, что с этим calc()
вещи? Обратите внимание, что я установил --base
переменная, которую можно использовать как общий множитель. Я использую его для вычисления font-size
, line-height
, padding
за карту, а теперь max-height
параграфа. Мне легче работать с постоянными значениями, особенно когда размер, который мне нужен, действительно основан на таком масштабе. Я заметил, что MDN использует аналогичный --base-line-height
переменная, вероятно, с той же целью.
Заставить третью строку текста исчезнуть? это классика linear-gradient()
на парграфе :after
псевдоэлемент, закрепленный в правом нижнем углу карточки. Итак, мы можем настроить это:
.card p:after {
content: ""; /* Needed to render the pseudo */
background-image: linear-gradient(to right, transparent, var(--background) 80%);
position: absolute;
inset-inline-end: 0; /* Logical property equivalent to `right: 0` */
}
Заметьте, я звоню --background
переменная, для которой задано то же значение цвета фона, которое используется в .card
сам. Таким образом, кажется, что текст исчезает на фоне. И я обнаружил, что мне нужно настроить вторую цветовую остановку в градиенте, потому что текст не полностью скрыт, когда градиент полностью смешивается до 100%. я нашел 80%
быть сладостью для моих глаз.
И да, :after
нужен height
и width
, height
где это --base
переменные снова вступают в игру, потому что мы хотим, чтобы они масштабировались до размера абзаца. line-height
чтобы покрыть текст высотой :after
.
.card p:after {
/* same as before */
height: calc(1rem * var(--base) + 1px);
width: 100%; /* relative to the .card container */
}
Добавление одного дополнительного пикселя высоты, казалось, помогло, но MDN смог сделать это без него, когда я заглянул в DevTools. Опять же, я не использую top
(или inset-block-start
), чтобы сместить градиент в этом направлении. 🤷♂️
Теперь, когда p:after
абсолютно позиционирован, нам нужно явно объявить относительное позиционирование в абзаце, чтобы сохранить :after
в его течении. В противном случае, :after
будет полностью выдернут из документооборота и окажется за пределами карты. Это становится полным CSS для .card
пункт:
.card p {
max-height: calc(4rem * var(--base)); /* Set a cut-off point for the content */
overflow: hidden; /* Cut off the content */
position: relative; /* needed for :after */
}
Мы закончили, верно? Неа! Чёртов градиент просто кажется не в правильном положении.
Признаюсь, я поразмыслил над этим и запустил DevTools на MDN, чтобы посмотреть, чего, черт возьми, мне не хватает. Ах, да, :after
должен отображаться как элемент блока. Ясно как день, когда добавим к нему красную рамку.🤦♂️
.card p:after {
content: "";
background: linear-gradient(to right, transparent, var(--background) 80%);
display: block;
height: calc(1rem * var(--base) + 1px);
inset-block-end: 0;
position: absolute;
width: 100%;
}
Все вместе сейчас!
И да, внешность похоже, что VoiceOver учитывает полный текст. Однако я не тестировал другие программы для чтения с экрана.
Я также заметил, что реализация MDN удаляет pointer-events
от p:after
. Вероятно, это хорошая защитная тактика для предотвращения странного поведения при выборе текста. Я добавил его, и выбор текста стал немного более плавным, по крайней мере, в Safari, Firefox и Chrome.