“Dot Leaders” или “Точки между словами” на CSS

Inomdzhon Mirdzhamolov
5 min readOct 23, 2016

--

Недавно столкнулся с задачей сверстать список свойств, где свойство и его значение разделено точками. Чтобы сразу было понятно о чем идет речь, приведу пример как это выглядит:

Яйцо…….………………….2 шт.

Спагетти…………………300 гр.

Как выяснилось, в типографике такую запись называют “Dot leaders”. Я так и не смог нормально локализовать этот термин (см. UPD 1).

С разметкой все сразу было ясно:

<div class="param">
<span class="param__prop">Яйцо</span>
<span class="param__value">2 шт.</span>
</div>
<div class="param">
<span class="param__prop">Спагетти</span>
<span class="param__value">300 гр.</span>
</div>

И на счет позиционирования (Рис. 1):

.param {
margin-bottom: 10px;
}
.param:after {
content: '';
display: table;
clear: both;
}
.param__prop {
float: left;
}
.param__value {
float: right;
}
Рис. 1

А вот на счет реализации самих точек было две идеи.

  1. Использовать у родителя свойство:
border-bottom: 1px dotted;

2. Использовать у родителя псевдоэлемент:

content: '......................................................';

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

Cвойство border-bottom у родителя

.param {
border-bottom: 1px dotted;
}
Рис. 2

Далее предлагается сдвинуть обе “ячейки” вниз с помощью postition: relative, либо margin-bottom (Рис. 3):

.param__prop,
.param__value {
margin-bottom: -.31em;
}
Рис. 3 Пока линия западет пот ячейки

И использовать background, чтобы обрезать лишнее (Рис. 4):

.param__prop,
.param__value {
background: #fff;
}
Рис. 4 Все работает

Все бы ничего, но, как по мне, в будущем от меня будут требоваться лишние действия, такие как сменять цвет фона у ячеек (Рис. 5).

Рис. 5 Упс! У body изменили фон

Полный код:

.param {
margin-bottom: 10px;
}
.param:after {
content: '';
display: table;
clear: both;
}
.param__prop {
float: left;
}
.param__value {
float: right;
}
.param__prop,
.param__value {
margin-bottom: -.31em;
background: #fff;
}

Способ с псевдоэлементом

Заполняем свойство content обычными точками (Рис. 6)

.param:after {
content: '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ';
display: block;
white-space: nowrap;
overflow: hidden;
}
Рис. 6 Все сразу работает

Кажется, что это то, что нужно, никаких операций с отступами и сменой фона, но что если ширина родительского блока будет больше? Или вдруг я захочу другой разделить так называемый dashed, например? Первую проблему можно решить добавив дополнительные точки, а вторую уже никак.

Полный код:

.param {
margin-bottom: 10px;
}
.param:after {
content: '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ';
display: block;
white-space: nowrap;
overflow: hidden;
}
.param__prop {
float: left;
}
.param__value {
float: right;
}

Меня, в принципе, устраивали оба варианта, поэтому я взял и, можно сказать, комбинировал их. (см. UPD 2)

Псевдоэлемент использовал не на родителе, а непосредственно на DOM элементе представляющее свойство. Также задал псевдоэлементу border-bottom с относительным размером границы и его позиционировал абсолютно:

.param__prop {
position: relative;
display: block;
overflow: hidden;
}
.param__prop:after {
content: '';
position: absolute;
bottom: .35em;
width: 100%;
border-bottom: .1em dotted;
}

Так как не указываются свойство left — псевдоэлемент по горизонтали будет позиционироваться автоматически, относительно контента. Для вертикального позиционирования используется bottom с относительными единицами.

Поменял порядок в разметке (см. UPD 3):

<div class="param">
<span class="param__value">2 шт.</span>
<span class="param__prop">Яйцо</span>
</div>
<div class="param">
<span class="param__value">300 гр.</span>
<span class="param__prop">Спагетти</span>
</div>

И оставил выравнивание только у DOM элемента представляющее значение:

.param__value {
float: right;
}

Полный код (с некоторыми дополнениями) с демонстрацией:

Живой пример на codepen

В общем в итоге получил то, что хотел. Хочешь меняй цвет фона, хочешь меняй размер шрифта, хочешь выводи на Smart TV, чтобы бедный обладатель сего вертел головой, чтобы приготовить себе Карбонару (см. UPD 4, UPD 5):

Дополнительные материалы:

UPD:

  1. Это называется “Отточие” (спасибо Lynn «Кофеман»).
  2. Как заметил Dmytro Skliarov, у моего решения есть существенный минус — из-за неправильного порядка нельзя выделить список.
  3. Вместо тегов <div> и <span> лучше использовать тройку <dl>, <dt>, <dd> для семантики и доступности (спасибо Misha).
  4. Данное решение не покрывает кейса, когда название занимает больше одной строки.
  5. Если Вам не важна поддержка старых браузеров, то лучше использовать flexbox для решения данной задачи. Для примера можете посмотреть комментарий Ярослава Фролова (Yaroslav Frolov).

--

--