- PVSM.RU - https://www.pvsm.ru -
Каждый знает что такое тултип [1]. Кто-то находит их крайне полезными, а кто-то обходит стороной. Судьба предрешила отнести меня к первой категории.
На разработку собственного варианта подсказок меня натолкнул Tipsy Tooltip [2] используемый в Twitter Bootstrap. По началу я пользовался им, но все возможности плагина мне были не нужны и, будучи перфекционистом, лишний код смущал естество. Решил: напишу-ка я то, что нужно мне и ни строчкой больше. Написал и осмеливаюсь поделиться рецептом с сообществом. Авось кому-то приглянется…
Замечу, что идея не нова и схожая реализация, скорее всего, существует. По-этому, если вы уже съели парочку тутлтипов и не хотите более, откажитесь от прочтения данного рецепта, ведь он — лишь урок, главная мораль которого: код, используемый на фронтенде, должен использоваться, а не попросту отдаваться клиенту.
Тесто мы готовим часто и рецепт знаем на зубок — на этом этапе проделаем рутинную операцию: создадим HTML разметку со ссылками, каждая из которых будет иметь подсказку и, отличное от предыдущего, направление:
<section>
<div>
<a href="#" data-tooltip="nw" data-title="This is an example of Northwest gravity">Northwest</a>
</div>
<div>
<a href="#" data-tooltip="north" data-title="This is an North gravity">North</a>
</div>
<div>
<a href="#" data-tooltip="ne" data-title="This is an example of Northeast gravity">Northeast</a>
</div>
<div>
<a href="#" data-tooltip="west" data-title="This is an example of West gravity">West</a>
</div>
<div>
<h3>simpleTooltip</h3>
</div>
<div>
<a href="#" data-tooltip="east" data-title="This is an example of East gravity">East</a>
</div>
<div>
<a href="#" data-tooltip="sw" data-title="This is an example of Southwest gravity">Southwest</a>
</div>
<div>
<a href="#" data-tooltip="south" data-title="This is an example of South gravity">South</a>
</div>
<div>
<a href="#" data-tooltip="se" data-title="This is an example of Southeast gravity">Southeast</a>
</div>
</section>
Элементу, который должен иметь подсказку, необходимо присваивать два атрибута:
Итак, у нас готово восемь основ для будущего блюда. Каждую мы по-своему приправили и теперь самое время заняться приготовлением начинки.
Начинка должна быть вкусной, и по-этому мы не будем использовать никаких примесей и вредных веществ. Только, как его иногда называют, натурпродукт — pure CSS. Нам понадобятся псевдоэлементы :before
и :after
, селекторы атрибутов с модификаторами начала и конца строки (^
, $
) и CSS функция attr() [3]. Убедившись в наличии ингредиентов можно приступать к готовке.
Мы ведь не хотим поедать дурно пахнущие тултипы? Точно не хотим и, по-этому, сразу говорим себе: никаких магических чисел — только обоснованный и осмысленный код.
#tooltip_width {
float:left;
}
#tooltip_width, [data-tooltip]:before, [data-tooltip]:after {
display:none;
font:normal 11px/24px Arial;
}
[data-tooltip]:before, [data-tooltip]:after {
position:absolute;
z-index:1000;
}
[data-tooltip]:before {
content:attr(data-title);
color:#fff;
padding:0 5px;
border-radius:2px;
background:rgba(0,0,0,.8);
text-align:center;
white-space:nowrap;
}
[data-tooltip]:after {
content:'';
height:0;
width:0;
border:solid transparent;
border-width:5px;
pointer-events:none;
}
[data-tooltip]:hover:before, [data-tooltip]:hover:after {
display:block;
}
Псевдоэлемент :after
— декоративная стрелка-указатель на родителя, :before
— тело тултипа с текстом. И вот еще что: вы точно заметили правила для элемента с #tooltip_width, но понятия не имеете зачем он нужен. Так вот он — это особая присыпка от повара и нужна она для измерения ширины подсказки. Изначально, на этапе составления представления о будущем блюде, планировалось рассчитывать ширину по формуле:
width = text.length * 5; // кол-во символов умноженное на среднюю ширину одного из них (Arial, 11px)
Но такой подход был обречен по двум причинам:
iii
" не будут равны "WWW
" по ширине.
Новый метод, учитывающий все особенности, работает следующим образом: текст подсказки помещается в невидимый, плавающий (float:left
), блок с идентичными настройками кегля шрифта, затем измеряется его ширина и он удаляется из DOM, позволяя, тем самым, получить ширину следующего тултипа при помощи этого же элемента.
Хороший выбор для группировки свойств. Можно обойтись и без них, как и кушать суп/борщ без хлеба, но все-таки с ними будет вкуснее.
Названия направления, такие как: nw и ne начинаются с латинской буквы n и имеют общие свойства — это играет нам на руку и мы можем описать их правила в таком виде:
[data-tooltip^=n]:before, [data-tooltip^=n]:after {
top:100%;
}
[data-tooltip^=n]:before {
margin-top:5px;
}
[data-tooltip^=n]:after {
margin-top:-5px;
border-bottom-color:rgba(0,0,0,.8);
}
Помним, что в псевдоэлементе :before
располагается текст, а :after
выступает декоративным указателем. Данный код работает для направлений nw, ne и north и смещает псевдоэлементы на 100% вниз: текст смещается еще на 5px ниже (5px — высота и половина ширины указателя), а стрелка настолько же выше — это позволяет «примагнитить» ее к телу тултипа.
Синяя линия — top:100%
, красная — margin-top:5px
.
Тоже самое и для sw, se и south, только смещение направлено вверх:
[data-tooltip^=s]:before, [data-tooltip^=s]:after {
bottom:100%;
}
[data-tooltip^=s]:before {
margin-bottom:5px;
}
[data-tooltip^=s]:after {
margin-bottom:-5px;
border-top-color:rgba(0,0,0,.8);
}
Как вы уже догадались, все названия для направления смещения подобраны так, чтобы их можно было легко объединять в группы. Давайте теперь опишем общие стили для nw, ne, sw, se, north и south с применением модификатора конца строки:
[data-tooltip$=w]:before, [data-tooltip$=w]:after, [data-tooltip$=th]:before, [data-tooltip$=th]:after {
left:50%;
}
[data-tooltip$=w]:before {
margin-left:-15px;
}
[data-tooltip$=w]:after, [data-tooltip$=th]:after {
margin-left:-5px;
}
[data-tooltip$=e]:before, [data-tooltip$=e]:after {
right:50%;
}
[data-tooltip$=e]:before {
margin-right:-15px;
}
[data-tooltip$=e]:after {
margin-right:-5px;
}
Синяя линия — right:50%
, красная — margin-right:-5px
, зеленая — margin-right:-15px
.
Теперь опишем поведение для двух оставшихся направлений — east и west:
[data-tooltip$=st]:before, [data-tooltip$=st]:after {
bottom:50%;
}
[data-tooltip$=st]:after {
margin-bottom:-5px;
}
[data-tooltip$=st]:before {
margin-bottom:-12px;
}
[data-tooltip=west]:before, [data-tooltip=west]:after {
left:100%;
}
[data-tooltip=west]:before {
margin-left:10px;
}
[data-tooltip=west]:after {
margin-right:-10px;
border-right-color:rgba(0,0,0,.8);
}
[data-tooltip=east]:before, [data-tooltip=east]:after {
right:100%;
}
[data-tooltip=east]:before {
margin-right:10px;
}
[data-tooltip=east]:after {
margin-left:-10px;
border-left-color:rgba(0,0,0,.8);
}
В вышеуказанном коде может показаться странным следующий код: margin-bottom:-12px;
. Отвечает он за смещение половины тела подсказки вверх. Почему 12 — половина? Потому что в самом начале мы указали высоту строки равной 24px при помощи следующего правила:
font:normal 11px/24px Arial; // обычное начертание Arial размером в 11px и высотой строки в 24px
Синяя линия — bottom:50%
, красная — margin-bottom:-5px
, зеленая — margin-bottom:-12px
.
Работа кипит: тесто набухло и ждет подоспевшую вовремя начинку. Бросаемся фаршировать и вспоминаем о присыпке без которой выглядеть наше блюдо будет не эстетично.
По большому счету, тултипы можно нафаршировать и съесть уже сейчас, но перед тем как это сделать, вам нужно кое-что знать:
white-space:nowrap
;position:static;
), которое имеют все элементы без определенного правила position
, то подсказка не будет работать должным образом т.к. она позиционируется абсолютно элемента;Исходя из этого, вы можете не использовать JavaScript тогда, когда уверены что:
А иначе, вот вам присыпка:
/**
* @max (int) максимальная ширина подсказки.
*/
(function(){
$.simpleTooltip = function(a){
var max = a ? a : 300, body = $('body');
$('[data-tooltip]').each(function(){
t = $(this);
/**
* Все элементы, обладающие подсказкой, получают относительное позиционирование,
* но только в тех случаях, когда не используется абсолютное.
*/
t.css('position') == 'static' ? t.css('position', 'relative') : !1;
}).on('mouseenter mouseleave', function(e){
if (e.type == 'mouseenter') {
t = $(this);
/**
* При наведении мыши на элемент с подсказкой его текст помещается в плавающий блок
* и затем измеряется его ширина которая будет равна ширине подсказки.
*/
body.append('<div id="tooltip_width">'+ t.data('title') +'</div>');
width = $('#tooltip_width').width(), styles = '';
/**
* Если ширина больше максимальной, то подсказка будет иметь ширину @max и получит
* особое форматирование текста.
*/
if (width > max) {
width = max,
styles = '[data-tooltip]:before{
width:'+ width +'px;text-align:left;line-height:17px;padding:2px 5px;white-space:normal
}';
}
/**
* Если подсказка направлена на юг или север, то она будет центрироваться таким образом:
* к ширине прибавляются боковые значения padding и вычитается половина, на которую и
* будет смещена подсказка относительно центра элемента, которому она дана.
*/
if (t.data('tooltip').slice(-2) == 'th') {
styles += '[data-tooltip$=th]:before{margin-left:-'+ ((width + 10) / 2) +'px}';
}
/**
* Если один из предыдущих, или оба, шагов пройдены, то в DOM будут добавлены стили
* подсказки для конкретного элемента. Иначе, если ширина меньше максимальной и
* направление не южное или северное, то работа плагина закончится.
*/
if (styles) body.append('<style id="tooltip_style">'+ styles +'</style>');
} else $('#tooltip_style, #tooltip_width').remove();
});
};
})(jQuery);
$(document).ready(function(){
$.simpleTooltip();
});
Единственно возможным аргументом функции может быть максимальная ширина, определяющаяся в пикселях и для всех подсказок. Задается она таким образом:
$.simpleTooltip(400); // аргумент функции, 400 в нашем примере - максимальная ширина для всех тултипов.
Что касается этапов работы плагина, то они описаны в комментариях к коду и, надеюсь, доступным языком.
* — в исходных файлах есть corners.htc, который заставит старые версии браузера от MS закруглять углы, но размер данного файла равен 4Кб, что на 1Кб больше размера файлов всего проекта без него.
Блюдо готово. Оно не экстравагантно и не эксцентрично. Это обыденная пища со своими преимуществами и недостатками и только вам решать чем отужинать. Но заметьте: не попробовав и не узнаешь нравится тебе что-то иль нет.
Надеюсь, что рецепт не был слишком сложным и каждому пункту дано предельно ясное описание. Но, в любом случае, вопросы не возбраняются.
Употребляйте на здоровье!
Автор: yourway
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/css/37694
Ссылки в тексте:
[1] что такое тултип: http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B4%D1%81%D0%BA%D0%B0%D0%B7%D0%BA%D0%B0
[2] Tipsy Tooltip: http://onehackoranother.com/projects/jquery/tipsy/
[3] CSS функция attr(): http://htmlbook.ru/css/attr
[4] http://firstvector.org/simpleTooltip: http://firstvector.org/simpleTooltip
[5] https://github.com/BR0kEN-/simpleTooltip: https://github.com/BR0kEN-/simpleTooltip
[6] https://github.com/BR0kEN-/simpleTooltip/archive/v1.0.zip: https://github.com/BR0kEN-/simpleTooltip/archive/v1.0.zip
[7] Источник: http://habrahabr.ru/post/185110/
Нажмите здесь для печати.