У меня на сайте текущий пункт меню выделяется жирным. Обычно при таком дизайне возникают прыжки: жирное слово ведь чуть шире обычного, так что при переходах между разделами более правые пункты немного сдвигаются влево-вправо. Бывают редкие «униширинные» шрифты, где разные начертания имеют одинаковую ширину, но не ограничивать же выбор ими.
Когда я открыл новый сайт на прошлой неделе, меню у меня прыгало, потому что я не успел докрутить, а открываться уже было пора. Но надо было решить эту проблему.
Идея решения простая: каждый пункт меню должен всегда занимать столько места, сколько занимал бы, будь он жирным, даже когда на самом деле он не жирный. Но как это сделать?
Можно написать скрипт, который бы как-то незаметно временно рисовал пункты жирными, измерял бы их, а потом жёстко расставлял бы пункты по стабильным позициям. При этом пришлось бы ещё отслеживать адаптивное изменение размеров шрифта при разных ширинах окна и перемерять. Напрограммировать такое с Кодексом — дело минутное, но это тяжеловесно и неэлегантно. Хочется без скрипта.
Можно положить внутрь каждого пункта невидимую жирную копию текста, распорку. Это лишний элемент в разметке, тоже не идеально, но смириться можно. Я не нашёл решения совсем без изменения разметки, но зато нашёл, как обойтись атрибутом, без лишних элементов: слово, жирность которого нужно мерить, ставится в атрибут, а потом в ЦССе делается псевдоэлемент, контент которого берётся из этого атрибута. Так уже неплохо.
Есть и ещё одна есть сложность: у меня же при наведении под пунктом изменяется цвет подчёркивания, и мне надо, чтобы это подчёркивание было ровно по длине пункта. Если же элемент с текстом растянется до ширины его жирной версии, подчёркивание станет торчать правее видимого конца самого текста, что коряво.
Соответственно надо как-то так сверстать, чтобы подчёркнутая часть осталась по ширине видимого текста, а вокруг неё уже была обёртка по ширине жирного текста, которая бы влияла только на лейаут меню. При этом ради Фиттса область нажатия пункта меню у меня дотянута до середины отступа с соседним пунктом. То есть сама ссылка на самом деле больше и чем её обычный текст, и чем её жирный текст. И да, все эти отступы ещё и адаптивятся по-всякому.
С адаптивом есть ещё и такой момент. Когда меню не влезает целиком, важно, чтобы ты хотя бы видел, что какие-то пункты ещё есть за пределами экрана. На сайте Бюро для этого давно работает фокус: если меню не влезает полностью, то расстояния между пунктами подкручиваются так, чтобы последний пункт гарантированно обрезался краем экрана, и тем намекал на продолжение. Это я тоже к запуску сделать не успел, но хотел.
В общем, теперь всё распутал: атрибут, используемый ЦССом для измерения жирного текста, стоит у обёртки, а сам текст пункта меню стоит у элемента внутри. Любой пункт можно делать и жирным, и обычным, и подчёркивание при наведении всегда остаётся ровно под буквами. Кликать можно в отступ между пунктами, и ничего никуда не прыгает при переключении. Жирность как бы переезжает с пункта на пункт при переключении, но каждый из них остаётся на своём месте. И расстояние между пунктами растягивается так, чтобы всегда было видно, что есть ещё пункты за краем. Красота!