Развлечения с line-height!

Перевод статьи Fun with line-height! с сайта css-tricks.com, c разрешения автора — Криса Койера.

Свойство line-height в CSS управляет расстоянием между строками текста. Его часто устанавливают в безразмерное значение (напр. line-height: 1.4;), чтобы оно было пропорционально размеру шрифта. Это свойство крайне необходимо для управления типоргафикой. Если расстояние между строк слишком маленькое, то строки неуклюже придавлены друг к другу; а если слишком большое, то строки выглядят неуклюже растопыренными. Оба случая тормозят чтение текста. Но, вероятно, вы уже сами это знаете.

В этой статье мы сосредоточимся на некоторых хитростях. Если вы знаете (или можете выяснить) точное значение line-height, то у вас есть возможность делать интересные вещи.

Оформление каждой строки текста своим цветом

К сожалению, не существует ::nth-line(). Мы даже не можем надёжно полагаться на <span>-ы, т.к. есть куча всевозможных вещей, из-за которых текст может переноситься на новую строку в разных местах.

Есть способ, хотя и нестандартный, использовать фон элемента в качестве фона для текста.

.text {
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

Есть ещё один трюк, когда можно использовать linear-gradient() с резкими переходами между цветами. Допустим нам известно, что line-height равен 22px, тогда мы мы можем сделать градиент, у которого цвета меняются точно с таким шагом.

.text {
  background-image: linear-gradient(
    to bottom,
    #9588DD,
    #9588DD 22px,
    #DD88C8 22px,
    #DD88C8 44px,
    #D3DD88 44px,
    #D3DD88 66px,
    #88B0DD 66px,
    #88B0DD);
}

gradient-stops

А теперь объединим оба трюка:

funsville

В браузере, который не поддерживает обрезку фона по тексту (напр. Firefox), вы получите сплошные полоски цвета под текстом. Возможно, это круто и вам понравится. Возможно, вы бы скорее предпочли оставить сплошной цвет текста. В этом случае можно использовать @supports и применять его везде, где он поддерживается.

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

$lh: 1.4em;

body {
  font-size: 1em;
  line-height: $lh;
}

@supports (-webkit-background-clip: text) {
  p {
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-image: linear-gradient(
      to bottom,
      #9588DD,
      #9588DD $lh,
      #DD88C8 $lh,
      #DD88C8 $lh*2,
      #D3DD88 $lh*2,
      #D3DD88 $lh*3,
      #88B0DD $lh*3,
      #88B0DD);
  }
}

Использовать этот трюк для вверхней части элемента проще простого. Вот пример, в котором первые несколько строк выделены для выразительности.

.text {
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(
    to bottom,
    rgba(white, 0.8),
    rgba(white, 0.8) $lh,
    rgba(white, 0.6) $lh,
    rgba(white, 0.6) $lh*2,
    rgba(white, 0.4) $lh*2,
    rgba(white, 0.4) $lh*3,
    rgba(white, 0.2) $lh*3,
    rgba(white, 0.2));
}

start

Но это становится труднее, если вы пытаетесь обратиться к последним нескольким строкам из произвольного количества текста. В этом случае, нам необходимо, чтобы верхняя цветная полоса шла от верха до низа текста за вычетом нескольких строк. К счастью можно сделать это при помощи calc()! (В комментариях к оригиналу статьи Лиа Веру предложила более простое решение: просто изменить направление градиента на "to top" — прим. перев.)

.text {
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(
    to bottom,
    rgba(white, 0.8),
    rgba(white, 0.8) calc(100% - 66px),
    rgba(white, 0.6) calc(100% - 66px),
    rgba(white, 0.6) calc(100% - 44px),
    rgba(white, 0.4) calc(100% - 44px),
    rgba(white, 0.4) calc(100% - 22px),
    rgba(white, 0.2) calc(100% - 22px),
    rgba(white, 0.2));
  background-position: bottom center;
}

fade

Есть также и другие способы сделать это, например, наложение поверх текста псевдоэлемента с градиентом (с указанием pointer-events: none;, так чтобы он не мешал вам)

Линии между строками текста

С помощью приема, похожего на прием с резким переходом между цветами, использованный выше, можно создать линию градиента в 1px, которая повторяется с шагом, в точности равным известному line-height. Самый простой способ сделать это – использовать repeating-linear-gradient(), а также убедиться, что все другие параметры не создают помех (например, отступы, которые также основаны на line-height).

.parent {
  padding: $lh*2;
  background: #082838;
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(white, 0)   0,
    rgba(white, 0)   $lh/1em*16px-1,
    rgba(white, 0.1) $lh/1em*16px-1,
    rgba(white, 0.1) $lh/1em*16px
  );
}

Чтобы получить строку в 1px, необходимо знать значение line-height, а затем вычесть один. Цель состоит в том, что градиент повторяется с шагом, точно равным известному line-height, так что последним пикселем в этом отрезке может быть линия. Поскольку мы оставили font-size для body равным 1em, он у нас будет 16px. И поскольку line-height задан в em-ах, мы можем разделить на 1em, избавившись от единицы измерения, а затем помножить результат на 16px и вычесть один где нужно.

lines

Размещение изображений на каждой строке

Ещё одна вещь, которую можно сделать, зная точный line-height, это заставить background-size ему соответствовать, по крайней мере по вертикальной оси. Тогда можно заставить его повторяться по вертикали, и фоновое изображение будет размещаться построчно.

.text
  background-image: url(image.svg);
  background-size: $lh $lh;
  background-repeat: repeat-y;
  padding-left: $lh*2;
}

ticks

Демо

P.S. Это тоже может быть интересно:

9 Комментарии

  1. Dartess

    Читал через телефон (хром). Финальное демо жесть кривое =)

    1. SelenIT

      А можно скриншот жесть кривизны? Может, вместе придумаем, как пофиксить)

        1. SelenIT

          Действительно занятно, судя по всему, шрифт и градиенты по-разному отмасштабировались. Похоже, это лечится заданием -webkit-text-size-adjust: none.

          Приношу извинения за спам-фильтр — он здесь немножко параноик и настораживается, видя много ссылок в комментах)

          1. Dartess

            Да, так — отлично, спасибо)

      1. Dartess

        Запостил ссылки на скриншоты. То ли удалились сами, то ли их выпилили.

      2. Dartess

        Ан нет, извиняюсь. Ваш комментарий ожидает проверки. 

  2. cow

    "Так что же это за позорные фичи?

    -webkit-background-clip: text;
    -webkit-text-fill-color                "    Отзовите статьи, лекции, примеры и т.п., пропагандирующие эти фичи без каких-либо предупреждений !!! " 

    Котят не жалко?   

    1. SelenIT

      Жалко… Предупреждение, что способ нестандартный, в статье есть (прямо перед примером кода). Понятно, что оно мало кого остановит…

      Но, к сожалению, близкое к монопольному положение Вебкита/Блинка продолжает делать свое черное дело, и за два года после той статьи Лии Веру эти свойства успели войти в обиход. Так что вполне может быть, что их всё-таки продавят в стандарт, как получилось со многими IEшными «нововведениями» 90-х (overflow-x/y, text-align-last и т.п.). Посмотрим.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.