?

Log in

No account? Create an account

Старинная типография на новый лад - Ваши рубидии уже у кобальта во ртути

Jan. 11th, 2017

02:55 pm - Старинная типография на новый лад

Previous Entry Share Next Entry

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

Идея в том, чтобы "поднять" очередную строку до уровня предыдущей. Ну хорошо, пишем себе

<pre>
Мой тятя дядя самых честных правил
<div style="margin-top: -1em; margin-bottom: -1em;">    xxxx</div>
Когда не в шутку занемог...
</pre>

и получаем убожество: херы оказываются ниже, чем надо.

А всё потому, что интерлиньяж (line-height) по умолчанию равен не 100% текущего кегля (font-size), а "roughly" 120% (поищите "css default line height" - убедитесь), да еще и зависит от браузера и шрифта, поэтому хоть и выходит похоже на правду, если написать -1.2em или даже -1.25em, но делать так будет браузеро-зависимо, да и попросту хочется один и тот же CSS-элемент использовать для наложения строк независимо от текущего интерлиньяжа, который не обязан быть близок к 1.2.

Вот и вопрос: какую магию надо написать, чтобы атрибутам верхней и нижней границы автоматически присваивалось текущее размерное значение line-height с обратным знаком? "Размерное" важно, потому что line-height, наверное, единственный атрибут, который может принимать не только размерные значения (в случае обозначения в процентах - по отношению к унаследованным в рамках DOM), а и безразмерное, что означает требование использовать это значение как кратность по отношению к [максимальному, насколько я понимаю] кеглю, встретившемуся в данной строке текста, каким бы образом кегль ни был установлен. А если вдруг атрибутам границ присвоится 1.2, для них это будет означать просто пиксели, что бесполезно.

Comments:

[User Picture]
From:brmail
Date:January 12th, 2017 12:40 am (UTC)
(Link)
возможно я что-то упускаю, но непонятно зачем полагаться на браузер, что тебе мешает явно задать line-height для того же pre тега, и далее более не беспокоиться?
Или ты просто ищешь более изящное решение?
(Reply) (Thread)
[User Picture]
From:spamsink
Date:January 12th, 2017 01:36 am (UTC)
(Link)
Я ищу общее решение, чтобы один и тот же элемент работал независимо от line-height.
Так-то конечно, можно насоздавать несколько элементов и горя не знать.
(Reply) (Parent) (Thread)
[User Picture]
From:ak_47
Date:January 12th, 2017 12:47 am (UTC)
(Link)
Сразу признаюсь что я не уеб-дезигнер ни разу, и вообще просто погулять вышел. Но по-моему легче всего просто наложить div's друг на друга:
<div>
    <div style='position: absolute; z-index: 1'><pre>test test</pre></div>
    <div style='position: absolute; z-index: 2'><pre>     XXXX</pre></div>
</div>
(Reply) (Thread)
[User Picture]
From:spamsink
Date:January 12th, 2017 01:46 am (UTC)
(Link)
Я не совсем понял, как это работает в общем случае. Если в моем варианте я напишу
CSS:
.overlay { margin-top: -1.2em; margin-bottom: -1.2em; }

HTML:
<pre style="line-height: 1.2;">
FIRST LINE
THIS SHOULD BE          
<div class=overlay>XXXX XXXXXX XX OVERLAID<div>
... несколько раз, если надо много наложений
LAST LINE</pre>


И это преобразование из исходного plain text с маркерами наложения делается тривиально,
то как это будет выглядеть с помощью z-index?

Edited at 2017-01-12 01:47 am (UTC)
(Reply) (Parent) (Thread)
[User Picture]
From:ak_47
Date:January 12th, 2017 02:56 am (UTC)
(Link)
Да, это ни разу не generic solution. Я бы думал в направлении ^H^H^H - тогда всякая высота вообще становится нерелевантна. Только отступаем Х шагов назад, при условии что моно фонт, конечно.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:January 12th, 2017 05:12 pm (UTC)
(Link)
Да, это плодотворная идея; см. ниже.
(Reply) (Parent) (Thread)
[User Picture]
From:ak_47
Date:January 12th, 2017 07:25 pm (UTC)
(Link)
Да, очень хорошо. Я тоже начал экспериментировать со <span> но уже знаний нет как это сделать правильно.
(Reply) (Parent) (Thread)
[User Picture]
From:cema
Date:January 12th, 2017 04:10 am (UTC)
(Link)
Давно это дело не трогал, может тут посмотреть:
https://www.w3.org/TR/CSS2/visudet.html#line-height
https://www.w3.org/TR/CSS2/visudet.html#propdef-line-height
(Reply) (Thread)
[User Picture]
From:yatur
Date:January 12th, 2017 05:18 am (UTC)
(Link)
Вот такое вроде работает:

http://ikriv.com/misc/pushkin.html
(Reply) (Thread)
[User Picture]
From:spamsink
Date:January 12th, 2017 05:02 pm (UTC)
(Link)
Спасибо, но в пределе это требует формирования слоев для всего документа, а хочется преобразовывать текст в HTML построчно.
(Reply) (Parent) (Thread)
[User Picture]
From:yurikhan
Date:January 12th, 2017 05:23 am (UTC)
(Link)

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

<style>
.overlay {
  display: inline-block;
  width: 0px;
  overflow: visible;
}
</style>

<pre>Мой <span class="overlay">хххх</span>тятя дядя самых честных правил</pre>

Небольшими усилиями можно добиться семантической корректности:

<style>
pre del {
  text-decoration: none;
}

pre del::before {
  display: inline-block;
  width: 0px; /* или position: absolute */
  overflow: visible;
  content: attr(data-overlay);
}
</style>

<pre>Мой <del data-overlay="хххх">тятя</del> дядя самых честных правил</pre>

Оба варианта работают с повторным или вложенным наложением:

<pre>Мой <span class="overlay">\\\\</span><span class="overlay">////</span>тятя дядя самых честных правил</pre>
<pre>Мой <del data-overlay="\\\\"><del data-overlay="////">тятя</del></del> дядя самых честных правил</pre>


Edited at 2017-01-12 05:24 am (UTC)
(Reply) (Thread)
[User Picture]
From:spamsink
Date:January 12th, 2017 05:11 pm (UTC)
(Link)
I'm loving it!™
Семантическая корректность, хотя и в другом виде, в моём случае теоретически может быть полезна. Если, скажем, звёздочки сделаны из х и минуса, или неравенство из = и /, то в идеале при copy-paste должны получаться не исходные, а имитируемые символы, заданные в каком-нибудь атрибуте тега.
(Reply) (Parent) (Thread)
[User Picture]
From:yurikhan
Date:January 12th, 2017 05:51 pm (UTC)
(Link)
Для копипейстинга имитируемые символы должны быть реальным текстовым контентом (и их можно спрятать от глаз пользователя разными уловками вида opacity: 0). А вот имитации отлично делать атрибутом, передаваемым в свойство content.
(Reply) (Parent) (Thread)